Draft A
For a 20-person engineering team running eight services, already operating in eight separate repositories, my recommendation is: do not consolidate into a monorepo yet.
The same brief went to 5 models, from $0.00279 a draft to $0.1045 — a 37× price difference at current list rates applied to recorded usage. Read blind, or jump straight to the comparison.
Every other page here tells you what an article costs. None of them tell you what that money buys. So: 5 drafts of a decision piece that has to weigh trade-offs rather than list them, one commission, nothing edited, the model and the price hidden behind a click on each one.
The same 1,500-word comparison piece brief produced 5 drafts ranging from 1,395 to 2,765 words. This is one published run, not a general model ranking. Model identities stay hidden here.
Compare model identities, usage and costs · Read all editorial observations · Understand estimate accuracy
For a 20-person engineering team running eight services, already operating in eight separate repositories, my recommendation is: do not consolidate into a monorepo yet.
You have eight services, twenty engineers, and eight repositories. Someone on your team has read about Google's monorepo and wants to consolidate. Someone else remembers the last migration and has gone quiet in a way that means something.
You have eight services, eight repositories, twenty engineers, and a bad memory of the last time someone said "let's just migrate everything." That memory is doing useful work — it's making you ask what actually changes, rather than what the conference talk promised would change. Here's the honest version.
You’re managing a 20-person engineering team with eight services. Today those services live in eight repositories. You’re contemplating consolidation—not because you’re chasing fashion, but because you want predictable tooling, safer cross-service changes, and fewer duplicated rituals. You’re skeptical of migrations that promise the world and deliver little but churn. This piece takes a stand grounded in concrete mechanics, not slogans: for a team like yours, a well-governed monorepo is the right move, provided you build the right tooling and guardrails. It’s not a glamourous cure-all, but it reduces cross-service friction, clarifies ownership, and unlocks safer, faster evolution across services—if and only if you commit to the right implementation pattern. If you hit the scale where eight general services become a dozen, or if your services drift apart in lifecycle and tech stack, you’ll want to re-evaluate. But at your size and composition, consolidation is a net win with the right guardrails.
You're managing a 20-person engineering team, maintaining eight distinct services, each currently residing in its own repository. The itch to consolidate is understandable, particularly as the team scales and the complexities of coordinating across multiple repositories become more pronounced. However, the memory of past migrations, perhaps less than successful, makes any significant shift a decision to be approached with caution and a healthy dose of skepticism. This isn't about chasing the latest trend; it's about finding a layout that genuinely serves your team's productivity and sanity.
A sample without its brief is unreadable as evidence — you cannot judge a draft without knowing what was asked for. This is the exact prompt every model received, with no other instruction beyond a system line telling it to return the article and nothing else.
Write a 1,500-word comparison article titled "Monorepo vs Polyrepo: Choosing a Repository Layout for a 20-Person Engineering Team".
The reader manages a 20-person engineering team running eight services. They are currently on eight separate repositories and are considering consolidating. They are technical, sceptical of fashion, and have been burned by a previous migration.
Cover:
Requirements:
System prompt: “You are a professional writer producing a draft for an editor. Follow the brief exactly, including its structure and length. Return only the article itself in Markdown — no preamble, no commentary on the brief, no notes to the editor.”
| Draft | Words | vs the 1,500-word commission | Reading time | State |
|---|---|---|---|---|
| Draft A | 2,431 | +62% | ~11 min | Complete |
| Draft B | 1,867 | +24% | ~8 min | Complete |
| Draft C | 1,395 | -7% | ~6 min | Complete |
| Draft D | 2,765 | +84% | ~12 min | Complete |
| Draft E | 1,988 | +33% | ~9 min | Complete |
The at-a-glance row carries no model and no price — that stays behind each draft's reveal. Overshoot is billed at the same rate as the words that were asked for.
GPT-5.5 OpenAI
For a 20-person engineering team running eight services, already operating in eight separate repositories, my recommendation is: do not consolidate into a monorepo yet.
That is not because monorepos are a fad, or because polyrepos are inherently cleaner. It is because, at your current size, the benefits of consolidation are unlikely to outweigh the migration cost, tooling burden, and operational disruption unless you have a very specific kind of pain: frequent cross-service changes that must be made atomically and are currently causing real delivery or reliability problems.
If your main issues are inconsistent CI, duplicated configuration, dependency drift, or awkward local development, a monorepo may solve them — but only by forcing you to build a platform around it. You can often address those same problems more directly while staying polyrepo.
The right question is not “Which layout is better?” The right question is: what work becomes easier, what work becomes harder, and what machinery do you need to make either layout tolerable?
Moving from eight repositories to one repository is not just changing where the code lives. It changes how engineers make changes, how CI decides what to run, how ownership is enforced, how releases are cut, and how dependency changes propagate.
Today, in a polyrepo setup, each service likely has its own repository, CI pipeline, permissions, README, release process, dependency manifest, and deployment configuration. A change to one service usually means one pull request, one pipeline, one deployment. A change affecting three services usually means three pull requests, three pipelines, and coordination across merge order and release order.
In a monorepo, those eight services sit in one repository, usually in separate directories:
/services/billing
/services/search
/services/api
/services/worker
/libraries/auth
/libraries/observability
/tools
The first concrete change is that commits can span services. An engineer can update a shared library and all affected services in one pull request. That is the headline benefit, and it is real.
The second change is that CI must become smarter. In eight separate repositories, CI can be relatively blunt: if the billing repo changes, run the billing tests and build the billing artifact. In a monorepo, a commit may touch one service, five services, shared infrastructure code, or documentation. If every commit runs every test for every service, the team will quickly hate the system.
So you need change detection and a dependency graph. The pipeline must answer questions such as:
That logic has to be built, bought, or maintained through a general build system. Without it, monorepo CI becomes either slow or dangerously incomplete.
The third change is versioning. In a polyrepo world, each service can version independently. Shared libraries may be published as packages, and services choose when to upgrade. In a monorepo, teams often move toward source-level dependency on shared code. That removes package publishing friction, but it also means a change to shared code is immediately visible to all consumers. This is convenient when the change is good and disruptive when it is not.
The fourth change is permissions and ownership. Separate repositories provide a natural boundary. In a monorepo, you need code ownership rules, review requirements, path-based approvals, and conventions about who can change what. Otherwise, consolidation quietly weakens service ownership.
The fifth change is developer workflow. Cloning, searching, grepping, and editing become easier in one sense: everything is in one place. But local setup may become heavier. Engineers need tooling to run only the relevant services, tests, linters, and generators. If every local command assumes the whole company codebase, productivity drops.
The sixth change is migration itself. You need to preserve history, move open pull requests, update CI secrets, rewrite documentation, change deployment paths, adjust automation, retrain engineers, and handle the awkward period where some code has moved and some has not. A repository migration is not a refactor. It is an infrastructure project.
A monorepo wins when the team frequently makes changes that cut across service boundaries and those changes are painful to coordinate in separate repositories.
The strongest case is shared contracts. Suppose you have an API schema, generated clients, shared authentication middleware, common observability code, and several services that must change together. In polyrepo, a typical workflow might require updating a shared package, publishing it, bumping versions in multiple services, opening several pull requests, merging them in order, and deploying carefully. If that happens weekly, the coordination tax is real.
In a monorepo, the same change can be made in one commit. The schema, generated code, services, and tests can be updated together. Reviewers can see the entire blast radius. CI can validate all affected services before merge. That is a genuine advantage.
Monorepos also win when standardisation is more valuable than autonomy. If you want one linting setup, one test runner pattern, one build convention, one dependency update process, and one security scanning policy, a monorepo gives you leverage. You can change the standard once and apply it everywhere.
They also work well when there is a strong platform or build engineering function. The larger and more active the monorepo, the more it depends on tooling: affected-test detection, remote caching, reproducible builds, fast code search, path-based ownership, dependency analysis, and release automation. If your organisation is willing to treat that as product work, the monorepo can become a powerful internal platform.
The condition matters. A monorepo does not automatically create consistency. It creates the possibility of consistency, provided someone builds and enforces the system.
Polyrepo wins when services are independently owned, independently deployed, and do not require frequent atomic changes across boundaries.
For eight services and 20 engineers, that is often the case. A team of this size can still coordinate through conversation, lightweight documentation, and shared conventions. The overhead of multiple repositories exists, but it is usually visible and manageable.
Polyrepo also wins when service boundaries are meant to be real boundaries. If the billing service should not casually reach into the search service’s internals, separate repositories reinforce that separation. The friction is sometimes useful. Publishing a package, versioning an API, and upgrading deliberately can prevent accidental coupling.
Polyrepo is also operationally simpler in several ways. CI configuration can remain service-specific. A failing test in one service does not block unrelated changes elsewhere. Repository permissions are easier to reason about. Deployment pipelines map cleanly to services. New engineers can clone and understand one service without loading the entire system into their head.
It is especially attractive when the services have different technology stacks. If two services are in Go, three in Node, two in Python, and one in Java, a monorepo build system must either support all of them coherently or devolve into a pile of path-specific scripts. Polyrepo lets each service use the tooling that fits it, while still allowing shared organisational standards.
The condition for polyrepo success is discipline around the seams: API contracts, dependency versions, shared templates, and release coordination. If those are neglected, polyrepo becomes eight little kingdoms.
The hidden cost of a monorepo is that it creates a new internal platform, whether you admit it or not.
You will need tooling for path-based CI, affected-service detection, dependency mapping, test selection, local task running, code ownership, and release orchestration. You may need build caching to keep pipelines fast. You will need conventions for directory structure, shared libraries, generated code, environment variables, and service metadata.
Someone must maintain all of this. At 20 engineers, that “someone” is unlikely to be a dedicated build team. It will be your senior engineers, the same people you need shipping product work.
The second hidden monorepo cost is social. Once everything is in one repository, people feel more licensed to make broad changes. Some of that is good. Some of it creates drive-by edits, ownership confusion, and large pull requests that are hard to review. Without strong ownership rules, the monorepo can weaken accountability.
The third cost is failure domain. A broken main branch, a bad shared script, or a CI outage can affect everyone. In polyrepo, one repository’s mess is often contained.
Polyrepo has its own hidden costs. The biggest is duplicated infrastructure. Eight repositories often means eight slightly different CI files, eight dependency update patterns, eight release scripts, and eight interpretations of “how we do logging.” That drift is slow at first, then expensive.
The second polyrepo cost is cross-repo change management. Even a simple shared library upgrade can turn into a spreadsheet: which services have upgraded, which are blocked, which have deployed, and which still use the old API? If no one owns that coordination, old versions linger.
The third cost is discoverability. Engineers may not know that another service already solved a problem. Code search is fragmented. Standards live in memory or scattered READMEs. New hires have to learn the organisation repo by repo.
Neither layout eliminates complexity. They move it. Monorepo centralises complexity in tooling and governance. Polyrepo distributes complexity across repositories and coordination habits.
If you consolidate, assume you need at least the following:
A repository structure standard that every service follows. A way to declare service metadata: owners, language, build command, test command, deploy target, dependencies. CI that detects changed paths and maps them to affected services. A build or task runner that works locally and in CI. Path-based code ownership and required reviews. Release automation that can deploy one service without deploying everything. Dependency update automation that understands shared code. Documentation for how to add a new service.
You do not necessarily need all of that on day one, but if you ignore it, engineers will rediscover the gaps during incidents and blocked releases.
If you stay polyrepo, you still need tooling. You need shared CI templates or generated pipeline configuration. You need a standard service template. You need automated dependency updates. You need contract testing or schema compatibility checks where services interact. You need centralised code search across repositories. You need a way to roll out organisation-wide changes without manually editing eight repos each time. You need documentation that says what belongs in every service.
The important point: polyrepo is not the “no tooling” option. It is the option where tooling is lighter, more federated, and often easier to introduce incrementally.
At 20 people and eight services, polyrepo is still a reasonable default. The team is small enough that coordination can happen directly, and the service count is not high enough to make repository sprawl overwhelming.
The answer starts shifting toward monorepo when three things become true.
First, cross-service changes are frequent. If a meaningful percentage of engineering work requires coordinated pull requests across multiple repositories, the cost of polyrepo becomes structural rather than occasional.
Second, shared code is central to the system. If many services depend on common libraries, schemas, generated clients, and infrastructure modules, source-level coordination becomes more attractive.
Third, you can fund the tooling. A monorepo used by 20 engineers still needs ownership. A monorepo used by 60 engineers needs serious build and developer-experience investment. The larger the team, the less acceptable slow CI, unclear ownership, and flaky global workflows become.
Service count matters too, but not mechanically. Eight services is not many. Fifteen services with similar stacks and heavy shared contracts might justify a monorepo. Thirty services owned by independent teams with stable APIs might still be better as polyrepo. More services increase both the pain of polyrepo drift and the blast radius of monorepo mistakes.
As a rough guide: below ten services, choose monorepo only for clear cross-service workflow pain. Between ten and twenty services, the decision depends heavily on shared code and release coupling. Above twenty services, you need deliberate platform thinking either way; repository layout becomes less important than the quality of the engineering system around it.
For your specific situation — 20 engineers, eight services, currently in eight repositories, sceptical of migration, and previously burned — I would stay polyrepo for now.
But I would not leave the system as-is. I would spend one quarter fixing the problems that are probably making monorepo attractive:
Create a standard service template. Centralise CI patterns so each repository is not hand-maintained. Define required service metadata: owner, runtime, build command, test command, deploy process, dependencies. Add cross-repository code search if you do not already have it. Automate dependency updates. Introduce contract tests for service boundaries. Make shared libraries boring to publish and upgrade. Document the expected shape of a service repository.
Then measure what remains painful.
If engineers are still spending significant time coordinating multi-repo changes, if shared library upgrades still take weeks, or if schema changes routinely require merge choreography across four or five repositories, then revisit consolidation with evidence.
The strongest argument against my recommendation is that staying polyrepo may preserve exactly the coordination pain you are trying to escape. If your eight services are not truly independent — if they are really one product split into eight deployables with constant shared contracts — then polyrepo can become ceremony masquerading as architecture. In that case, a monorepo would let you make coherent changes, review them in one place, and validate the affected system before merge. That is a serious argument.
I would change my recommendation if at least two of the following are true:
Your team makes cross-service changes every week. Shared libraries or schemas are central to development. Version skew between services has caused incidents. Engineers avoid necessary refactors because coordinating repositories is too painful. You are willing to assign real ownership to build and developer tooling. Your services use broadly compatible build and test patterns.
If those conditions hold, consolidate deliberately. Do not “move the repos into one folder” and call it done. Design the monorepo as a product: service metadata, affected CI, ownership rules, release isolation, local workflows, and rollback plans.
If those conditions do not hold, consolidation is likely to be an expensive way to obtain tidier aesthetics. For a 20-person team with eight services, the safer and more productive path is to keep the repository boundaries, reduce the accidental inconsistency around them, and reserve a monorepo migration for when the coordination cost is proven rather than assumed.
Claude Opus 5 Anthropic
You have eight services, twenty engineers, and eight repositories. Someone on your team has read about Google's monorepo and wants to consolidate. Someone else remembers the last migration and has gone quiet in a way that means something.
Here is the position up front: stay on polyrepo, but fix the three things that are actually hurting you. The pain you're feeling is real, but consolidation is an expensive and irreversible answer to a problem that has cheaper answers. I'll explain the conditions under which I'd change that recommendation, and I'll make the strongest case against myself before the end.
Strip away the philosophy and a monorepo is a set of concrete mechanical changes. Five of them matter.
Atomic cross-service commits become possible. Today, changing a shared contract between service A and service B requires two pull requests, coordinated merges, and a deployment order. In a monorepo, it's one commit. This is the single genuine, irreducible advantage, and everything else people claim for monorepos is downstream of it or achievable another way.
Dependency resolution changes from versioning to vendoring. In a polyrepo, service A depends on shared-lib@2.3.1. In a monorepo, service A depends on whatever is on main right now. This is not a small change. It means you cannot have two services on different versions of a shared library, which is the point — but it also means that upgrading a shared library upgrades it for everyone simultaneously, and whoever does that upgrade owns fixing every downstream breakage before they can merge. The "one version" rule is a discipline, not a convenience.
Your CI system stops being able to run everything. With eight repos, each CI run tests one service. With one repo, a naive CI setup tests all eight services on every commit. At twenty engineers pushing maybe forty commits a day, and let's say a six-minute test suite per service, you've gone from four hours of aggregate CI time to thirty-two. You will not accept this for long. So you need selective builds: a system that computes which services a given diff could possibly affect, and runs only those tests. This is the tooling burden, and it is the whole game.
Code ownership moves from repository permissions to file-path rules. GitHub or GitLab repo-level access control disappears. You need a CODEOWNERS file, enforced branch protection that respects it, and a convention for what happens when a change spans two owners. This is a downgrade in enforcement strength — path-based ownership is advisory in a way that repository access isn't — but it's usually acceptable.
Local development changes shape. Cloning becomes cloning everything. At eight services this is probably fine; at eighty it isn't, and you'd need sparse checkouts or a virtual filesystem. Your IDE will index the whole tree. Engineers who previously worked in a 40,000-line repo now work in a 320,000-line one, and their tooling will feel it.
Notice what didn't change: nothing about deployment, service boundaries, or runtime coupling. A monorepo does not make you a monolith and does not force lockstep deploys. That's a separate decision, and conflating the two is the most common error in this discussion.
Monorepos win when cross-cutting change is frequent and expensive. The specific condition: if your team makes changes that span three or more services more than roughly once a week, and each of those changes currently requires a multi-PR dance with a deployment ordering document, the monorepo's atomic commit is worth real money. This is common in teams where the services share a rich domain model, or where there's a shared client library that everything consumes.
The second condition is shared code with tight coupling to consumers. If you have an internal library that changes weekly and has eight consumers, versioning it is pure overhead — you publish a version, then immediately open eight PRs to bump it, and for a month you have eight services running four different versions of the thing. A monorepo collapses that to one commit. If your shared library changes quarterly, none of this matters and semantic versioning works fine.
Third: refactoring at scale. Renaming a concept across the whole codebase is a single grep-and-replace in a monorepo and a two-week project in a polyrepo. How much you care depends on whether you're still discovering your domain model or have settled it.
Polyrepos win when service boundaries are stable and teams are autonomous. The condition here is that a change to service A rarely requires touching service B. If that's true, the coordination costs a monorepo solves aren't costs you're paying.
They also win on blast radius of tooling failure. When your monorepo's build graph tool has a bug, all eight services stop shipping. When one repo's CI breaks, one service stops shipping. With twenty engineers, you probably don't have a dedicated build team, which means the person who fixes the build graph tool is a product engineer with other priorities. Single points of failure are worse when nobody owns them.
And they win on incremental adoption of anything. New language, new test framework, new CI provider, new linter — in a polyrepo you try it in one service. In a monorepo, the tooling is shared, so trying something new means either making it work for everyone or building an exception mechanism.
For monorepos: the real cost isn't the migration, it's the permanent tooling tax. You need selective CI (build or buy), and you need someone who understands it well enough to debug it at 2am. You need a merge queue, because with twenty engineers on one branch, the "my PR passed CI but main is broken" problem goes from occasional to constant — semantic conflicts, where two independently-valid changes break each other, become a weekly event rather than a yearly one.
Less discussed: monorepos make it socially harder to delete things. In a polyrepo, an unused service is an unused repo you archive. In a monorepo, unused code sits in the tree, gets picked up by refactoring tools, breaks builds, and nobody's quite sure who owns removing it.
And: the "one version" rule means the cost of upgrading a dependency is paid by whoever needs it first. The engineer who wants a feature from a new library version must fix every other service that breaks. This is a real disincentive to upgrade, and it produces a codebase that stays on old versions longer than a polyrepo would.
For polyrepos: the costs are more familiar but usually understated. Configuration drift is the big one — eight repos means eight CI configs, eight lint setups, eight Dockerfile conventions, and after eighteen months they've all diverged. Fixing a security issue in a shared pattern means eight PRs. Most teams handle this with a template repo and manual propagation, which works right up until it doesn't.
The second real cost is discovery. New engineers don't know which repo contains what. Cross-repo search is worse than in-repo search in every tool. And you cannot easily answer the question "what calls this function?" across your whole system.
Third, and most corrosive: the dependency graph becomes invisible. With eight repos and semantic versioning, nobody knows which services are running which version of the shared library until something breaks. This is the specific failure mode that pushes teams to monorepos, and it's worth naming precisely because there are cheaper fixes.
Two variables, moving in different directions.
Service count per engineer is the more important one. You have 0.4 services per engineer. That's healthy — two to three people per service, enough that each service has real ownership. The polyrepo overhead per service is roughly fixed, so the total overhead scales with service count, not team size. At eight services, the per-repo tax is annoying. At thirty services with the same twenty people, it becomes untenable, because nobody has time to maintain thirty CI configs and you've drifted into config chaos. The service count threshold where monorepos start winning is somewhere around fifteen to twenty for a team this size.
Team size moves the other way. Below roughly ten engineers, a monorepo is nearly free — you don't need a merge queue, selective CI is optional because you can just run everything, and coordination happens by shouting. Between ten and fifty, you're in the awkward middle: big enough that you need the tooling, too small to have someone dedicated to owning it. Above fifty or so, you have a platform team, and the monorepo's tooling burden becomes someone's job rather than everyone's tax.
You are at twenty engineers and eight services: squarely in the awkward middle on team size, and comfortably below the threshold on service count. This is the worst possible position from which to attempt a consolidation.
Stay on polyrepo. Spend the migration budget on three specific fixes:
Total: two to three weeks. Compare against a monorepo migration, which for eight repos with history preservation, CI rebuild, selective build tooling, and the productivity dip while everyone relearns their workflow, is realistically two to three months of meaningful disruption.
The strongest argument against me: if your team is making cross-service changes constantly — if the multi-PR dance is happening several times a week and it's the thing your engineers complain about most — then my three fixes address the symptoms and not the disease. Atomic cross-service commits cannot be simulated. Automated upgrade PRs still produce a window where services disagree, and if your services are coupled tightly enough that this window causes incidents, you should consolidate now rather than at fifteen services, because migrating later is strictly more expensive. Migration cost scales with repo count and history size, and both only go up.
So: instrument first. Count, over the next month, how many changes required coordinated PRs across two or more repositories. If that number is above one per week per engineer, consolidate. If it's below, fix the three things and revisit when you hit fifteen services or your first dedicated platform hire, whichever comes first.
The team that got burned by the last migration is right to be sceptical. The question isn't whether monorepos work — they demonstrably do at scale. It's whether the specific pain you have is the pain they solve, and whether you have the tooling capacity to pay their rent. At eight services with twenty people and no platform team, I don't think you do yet.
Claude Sonnet 5 Anthropic
You have eight services, eight repositories, twenty engineers, and a bad memory of the last time someone said "let's just migrate everything." That memory is doing useful work — it's making you ask what actually changes, rather than what the conference talk promised would change. Here's the honest version.
"Monorepo" is not a philosophy, it's a set of concrete changes to how your systems operate. Four of them matter more than the rest.
CI stops being one pipeline per repo and becomes one pipeline that has to figure out what changed. Right now, a push to payments-service triggers payments-service's CI, full stop. In a single repo, a push touching one directory can't be allowed to rebuild and redeploy all eight services — that's an immediate five-to-ten-minute wait tax on every commit, and it gets worse as you add services. You need path-based triggering: CI reads the diff, determines which service directories changed, and runs only those pipelines. At eight services this is buildable in an afternoon with basic path filters in your CI config. It stops being trivial once your services share internal libraries, because now you also need to know that a change to libs/auth should trigger every service that depends on it — which means either maintaining a manual mapping or building a real dependency graph. That graph is the actual "monorepo tooling" people are alluding to when they mention Bazel, Nx, or Turborepo. You don't need one of those at your scale, but you do need to decide, honestly, who owns the path-filtering config and what happens when it's wrong and something doesn't rebuild that should have.
Versioning of internal dependencies changes shape. Today, if payments-service depends on your internal auth library, that dependency is almost certainly a published package pinned to a version number, bumped via a PR in each consumer. In a monorepo, that dependency usually collapses to a file path — everyone builds against the current version of auth, always. This eliminates an entire category of "which repo is on which version of the library" bugs, but it also means a bad change to auth can break all eight services in the same commit, immediately, with no version boundary to slow it down.
Access control and ownership move from the repo boundary to the directory boundary. You lose the ability to say "contractor X can only see repo Y" via GitHub/GitLab permissions. You gain (if you set it up) CODEOWNERS-style rules that require the payments team's approval on payments changes regardless of who opens the PR. This is usually a net improvement for a 20-person team, but it's not free — someone has to write and maintain those rules, and someone has to enforce that people don't route around them.
Local developer experience changes for better and worse simultaneously. One clone, one set of dotfiles, one place to grep across all eight services — genuinely useful when you're 20 people who all touch multiple services in a given month. The cost shows up later: IDE indexing time, checkout size, and the fact that a repo-wide git blame or CI status page now has noise from services you don't own.
None of this is exotic. All of it is work. The question is whether the work is worth it for you specifically.
Monorepos win when cross-service changes are routine rather than exceptional. If your typical sprint includes a change that touches an internal library and two or three of the services that consume it, a monorepo turns that into one PR, one CI run, one atomic merge. In a polyrepo setup, the same change is three or four PRs, opened separately, merged in some order you have to remember, with a window in between where the library and its consumers are out of sync. If that window is rare for you, this advantage is theoretical. If it happens weekly, it's real money.
Polyrepos win when your eight services are eight services in name only — different languages, different release cadences, different owning teams with little shared code and little reason to ever touch each other's directories in the same PR. A Python data pipeline, a Go ingestion service, and a Rails admin panel gain almost nothing from living in the same repository; they gain independent CI, independent access control, and the ability for one team to move fast without a broken build in an unrelated service blocking their deploy. Polyrepos also win cleanly when a service has a different lifecycle than the rest — it's getting spun out, sold, open-sourced, or handed to another org. Repo boundaries map naturally onto legal and organizational boundaries; monorepo boundaries don't.
The pitch for monorepos rarely mentions that someone now owns the build graph as a permanent, load-bearing piece of infrastructure. Path-filtering CI is easy to write and easy to get subtly wrong — a shared config file that isn't in anyone's dependency list, a service that imports another service's code directly instead of through the shared library, a rename that silently breaks the mapping. That ownership doesn't go away after the migration; it's a new, ongoing job, even if it's a small one. The pitch also undersells blast radius: a broken shared library now blocks every team simultaneously, and without branch protection and required checks that are actually enforced, one careless merge stalls twenty people instead of five.
The pitch for polyrepos, in turn, rarely mentions the dependency version treadmill. Eight repos with a shared internal library means someone is perpetually opening PRs to bump that library's version across all eight, or worse, nobody is, and you discover the drift during an incident. It also rarely mentions the duplicated tooling problem directly: eight .github/workflows files, eight linter configs, eight Dockerfiles that started identical and are now subtly different, each one a small trust erosion. Fixing that without a monorepo means building and maintaining a template-sync mechanism of your own — which is real tooling debt, just distributed instead of centralized. And nobody mentions that the migration cost itself — rewriting or preserving history, moving secrets and deploy configs, updating every link in every ticket that references a commit — is nontrivial in either direction, which is presumably part of what burned you last time.
Team size and service count don't shift the answer on their own; the ratio between them does, along with how correlated your services actually are. At 2.5 engineers per service, as you have now, coordination overhead — version bumps, config drift, choreographed multi-repo PRs — tends to cost more than it would at, say, five engineers per service, because there's less slack to absorb it. As service count grows faster than headcount, the case for a monorepo strengthens, because shared code grows relative to team size and cross-cutting changes become more frequent, not less. Conversely, if your team is about to split into genuinely autonomous squads with independent roadmaps and release trains — or if any of your eight services is a spinout candidate — the case weakens sharply, monorepo tooling investment included.
For a 20-person team running eight services that you're already considering consolidating, I'd move to a single repository. At your scale, the tooling burden is real but small — path-based CI triggers and a CODEOWNERS file, not a bespoke build system — and the coordination costs of eight separate repos, which you're presumably already feeling or you wouldn't be asking, tend to outweigh it. Keep deploys independent per service; a monorepo is a source-control decision, not a deployment one, and conflating the two is the most common way this goes wrong.
The strongest argument against this: if your eight services don't actually share code, teams, or release cadence — if they're eight services in company only — you'd be paying a real migration cost, informed by a prior bad experience, for a benefit that mostly doesn't apply to you. Before committing, count how many PRs in the last quarter touched more than one service. If it's under roughly a quarter of them, don't migrate — fix the polyrepo pain you actually have, with a shared CI template and an automated dependency-bump bot, and revisit this in a year.
GPT-5 nano OpenAI
You’re managing a 20-person engineering team with eight services. Today those services live in eight repositories. You’re contemplating consolidation—not because you’re chasing fashion, but because you want predictable tooling, safer cross-service changes, and fewer duplicated rituals. You’re skeptical of migrations that promise the world and deliver little but churn. This piece takes a stand grounded in concrete mechanics, not slogans: for a team like yours, a well-governed monorepo is the right move, provided you build the right tooling and guardrails. It’s not a glamourous cure-all, but it reduces cross-service friction, clarifies ownership, and unlocks safer, faster evolution across services—if and only if you commit to the right implementation pattern. If you hit the scale where eight general services become a dozen, or if your services drift apart in lifecycle and tech stack, you’ll want to re-evaluate. But at your size and composition, consolidation is a net win with the right guardrails.
Transitioning from eight repos to a single, monorepo is not just “one repo, one feel.” It reorganizes the mechanics of how you build, test, and release across all eight services, while preserving service boundaries in code structure and ownership.
Monorepo (the recommended default for you, given your team size and service count) shines when these conditions hold:
However, monorepo only wins under conditions where you invest in the tooling that makes it safe and fast. The big caveat is build times and governance: if you don’t implement incremental builds, robust caching, and clear contracts, you’ll trade a little extra coordination for a lot of wasted time.
Polyrepo (the alternative) wins when:
Your eight-service, 20-person setup sits in the sweet spot for monorepo as the default. The strongest counterargument—the blast radius and the risk of slower iteration if the tooling isn’t strong enough—has to be mitigated by investing in a good monorepo toolchain and disciplined engineering practices.
There’s no free lunch in this space. You’ll pay a price for either choice, and the pain points aren’t always obvious until you’re in the middle of a migration or a growth spike.
Costs of monorepo
Costs of polyrepo
In both modes you must invest in robust testing culture, but the form of that testing changes: monorepo emphasizes cross-service integration tests and end-to-end scenarios; polyrepo emphasizes formal API contracts and heavyweight consumer-driven tests to capture cross-repo expectations.
Size and scope clearly tilt the balance. Your 20-person team with eight services already leans toward a monorepo, but you’re not a tiny shop, either. The tilt becomes sharper as you add people and services, and the reasons evolve.
In short: for your current footprint, monorepo is the ally of cohesion and coherent evolution. If you double the team, or service count grows into the mid-teens with hard boundaries around lifecycles and languages, re-evaluate the balance and potentially reintroduce polyrepo patterns where they serve autonomy better than speed.
Recommendation: move to a disciplined monorepo with staged consolidation, guarded by a robust tooling stack and a clear governance model. Do not treat this as a one-off migration; treat it as a multi-quarter program with measurable milestones.
What to build or buy (tooling burden)
Strongest argument against your own recommendation—and how you address it
The loudest counterargument is: a monorepo concentrates risk. If something goes wrong in one service, the entire codebase risks destabilization, and a single bad change can ripple through dozens of services. It’s a fair concern when tooling and governance aren’t tight. My counterpoint is threefold:
If you maintain a rigorous approach—contract-first design, strong tests, feature flags, and a reliable build-and-test cache—the blast-radius concern becomes a risk you can manage, not an inevitability you must live with.
Closing note on your path
With eight services and a 20-person team, consolidation offers concrete benefits: fewer duplicated rituals, more predictable cross-service changes, and a cohesive governance model. The key is not to pretend “monorepo solves everything” but to design the monorepo with a disciplined toolchain and explicit contracts. If you hit scale with more services or teams becoming more autonomous, re-evaluate to ensure you’re not trading velocity for centralization too aggressively.
If you pursue this path, start with a staged migration: pick a couple of services with shared dependencies to move first, implement the core tooling, and establish governance before porting the rest. Measure weekly cycle time, PR-to-merge time across the set, and the rate of cross-service regressions. If those metrics improve after the first stage, continue; if they stall, re-check the governance and tooling assumptions. And if you eventually find that the eight-service, multi-team dynamic has matured into a broader ecosystem with divergent lifecycles and tech stacks, you’ll want to re-open the polyrepo option—not as a retreat, but as a refinement guided by data and experience.
Gemini 2.5 Flash Google
You're managing a 20-person engineering team, maintaining eight distinct services, each currently residing in its own repository. The itch to consolidate is understandable, particularly as the team scales and the complexities of coordinating across multiple repositories become more pronounced. However, the memory of past migrations, perhaps less than successful, makes any significant shift a decision to be approached with caution and a healthy dose of skepticism. This isn't about chasing the latest trend; it's about finding a layout that genuinely serves your team's productivity and sanity.
Let’s cut through the architectural philosophy and look at the concrete changes, the genuine wins, the hidden costs, and ultimately, what makes sense for your specific context.
Moving from eight polyrepos to a single monorepo isn't just about dragging folders into a new root directory. It's a fundamental shift in how your team interacts with its codebase, impacting nearly every aspect of the development lifecycle.
service-a.git, service-b.git, you now have your-org/monorepo.git containing /services/service-a, /services/service-b, and potentially /shared/libraries. This means a single git clone gets you everything.Service A depends on Library X, Library X must be independently versioned, packaged (e.g., as an NPM package, Maven artifact, Python wheel), published to a package registry, and then consumed by Service A using its semantic version. In a monorepo, Service A can simply import Library X as a local path: /shared/libraries/library-x. This eliminates the overhead of publishing, versioning, and coordinating updates for internal dependencies. Your IDE now understands these local references, making navigation and refactoring seamless.git grep the entire codebase or browse related services without cloning multiple repositories.Both approaches offer compelling advantages under the right conditions.
A Monorepo Genuinely Wins When:
A Polyrepo Genuinely Wins When:
Both repository layouts come with trade-offs that are rarely discussed in introductory comparisons.
Monorepo's Hidden Costs:
blame or log might take longer without sparse checkouts or shallow clones configured. This can be mitigated, but it requires active management.services/service-a), you might need to layer additional tooling or hooks on top of your VCS, which adds complexity.Polyrepo's Hidden Costs:
The optimal repository layout is highly sensitive to the scale of your operation.
As your team size and service count increase, the arguments for a monorepo become stronger, primarily because the costs of coordination and consistency in a polyrepo grow exponentially. Conversely, shrinking these numbers would likely favor a simpler polyrepo approach.
For your 20-person team maintaining 8 services, the recommendation is clear: embrace a managed monorepo.
Your current setup of 8 separate repositories is likely already causing friction around internal dependency management, inconsistent tooling, and the impossibility of atomic changes across services. These are the very problems a monorepo is designed to solve at your scale. The coordination overhead for 20 engineers working across 8 distinct deployment units, each potentially with its own versioning and release schedule for shared components, is a significant drain on productivity.
A monorepo will simplify your internal dependency graph, making it trivial to update a shared library and its consumers in a single commit. It will foster standardization, allowing your team to establish common build processes, linters, and deployment patterns. Crucially, it enables atomic changes, preventing the integration headaches that plague polyrepo teams trying to coordinate multi-repository releases.
Acknowledging the Strongest Argument Against This:
You've been burned by a previous migration, and the thought of another complex shift is naturally daunting. The strongest argument against my recommendation isn't the philosophy of the monorepo itself, but the pain of implementing it poorly. An unmanaged monorepo, without the necessary investment in tooling for intelligent change detection and efficient CI/CD, is indeed a nightmare. It becomes a slow, monolithic beast that grinds productivity to a halt. This is precisely why the "managed" aspect is paramount. You will need to dedicate engineering effort to selecting, integrating, and maintaining a robust build system and optimizing your CI/CD pipelines for this new structure. This is a non-trivial upfront cost.
Conditions Under Which I Would Change This Recommendation:
While a managed monorepo is generally optimal for your situation, I would reconsider if:
Absent these specific conditions, the benefits of consolidation for your 20-person, 8-service team, particularly in simplifying internal dependency management and enabling efficient cross-service development, strongly lean towards a well-engineered monorepo. It’s an investment, but one that pays dividends in reduced coordination friction and increased developer velocity.
These are the providers' own token counts for the generations above, priced with the same current rate data the calculator uses. Usage is recorded; these dollar amounts are current-rate repricing, not preserved historical invoices. Rates last verified 2026-09-24.
| Model | Usage at current rates | Calculator estimate | Words | Output tokens per word |
|---|---|---|---|---|
| GPT-5 nano Read Draft D | $0.00279 | $0.00146 | 2,765 | 2.51 |
| Gemini 2.5 Flash Read Draft E | $0.0131 | $0.00658 | 1,988 | 2.63 |
| Claude Sonnet 5 Read Draft C | $0.0509 | $0.0189 | 1,395 | 3.59 |
| Claude Opus 5 Read Draft B | $0.0913 | $0.0626 | 1,867 | 1.91 |
| GPT-5.5 Read Draft A | $0.1045 | $0.0968 | 2,431 | 1.41 |
“Calculator estimate” is what this site would have quoted for an article of that length at 1.3 tokens per word. Compare estimated usage with recorded usage on the same current-rate basis before you budget. Each model name links its provider's calculator page; every rate behind these figures is on the full pricing table.
Every model here used more than the 1.3 output tokens per word the calculator assumes — between 1.41 and 3.59. The base estimate understated recorded usage in this run; this observed range is not a universal lower bound or statistical error bar.
The brief asked for 1,500 words. Claude Sonnet 5 came closest at 1,395; GPT-5 nano wrote 2,765 — 84% over. You are billed for the overshoot, and an editor pays for it twice, because cutting is work.
Draft C, Draft D, Draft E used more than two output tokens per written word. Aggregate usage does not tell us how much of that comes from reasoning versus tokenizer differences. Do not infer a reasoning-token breakdown from this ratio alone.
Written 2026-08-24, after reading all 5 drafts of the 2026-08-20 run in full.
Same brief, same facts: Drafts A and B say stay on separate repositories; C, D and E say consolidate. All five argue their position confidently, as the brief demanded. This is the clearest evidence on this site that a model’s conclusion is a draft, not an answer — the judgment call is still yours.
Drafts B and C independently reduce the whole decision to a measurable test: count the changes that span repositories. B’s threshold is more than one coordinated change per engineer per week; C’s is a quarter of all PRs. Everything else in ten thousand words is commentary on that one instrument.
The brief banned pros-and-cons bullet lists as the main structure and vendor recommendations. Draft E structures its middle sections as exactly those lists and names three build tools, twice. Draft C names the same tools once — to tell the reader they are not needed at this scale.
Draft B costs everything it recommends: "half a week of work" for a dependency dashboard, "two to three weeks" of fixes against "two to three months" of migration disruption. That is the framing a manager can actually budget with, and no other draft attempts it.
Draft D runs 2,765 words against the 1,500 commissioned and leaves artefacts in the prose ("runbooks, runbooks for rollbacks"). Its bill also carries reasoning tokens — 2.5 billed output tokens per written word against the 1.3 the calculator assumes.
Each model wrote the brief 3 times. Run 1 is published — a number fixed in the config before the first API call. The other 10 generations are committed to the repository beside these ones, so you can check that the published run is not the flattering one.
This is a single Comparison piece commission. A model that handles it well may handle a technical explainer or a comparison piece differently. Treat this as a sample of house style and competence, not a ranking.
No temperature, no top-p, to anyone. Current Claude models reject them outright, and pinning them for some providers while Claude ran on defaults would be an unfair comparison dressed up as a controlled one. Every model ran on its own defaults.
Providers change what sits behind a model name. These drafts are a claim about 2026-08-20 and nothing else. When they get old enough to mislead, they get regenerated or taken down.
A model that writes a clean how-to may not hold an argument together or get a technical claim right. The same five models wrote these too, under the same rules:
Every draft here is a first draft from a machine that cannot check a fact, has no opinion worth printing and has never met your reader. The gap between the best of these and something you would put your name on is editing — and that cost is not on any pricing page, including ours. What the drafts do tell you is how much editing each one implies, which is the number that actually decides which model is cheapest for you.
Answered from this run's own numbers, not in general.
All five drafts above obeyed the brief's hardest rule — take a position — and then split: two argue one way, three the other, each confidently, from the same brief. That is the finding. A model will commit to a verdict; which verdict you publish is still an editorial decision, and this page is the demonstration.
Not here. The same facts and the same instructions produced opposite recommendations across the five drafts, 4 of which also overshot the commissioned length. If a workflow publishes a model's conclusions unreviewed, this page is the argument for keeping a human who owns the verdict.
Between $0.00279 to $0.1045 for the same commission, using recorded API token counts at current list rates. The gap reflects output length, tokenizer differences and possible reasoning usage rather than quality: the drafts with the highest current-rate cost are not the ones that read best.
You have seen what the drafts look like. The calculator turns that into a monthly bill for your own volume, and the model guide explains where each one earns its price.