What Changes as the Codebase Grows
Practices that work at ten engineers fail at two hundred, and the transition points are predictable enough to plan for.
Analysis
Most toolchain pain is a practice that was correct at a previous size and was never revisited.
What breaks, and roughly when
Rebuilding everything. Fine when a full build is thirty seconds. Unbearable at ten minutes. The transition happens quietly and the fix — real module boundaries — is much cheaper before than after.
Running the whole test suite on every change. Fine at two minutes, impossible at forty. Selection becomes necessary and it requires the module structure that should have been established earlier.
One shared development database. Fine for five people, a contention problem for fifty.
Manual environment setup. Tolerable when nobody joins, a permanent tax when someone joins monthly.
A single CI configuration file. Manageable at a hundred lines, unmaintainable at a thousand.
Everyone can change everything. Works when everyone knows the codebase; produces accidental coupling when they do not.
Informal ownership. Fine when you can name everyone; produces unowned code as soon as you cannot.
The pattern
Each of these fails through accumulation rather than through an event.
Nobody notices the day the build crossed five minutes. It is noticed a year later when it is fifteen, and by then the fix is a project rather than a configuration change.
Which is the argument for the trend report: the value is catching the crossing while it is still small.
What to put in place early
Cheap when the codebase is small, expensive to retrofit.
Module boundaries, even if the codebase does not obviously need them yet.
Declared dependencies, with cycles failing the build.
Pinned toolchain versions.
A scripted setup path, tested in CI.
Timing telemetry, so the trend exists when you eventually need it.
Ownership recorded somewhere machine-readable.
None of these is urgent at small scale and all are much cheaper then.
The transitions worth planning
Ten to fifty engineers: setup automation, module boundaries, caching.
Fifty to two hundred: test selection, remote caching, a merge queue if merge frequency warrants it, dedicated toolchain ownership.
Beyond that: distributed execution, sparse checkouts, structural work on the graph.
Rough and directional. The trigger is the measurement, not the headcount.
The trigger, stated properly
Blocking pipeline duration crossing the point where people batch changes. Watch pull request size: when it starts rising, feedback has become slow enough to change behaviour.
Rebuild breadth crossing the point where a typical change rebuilds most of the codebase.
Onboarding time crossing a week.
Flake rate crossing the point where retries are the norm.
Any of these is the signal that the current practice has expired, and acting on it is much cheaper than waiting for the complaints.
Watching for the batching signal
The earliest indicator that feedback has become slow enough to change behaviour.
Track median changes per pull request over months.
A rising line means people have started batching, which means verifying individually has become too expensive.
It moves before the complaints do, which is what makes it useful.
Plot it against blocking pipeline duration and the relationship is usually visible.
Treat a sustained rise as the trigger for the next round of work, rather than waiting for the number of complaints to reach some threshold.
Doing the cheap things early
The practices that cost little at small scale and are expensive to retrofit.
Module boundaries, before the codebase obviously needs them.
Declared dependencies with cycles failing the build.
Pinned toolchain versions.
A scripted setup path, tested in CI.
Timing telemetry, so the trend exists when you eventually need it.
None of these is urgent at fifteen engineers and all are much cheaper then than at a hundred and fifty, which is the argument for doing them while nobody is asking.