â—† AI Article Pricer Compare AI article generation costs
Comparison piece · generated 2026-08-20 · unedited

Can an AI Write a Comparison Article? Read Five and Decide

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 original drafts are unedited No typo fixed, no preamble trimmed, no generation re-rolled. Raw output as it came back from each API on .
What this experiment shows

The findings before the full drafts

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.

  • The five drafts reach opposite verdicts. 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.
  • The most useful idea appears twice, with numbers. 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.

Compare model identities, usage and costs · Read all editorial observations · Understand estimate accuracy

Compare the opening paragraph of each draft (blind)

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.

Draft B

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.

Draft C

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.

Draft D

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.

Draft E

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.

The commission

Comparison / decision

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.

Read the full brief every model was given

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:

  1. What actually changes when you consolidate — the concrete mechanics, not the philosophy
  2. Where each layout genuinely wins, with the conditions that make it win
  3. The costs nobody mentions, for both options
  4. What team size and service count shift the answer, and in which direction
  5. A recommendation for this specific reader, with the conditions under which you would change it

Requirements:

  • Take a position. A comparison that concludes "it depends" without saying what it depends on has failed
  • Be specific about tooling burden — say what has to be built or bought
  • Acknowledge the strongest argument against your own recommendation
  • No vendor recommendations
  • Do not use a pros-and-cons bulleted list as the main structure

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.”

Blind first

5 drafts, in a random order

Read at least two before you reveal anything. Knowing the price changes what you see in the prose — that is exactly the bias this page exists to remove. The letters were assigned from the run's own seed before generation started, so the order is not ours to arrange.
DraftWordsvs the 1,500-word commissionReading timeState
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.

Draft A

2,431 words

Reveal the model and what it cost

GPT-5.5 OpenAI

Recorded usage at current rates
$0.1045
Output tokens
3,435
Tokens per word
1.41
Calculator quoted
$0.0968
Price this model for your own volume →

Monorepo vs Polyrepo: Choosing a Repository Layout for a 20-Person Engineering Team

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.

Read the rest of Draft A

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?

What Actually Changes When You Consolidate

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:

  • Which services are affected by this change?
  • Which tests must run?
  • Which Docker images or deployable artifacts must be rebuilt?
  • Which downstream services need validation because a shared library changed?
  • Can unaffected services be skipped safely?

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.

Where Monorepo Genuinely Wins

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.

Where Polyrepo Genuinely Wins

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 Costs Nobody Mentions

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.

The Tooling Burden You Should Expect

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.

What Team Size and Service Count Shift the Answer

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.

Recommendation for Your Team

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.

Draft B

1,867 words

Reveal the model and what it cost

Claude Opus 5 Anthropic

Recorded usage at current rates
$0.0913
Output tokens
3,564
Tokens per word
1.91
Calculator quoted
$0.0626
Price this model for your own volume →

Monorepo vs Polyrepo: Choosing a Repository Layout for a 20-Person Engineering Team

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.

Read the rest of Draft B

What actually changes when you consolidate

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.

Where each layout genuinely wins

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.

The costs nobody mentions

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.

How team size and service count shift the answer

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.

The recommendation

Stay on polyrepo. Spend the migration budget on three specific fixes:

  1. Build a dependency dashboard. A scheduled job that reads every service's lockfile and reports which version of each shared library each service is running. Half a week of work. This solves the invisible-dependency-graph problem, which is the one that actually hurts.
  2. Automate shared library upgrades. When a shared library publishes, open PRs against all consumers automatically. If CI passes, auto-merge. This gets you most of the monorepo's "everyone on one version" benefit without the atomic commit.
  3. Centralise CI configuration. Move your pipeline definitions into a shared, versioned template that each repo references rather than copies. Kills the drift problem.

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.

Draft C

1,395 words

Reveal the model and what it cost

Claude Sonnet 5 Anthropic

Recorded usage at current rates
$0.0509
Output tokens
5,004
Tokens per word
3.59
Calculator quoted
$0.0189
Price this model for your own volume →

Monorepo vs Polyrepo: Choosing a Repository Layout for a 20-Person Engineering Team

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.

What Consolidation Actually Does, Mechanically

Read the rest of Draft C

"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.

Where Each Layout Actually Wins

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 Costs Nobody Mentions

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.

What Changes the Answer

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.

The Recommendation

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.

Draft D

2,765 words

Reveal the model and what it cost

GPT-5 nano OpenAI

Recorded usage at current rates
$0.00279
Output tokens
6,937
Tokens per word
2.51
Calculator quoted
$0.00146
Price this model for your own volume →

Monorepo vs Polyrepo: Choosing a Repository Layout for a 20-Person Engineering Team

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.

  1. What actually changes when you consolidate — the concrete mechanics
Read the rest of Draft D

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.

  • Boundaries and layout. The monorepo keeps each service in its own directory, but under a common codebase. The top level contains a single package manifest or workspace file that records shared dependencies and per-service metadata. Within the tree, you can still honor service-specific languages, abstractions, and runtimes, but the path to change a shared library or a cross-service utility becomes straightforward and centralized.
  • Dependency management. Shared libraries become first-class citizens in the repo, with a single source of truth for versions. Pinning and updating dependencies across services no longer requires synchronized PRs across independently governed repos. Instead, you update a shared library once, and all services that consume it pick up the change through the consistent dependency graph. You still maintain service-specific dependencies, but there’s less drift in core utilities.
  • Build and test orchestration. The core shift is in how you compute what to build. In a monorepo, you rely on a global build orchestrator that can determine which services were touched by a commit and run incremental builds and selective tests only for those services plus any that are transitively affected. If a change touches a shared library, you wake up all affected services. If it’s completely isolated, you run only the single service’s pipeline. The result is dramatically fewer wasted cycles than rebuilding eight disjoint pipelines.
  • CI pipelines and rollout gates. Instead of eight separate pipelines, you maintain one centralized CI framework that slices work by service boundaries and uses feature flags to gate cross-service behavior. You still get per-service test suites, but you also gain integrated cross-service tests that verify the boundaries you rely on—authentication, authorization, shared data contracts, and so on—without triggering a full-blown, eight-repo coordination dance.
  • Code ownership and reviews. In a monorepo, ownership becomes a lattice rather than a wall. You maintain per-service owners, but with a shared code search index, a single set of lint and test rules, and a unified PR policy for cross-service changes. The governance burden shifts from “do we approve across repos?” to “do we respect service boundaries and the shared contracts?” This is a cultural and procedural shift as much as a tooling one.
  • Release and deployment. Cross-service deployments can be coordinated through a single release calendar and a common versioning approach for shared libraries, but actual deployments remain per-service. You gain the ability to do isolated canary and A/B tests with shared code, because the monorepo makes it easier to align changes, ensure compatibility, and rollback via feature flags rather than by unpicking eight separate histories.
  • Tooling footprint (the needed investments). You don’t just merge code; you must equip the team with a real monorepo toolchain that can (a) derive an exact “affected set” given a change, (b) maintain fast, hermetic builds and tests, (c) provide fast, scalable code search and navigation, (d) enforce access control and code ownership across a single repository, and (e) provide robust metrics and dashboards for cross-service dependencies. In short, you need build caches, a scalable code search index, a dependency graph, and a governance layer that can handle cross-service changes without blowing up.
  • Operational discipline. One repo increases the blast radius of a breaking change unless you impose strict contracts, tests, and staged deployments. You’ll need formalized API contracts, consumer-driven tests, and a robust feature-flag strategy to keep teams from unknowingly coupling services. It’s not doom, but it is a responsibility: your teams must design non-breaking interfaces and maintain backward compatibility.
  1. Where each layout genuinely wins, with the conditions that make it win

Monorepo (the recommended default for you, given your team size and service count) shines when these conditions hold:

  • High cross-service coupling and shared libraries. If your eight services reuse common utilities, data models, or authentication and authorization logic, a single codebase reduces drift and accelerates coordinated changes. When a change to a shared contract touches multiple services, you can implement, test, and release the change in a single place rather than coordinating eight separate repos.
  • Consistent tooling and standards. If you prize uniform linting, testing, and release practices, a monorepo makes enforcement simpler. You get one definition of “done” for changes that affect multiple services and one place to audit for regressions.
  • Coordinated governance and risk management. A monorepo lets you implement centralized scanning, governance, and access controls that apply across services. You don’t fight the friction of cross-repo approvals when a change cascades through several services.
  • Rapid cross-service iteration. When product features require touching more than one service in a single sprint, a mono-repo reduces coordination overhead and the risk that changes drift apart. It’s easier to run cross-service integration tests and to stage release sequences that reflect real user journeys.

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:

  • Autonomy and independence trump shared velocity. If each service evolves on its own cadence, with different release cycles, different languages, or differing security requirements, polyrepo minimizes the blast radius of changes, giving teams the freedom to optimize for their own lifecycles without waiting on others.
  • Distinct security or regulatory boundaries exist. If one service enters a domain with stricter compliance requirements, keeping it isolated helps with access control, auditing, and risk containment. Isolation can also simplify legal and vendor relationships, where different teams own different contracts.
  • Heterogeneous tech stacks are dominant. If some services are Python, others are Go, some rely on different databases or data models, and the teams want to avoid forcing uniform tooling, polyrepo reduces the friction of cross-stack coordination.
  • Velocity at the per-service level matters more than cross-service alignment. In practice, if you measure success by per-service deployment frequency and rollback safety rather than coordinated multi-service launches, polyrepo aligns with that emphasis.

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.

  1. The costs nobody mentions, for both options

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

  • Migration and porting. You must port code, align build scripts, and adjust tests. The first two quarters are heavy on planning, refactoring, and re-architecting shared libraries so that they remain stable across services.
  • Tooling and infrastructure. You’re buying or building a scalable monorepo toolchain: a build orchestrator with incremental builds, a distributed build cache, a code search index that can span the entire codebase, and a dependency graph that can detect transitive effects. You’ll likely invest in a robust CI system that can run thousands of jobs per day with fine-grained dependencies.
  • Governance overhead. Centralized standards require enforceable policies and a process for cross-service changes, including owners for every shared contract. You’ll need runbooks, runbooks for rollbacks, and a way to audit changes across services.
  • Performance risk if not optimized. Without proper caching and selective builds, you’ll run into longer feedback loops that frustrate engineers and slow sprints. This isn’t a one-time cost; it’s a capability that must be sustained.

Costs of polyrepo

  • Tooling duplication. You’ll replicate much of the observability, linting, testing, and release scaffolding for each service. The cost of maintaining multiple pipelines, multiple dependency managers, and multiple code search indices adds up in both time and money.
  • Inconsistent standards. If you haven’t aligned governance across services, you’ll tolerate drift in coding standards, test quality, and release practices. Cross-service changes become fiddly to coordinate and risky to deploy.
  • Cross-service changes become harder. Even with strong automation, you’ll require custom tooling to surface, align, and validate changes that affect multiple services—leading to more complex release planning, more PR coordination, and more inter-team meetings.
  • Fragmented security posture. Isolating services means you replicate security controls, secret management, and audit trails across repos. Ensuring uniform protection becomes more labor-intensive and error-prone if you don’t invest in centralized patterns.

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.

  1. What team size and service count shift the answer, and in which direction

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.

  • When teams approach 30–40 engineers with 12–15 services, the benefits of a unified toolchain and centralized governance grow stronger. The overhead of keeping eight separate pipelines, eight separate test matrices, and eight rings of code ownership becomes a real drag on velocity if you continue to scale. A monorepo with a scalable build cache and a single CI baseline can unlock cohesion across teams and reduce the total effort spent on bor­ing but necessary synchronization tasks.
  • If you cross into a realm where services routinely live on different lifecycles, languages, or data platforms, the balance shifts. If managers begin prioritizing independence—pulling back on shared libraries, allowing each service to own its release cadence, and allowing teams to optimize for their own stack—polyrepo becomes more compelling. The less you share intrinsically, the less you gain from a single codebase.
  • A practical threshold you can monitor: cross-service churn. If more than a third of your active development work regularly touches more than one service, monorepo is likely to yield more benefit than it costs. If the majority of changes stay within a single service and only rare coordinated changes span services, polyrepo keeps things simpler and reduces risk.
  • Language and platform diversity also matter. A monorepo shines when you can unify tooling around a common CI and test strategy, but if every service truly runs in a separate tech stack with bespoke pipelines, the maintenance burden of a single toolchain grows quickly. In your current eight-repo world, you’re not at that extreme yet; the monorepo path remains plausible with disciplined architecture.

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.

  1. A recommendation for this specific reader, with the conditions under which you would change it

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)

  • A scalable build orchestrator. You’ll need to compute the affected set for a change and run incremental builds for only the touched services. It should support transitive dependency analysis, parallel execution, and deterministic caching.
  • A global cache and distributed build system. This is essential to keep feedback loops fast as the repository grows. You’ll want cold-cache resilience and a strategy to invalidate caches when interfaces change.
  • A unified test harness with per-service tests and cross-service integration tests. You’ll want test isolation where necessary, but you must also support end-to-end tests that reflect real user journeys across services.
  • Centralized code search and navigation. Index the entire codebase so developers can answer questions like “where is this contract defined?” or “which services depend on shared data models?” in seconds, not hours.
  • A single, auditable governance layer. This includes a central owners document, a policy for cross-service changes, and a mechanism for cross-service approvals when contracts are affected.
  • Shared libraries and contract management. You’ll need a precise mechanism to version and publish shared libraries, along with clear deprecation paths for breaking changes. This makes it easier to evolve shared code without forcing all services to move in lockstep.
  • Feature flag infrastructure. To reduce blast radius and test across services safely, you’ll implement a robust feature flag system that lets you split deployments and revert risky changes quickly.
  • Observability and release tooling. You’ll standardize metrics, traces, and dashboards demonstrating how a change affects cross-service behavior. You’ll align release calendars and canary strategies to reduce risk.
  • Data contracts and API schemas. A strict schema regime across services matters in a monorepo so that changes don’t surprise dependent services.

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:

  • You design against it. The risk is real, but preventable with a disciplined approach: strict API contracts, consumer-driven tests, and a mature feature-flag strategy. Deployments can be decoupled by gating changes at the surface area of impact, so you don’t force a global release for a small change.
  • You control the blast radius with tooling. A global build cache and selective builds keep feedback fast even as the repo grows. If you implement per-service and cross-service integration tests with clear success gates, you keep the feedback loop tight enough to catch issues early.
  • You gain in visibility and velocity. The ability to coordinate changes across services in a single place often reduces the cumulative lead time for multi-service features. The upfront investment is substantial, but the long-term payoff is a platform that evolves as an integrated system rather than a loose federation of independent repositories.

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.

Draft E

1,988 words

Reveal the model and what it cost

Gemini 2.5 Flash Google

Recorded usage at current rates
$0.0131
Output tokens
5,219
Tokens per word
2.63
Calculator quoted
$0.00658
Price this model for your own volume →

Monorepo vs Polyrepo: Choosing a Repository Layout for a 20-Person Engineering Team

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.

Read the rest of Draft E
The Mechanics of Consolidation: What Actually Changes?

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.

  1. Version Control Structure: Your Git history isn't simply merged. You'd typically re-root each service's history into a subdirectory within the new monorepo. Instead of 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.
  2. Dependency Management (Internal): This is perhaps the most significant functional change. In a polyrepo setup, if 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.
  3. CI/CD Pipelines: Currently, you likely have eight distinct CI/CD pipelines. In a monorepo, these consolidate into a single, more sophisticated system. The key here is change detection. A well-configured monorepo CI/CD pipeline doesn't rebuild or retest everything on every commit. It intelligently determines which services or libraries have been affected by a commit and only runs tests, builds, and deploys for those specific components. This requires more upfront investment in tooling (e.g., using Bazel, Nx, Turborepo, or custom scripting layered on top of Git diffs) but prevents the system from grinding to a halt.
  4. Tooling and Configuration: With polyrepos, each service might drift towards its own linters, formatters, build scripts, and dependency versions. A monorepo naturally pushes towards standardization. You can define root-level configurations for ESLint, Prettier, TypeScript, Dockerfiles, or even a shared base image, which all services inherit. This doesn't mean all services must use the exact same tech stack, but it enables consistent tooling around common concerns.
  5. Code Review and Discovery: Pull requests in a monorepo can span multiple services or shared libraries simultaneously, enabling atomic changes. Reviewers gain broader context, seeing all related changes in one go. For discovery, new engineers can git grep the entire codebase or browse related services without cloning multiple repositories.
The Genuine Wins: Where Each Layout Shines

Both approaches offer compelling advantages under the right conditions.

A Monorepo Genuinely Wins When:

  • Atomic Changes Across Services Are Common: Your team frequently needs to modify a shared library, update an API contract in one service, and simultaneously adjust its consumer in another service. In a monorepo, this is a single commit, a single PR, ensuring consistency and preventing integration issues. This is a strong indicator for your 8-service, 20-person team.
  • Large-Scale Refactoring and Standardization are Valued: Imagine upgrading a core framework or implementing a security patch across all eight services. In a monorepo, this can be done in one swoop, leveraging automated tools and a single testing cycle. Enforcing consistent code styles, build configurations, or deployment practices becomes significantly easier through shared tooling and templates.
  • Internal Dependency Management is a Pain Point: If your team spends significant time managing versions, publishing, and consuming internal libraries across multiple repos, a monorepo is a clear winner. The "local import" model vastly simplifies development, eliminating versioning headaches and allowing for easier local testing of changes to shared components.
  • Enhanced Code Discoverability and Collaboration: Engineers can easily navigate, search, and understand the entire codebase without context switching between repositories. This fosters knowledge sharing and makes it easier for teams to contribute to or understand related services.

A Polyrepo Genuinely Wins When:

  • Services Are Truly Independent with Minimal Shared Code: If your 8 services are completely disparate, written in different languages, deployed to different environments, and rarely interact or share code, the overhead of a monorepo's tooling isn't justified.
  • Strict Ownership Boundaries and Autonomous Release Cycles Are Paramount: If different teams or even individual engineers own services with absolute autonomy, dictating their own tech stack, build process, and release cadence without external dependencies, a polyrepo naturally supports this segmentation.
  • Security or Compliance Requires Absolute Isolation: In certain highly regulated environments, the logical and physical separation of services into distinct repositories might be a non-negotiable requirement for audit trails or access control.
The Unspoken Costs: What Nobody Mentions

Both repository layouts come with trade-offs that are rarely discussed in introductory comparisons.

Monorepo's Hidden Costs:

  • Tooling Burden and Investment: This is the big one. To make a monorepo efficient, you must invest in sophisticated build systems (like Bazel, Nx, Turborepo, or custom scripting) capable of incremental builds, dependency graph analysis, and remote caching. This is a significant engineering effort to build, configure, and maintain, requiring specialized expertise. Without this, your CI times will explode, and developer experience will suffer. It's not a "plug and play" solution.
  • Increased CI/CD Infrastructure Costs: While sophisticated tooling optimizes builds, the sheer volume of code and potential for cross-service changes means your CI/CD infrastructure needs to be robust, scalable, and potentially more expensive to handle the workload.
  • Repository Size and Performance: Over time, a monorepo can grow massive. Initial cloning can be slow. Git operations like blame or log might take longer without sparse checkouts or shallow clones configured. This can be mitigated, but it requires active management.
  • Access Control Granularity: Default Git permissions often operate at the repository level. If you need granular access control (e.g., only Team A can push to services/service-a), you might need to layer additional tooling or hooks on top of your VCS, which adds complexity.
  • Psychological Overhead: For developers, seeing the entire organization's codebase in one place can be intimidating. A broken build in one service can theoretically block others if not properly isolated by the CI system.

Polyrepo's Hidden Costs:

  • Internal Dependency Hell: The most common pain point. Managing internal libraries as external packages leads to versioning nightmares, slow feedback loops (change lib -> publish -> update service -> test), and a proliferation of outdated library versions across services. "Dependency hell" is a real productivity killer here.
  • CI/CD Sprawl and Duplication: Maintaining eight distinct CI/CD pipelines means eight separate configurations, eight sets of secrets, and eight places to update when a standard changes. Duplication is rampant, and consistency is hard to enforce.
  • Onboarding Fragmentation: New engineers need to clone and set up multiple repositories to get a full picture, each potentially with its own unique build and test process. This fragmented setup increases onboarding time and cognitive load.
  • Consistency Drift: Without a centralizing force, each repository naturally diverges in terms of tech stack versions, linting rules, security practices, and deployment mechanisms. This makes cross-cutting concerns (e.g., security audits, framework upgrades) incredibly difficult.
  • Difficulty with Cross-Service Refactoring: You're fundamentally unable to make atomic changes. Refactoring a shared interface requires coordinating multiple PRs, releases, and deployments across different repositories, leading to integration issues and extended rollout times.
Scaling Dynamics: Team Size and Service Count

The optimal repository layout is highly sensitive to the scale of your operation.

  • Small Teams (< 5 people) with Few Services (< 3): At this scale, the overhead of establishing and maintaining sophisticated monorepo tooling often outweighs its benefits. Polyrepo with minimal shared components is perfectly adequate, keeping things simple.
  • Medium Teams (5-50 people) with Moderate Services (5-20): This is the sweet spot where the balance shifts dramatically towards the monorepo. Your 20-person team with 8 services falls squarely into this category. The coordination overhead, internal dependency management, and consistency challenges of a polyrepo begin to genuinely hinder productivity and introduce risk. The benefits of atomic changes and centralized tooling in a monorepo start to provide a significant return on investment.
  • Large Teams (> 50 people) with Many Services (> 20): For very large organizations, a monorepo becomes almost essential to manage complexity. The coordination costs of a polyrepo at this scale are prohibitive, and the benefits of shared infrastructure, tooling, and large-scale refactoring become critical.

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.

Recommendation for the 20-Person Team: Embrace a Managed Monorepo

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:

  1. True Independence Prevails: Your 8 services are genuinely siloed, written in vastly different tech stacks (e.g., C++, Scala, Go, Node.js, Python), have almost no shared code, and absolutely no cross-service dependencies or atomic changes. If they are fundamentally distinct business units with entirely independent release cycles, the consolidation benefits diminish.
  2. No Willingness to Invest in Tooling: If your team or leadership is unwilling to dedicate the necessary engineering time and resources to build out the sophisticated monorepo tooling (incremental builds, change detection, caching), then the costs will outweigh the benefits, and you're better off sticking with the known pains of polyrepo.
  3. Regulatory/Security Mandates Strict Separation: Certain highly regulated industries might have compliance requirements that explicitly mandate independent repositories for auditability or strict access control.

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.

After the reveal

Compare models, recorded usage and current-rate cost

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.

After the blind read

Editorial observations on this run

Written 2026-08-24, after reading all 5 drafts of the 2026-08-20 run in full.

Read the drafts blind first — these notes are spoilers of judgement, if not of identity. Drafts are named by letter only, so the reveal stays yours. The notes are opinion; usage counts are recorded and dollar amounts use current list rates.
Note 01

The five drafts reach opposite verdicts

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.

Note 02

The most useful idea appears twice, with numbers

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.

Note 03

The bans were half-obeyed

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.

Note 04

Only one draft prices its own advice

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.

Note 05

Where the overshoot money went

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.

Method

How this was made, and how it could mislead you

Nothing was cherry-picked

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.

One brief is not a verdict

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 sampling parameters were sent

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.

A model is not a fixed thing

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.

The part this page cannot show

None of these are publishable as they stand

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.

Common questions

What people ask about these drafts

Answered from this run's own numbers, not in general.

Can AI write a comparison article that takes a position?

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.

Do different AI models reach the same conclusion?

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.

What did these comparison drafts cost?

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.

Now put a number on it

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.

Price your own workflow Which model should I use? →