The excuse survived a decade because one engineer’s feedback loop fitted inside one shared environment. Point twenty agents at that same environment and it stops being a slow loop and starts being a broken one.
Author: James Phoenix | Date: August 2026
The Excuse Had a Good Decade
Every backend team I have worked with has a version of this sentence. “We can’t run locally because of the auth service.” “We can’t run locally because of the broker.” “We can’t run locally, we’re on managed everything.”
Sometimes it is genuinely true. Mainframes exist. Specialised hardware exists. A handful of managed services ship no emulator, no open source equivalent, and no sane way to fake the parts you depend on.
Most of the time it is not a constraint anybody has tested. It is a decision nobody has revisited, propped up by a loop that is slow but survivable. Make a change, commit, push, wait for a build, wait for a deploy, run tests against shared dev. Twenty to forty minutes to learn whether a one-line change was right, and if it was not, you go around again.
That loop is bad. At human speed it is also merely bad. One engineer making three considered changes a day can absorb three forty-minute waits. They compensate by making each change larger, batching more work behind each validation, which is its own quiet damage. But the team ships, so nobody files the bug.
The Hidden Assumption Was Serialisation
Shared dev environments work at all because of a property nobody writes down: at any given moment, roughly one meaningful change per engineer is in flight, and the environment is only ever asked to hold a handful of them at once.
That assumption is doing enormous load-bearing work. It is why a single Postgres is fine, why one Redis with unprefixed keys is fine, why one Temporal namespace with one task queue is fine, why nobody bothered to make seed data idempotent. Shared dev is not a design. It is a bet on low concurrency, and for a decade it was a good bet.
Agents Break the Bet, Not Just the Clock
The obvious agentic reading of all this is “agents write code faster, so a slow validation loop hurts more.” True, and mostly uninteresting. My CI bill already taught me that lesson: once agents drive the commit button, every per-build inefficiency gets multiplied five to ten times.
The sharper problem is that a fleet is not a faster engineer. It is a concurrent one. When I run five worktrees with agents iterating in each, the shared environment is no longer holding one change in flight. It is holding five, none of which know about each other, all of them writing.
The failure modes are not slow, they are wrong:
- Two agents run migrations against the same database. The second one’s schema assumptions were true when it read them and false when it wrote.
- Agent A’s seed data makes Agent B’s assertion pass. Neither change is correct, and the suite is green.
- A worker on branch A consumes a message produced by branch B, because the task queue name is a constant in a config file rather than a function of the run.
- An agent’s test passes because somebody else’s deploy happened to be sitting in the environment, and fails an hour later for reasons no log will ever explain.
A slow feedback loop wastes a human’s time. A shared one poisons an agent’s evidence. That is a categorically worse failure, because the agent has no instinct that something smells off. It reads green, writes it into its context as established fact, and builds the next three changes on top of a result that was never true.
The Excuses, Repriced
His list is the right list. The prices have moved.
“My service depends on too many other services.” Run the ones you own, fake the ones you do not. The fleet version adds a constraint: the fakes have to be cheap enough to stand up per worktree, which usually means in-process rather than another container. When I collapsed our auth service into a module running inside the same Node process as the API, boot cost went from 30 seconds to zero and the local Docker stack lost a reason to exist.
“I need a database or a broker.” Run them locally, but the real work is namespacing, not installation. Schema per job in Postgres, run-and-attempt prefixes on every Redis key, deterministic per-run Temporal task queues and ports. Do that and the same box safely holds ten concurrent agents. Skip it and you have rebuilt shared dev on localhost, which is the worst of both.
“We use cloud services.” Emulators for some, Dockerised equivalents for others, fakes for the rest. The thing worth noticing is that the more open source a dependency is, the more cleanly an agent can operate it, because it can read the SDK in node_modules, run the server in a debugger, and wipe the volume between runs without asking anyone’s permission.
Local Has to Predict Prod, or It Is Theatre
The one place I would push back on the original framing is that “runs locally” is not the win condition. An agent’s local loop is only worth trusting if local actually predicts prod. If the Redis on my laptop carries different eviction flags than the Redis in GKE, a green suite is a lie, and I have simply moved the false evidence closer to home.
So the parity is mechanical, not aspirational. One linter runs on every pnpm lint and asserts that local, staging, and production compose files carry the same pinned images, the same collector, the same healthchecks, the same persistence flags. Bump a version in one place and the build stops you. Drift is not discouraged, it is rejected.
Local does not mean a laptop replica of production. It means infrastructure local and identical in shape, apps as hot-reload processes, and every piece of shared state keyed by the run that owns it.
The Test I Use
Before I accept “we can’t run locally”, I ask four questions in order:
- Can one command take a clean clone to a running system?
- Can two copies of that run at once on the same machine without touching each other’s state?
- Does the local infrastructure match production’s shape mechanically, or by somebody remembering?
- Can I wipe all of it and start again without consequence?
Most teams that say they cannot run locally have never got past question one. The ones that have usually fail question two, and that is the one that now decides how many agents you are allowed to run.
Related
- The Environment Leads The Agent – The parity linter and the wider case for a repo that steers the agent
- Zero-Friction Onboarding – Question one, and why setup speed predicts agent effectiveness
- Git Worktrees for Parallel Development – The parallelism this note is the precondition for
- Hosted Builds Are the Wrong Abstraction – The same argument applied to the build and deploy path
- Agents Broke the Economics of Your CI – What agent throughput does to per-build waste
- Self-Hostable Observability Is Local Infra – Local-first applied to the observability layer
- Protect Your Harness from Longer Integration Tests – Keeping the local loop fast once it exists

