AI writes code faster than you can review it. Here is what I did about it.

I'm Johannes. I'm building Tidebreak, an investigations engine where every finding traces back to the source bytes it came from. That obsession with provenance is also why I can only write about my own engineering one way: with the parts I got wrong left in.

In the last twelve weeks I made 4,111 commits to a codebase that is now about 455,000 lines: a real production system, 154 database tables, six hundred-odd endpoints, the works. I wrote almost none of it by hand.

That sentence is either exciting or alarming to you, and the honest answer is that it should be both. Because the thing nobody tells you about coding with AI is that the writing was never the bottleneck, and it was never the danger either. Agents will produce correct-looking code faster than any human can read it. So the moment you let them run, both the ceiling on your speed and the thing most likely to hurt you move downstream, past the keystroke, into a place you can no longer watch by eye.

I learned this the way you learn most things: by getting it wrong first. What kept the codebase from quietly rotting under that volume was not better prompts. It was a set of guardrails that make the rules the system depends on impossible to break silently, and an autonomous loop that is built so it cannot do the unsafe thing rather than trusted not to. This is a post about those, and about the parts that broke anyway, because a post that only shows the parts that worked is not worth your time.

The failure that scares me is the quiet one

Everyone writes about AI hallucinating a bug. That is the boring failure, and your tests catch it. The failure that actually costs you is silent.

An agent, asked to add a feature, notices there is already a scoring function two directories over and writes a second one that is subtly different. Or it returns a cleaner error message on a permission check and, in doing so, tells an attacker that a record exists. Or it reads a user id where the rule of the system is to read an organization id, and eleven months of careful isolation gets a hairline crack.

None of these fail a test, because a test encodes what you thought of, not what you forgot. At forty-eight commits a day you will not catch them by reading diffs, because you will not read the diffs. The problem is not correctness in the small. It is review bandwidth and invariant drift, and neither of those is fixed by a smarter model.

Invariants as guardrails, not comments

So the first real discipline is this: write down the rules the system cannot survive breaking, and then make each one break the build if it is violated, rather than living in a comment that hopes an agent reads it.

A few of mine, kept general:

  • Cross-tenant access returns "not found," never "forbidden." A forbidden response is more helpful to a user and it silently confirms the record exists. An agent optimizing for a clear error message will reach for forbidden every time. A guard rejects it, so the helpful-but-wrong version never lands.
  • One capability has exactly one implementation. The second copy of a scoring or de-duplication function is a build failure, not a code-review note. This is the single most useful rule I have: it turns "please reuse the existing thing" from a hope into a constraint, and agents respond to constraints, not pleas.
  • Some numbers may never be collapsed. A risk signal I track on two independent axes has to stay two numbers through every layer, because averaging them hides the case that matters. That is enforced in code, not prose, because prose is exactly what a fast agent skims.

The rule that makes the whole thing scale is the meta-rule: every non-negotiable ships with an automated backstop, or it does not ship. A rule an agent can violate without the build going red is not a rule. It is a wish, and wishes do not survive contact with an automated contributor that has read your style but not your scars.

I will be honest about the cost. This is real work paid up front, and below a certain velocity it is not worth it, because you would just read the diffs. The trade flips the moment the machine is committing faster than you can review. Then the guardrails are not bureaucracy. They are the only reason you can let go of the wheel at all.

An autonomous loop that cannot hurt you

The guardrails let agents commit safely. The next piece let them work while I sleep.

Every night a loop runs over the backlog: it triages what is worth doing, de-risks each candidate, builds it, reviews the result, and integrates what passes. The interesting thing about it is not that it is careful. It is that it is built so carefulness is not required. It structurally cannot deploy. It cannot push a red main. It cannot open its own pull request or approve its own work. If the final gate comes back red, it hard-resets the entire batch rather than salvage a piece it should not trust.

That is the whole philosophy in one line: I did not make the loop trustworthy, I made trust unnecessary. An autonomous process you have to trust is one you have to watch, and a process you have to watch is not autonomous. The only version that lets you actually walk away is the one where the worst thing it can do is waste a night's compute.

Isolation and specialists

Two smaller pieces hold that up. Parallel agents each work in their own isolated copy of the repository, so two of them cannot clobber each other's changes, and one checkout is reserved for integration only, guarded so no feature work lands there by accident. And the agents are not interchangeable: there is one that builds, one that reviews, one that plans, and the reviewer is pinned to the strongest model available, unconditionally. You can cost-optimize a lot of things in a setup like this. The gate is not one of them.

The gate is one local script

My continuous integration is deliberately dull. One script is the entire gate, and it runs the same way on my machine as anywhere else; the hosted CI mostly just dispatches it. That sounds unambitious until you remember who the primary user of your gate now is. It is not you, running it a few times a day. It is a machine, iterating against it a hundred times a night. Determinism and a single source of truth stop being nice-to-haves and start being the thing that keeps the whole loop from chasing ghosts.

What broke

If the rest of this reads like it worked, let me correct the impression, because the interesting part is where it did not.

I did not know what an overnight run cost. One of them burned 13.6 million tokens, and I learned that number by counting it by hand, afterward, when something felt off. There was no hard budget ceiling on unattended work at the time, nothing that would have stopped a loop that misjudged its own progress from running until morning. The industry has a small graveyard of these stories, some with four and five-figure price tags. I got a cheap lesson, and the real fix, a spend cap that does not depend on the agent's own judgment, came after the scare, not before it.

A nightly run crashed once and left a handful of issues marked in-progress, half-built, in a state the next morning's triage could not see. So the loop kept skipping them, because as far as it could tell someone was already on them. Nobody was. I built the self-heal that resets orphaned work on an abnormal restart because of that morning, not in anticipation of it. Almost every guardrail in this system has that shape: it is a scar, not a prediction.

Two agents sharing one working directory have tangled each other's changes more than once. Discipline, it turns out, is not structure. A rule that says each agent gets its own workspace is only as good as the enforcement behind it, and I have watched a second session quietly undo the first's work while both believed they were alone. That gap is not fully closed. I am telling you because a post that pretends otherwise is not worth reading.

And when I finally audited my own setup against how the best teams do this, the verdict was uncomfortable and correct: my automation was ahead of almost anyone's, and my visibility was the weakest part of the whole thing. I had been flying a fast aircraft with half the instruments dark. The token-count-by-hand story is just the most quotable symptom of that.

I lead with these because the numbers at the top of this post are only worth anything if you believe the person reporting them.

Where the bottleneck actually went

Here is the part I have not solved. The question stopped being "can I run more agents" a while ago. It is now "can I review and merge fast enough," and past a handful of parallel agents, the answer is me. I am the ceiling. More parallelism just grows the queue of things waiting on my attention.

The honest frontier from here is not a better prompt or a bigger fan-out. It is a real automated quality gate that earns enough trust to merge without me, and the tooling to review in batches instead of one change at a time. That is the actual hard problem in AI-assisted development at volume, and anyone selling you "just add more agents" has not hit the wall yet.

What to take from this

  • Machine-enforce your invariants, or they will drift. A rule the build does not check is a wish.
  • Make the dangerous action structurally impossible, not policy-forbidden. Do not build a careful autonomous loop; build one that cannot do the unsafe thing.
  • Never cost-optimize the reviewer.
  • Put a hard ceiling on anything that runs unattended, independent of the agent's own judgment.
  • Instrument before you scale. Automation without visibility is just a faster way to be surprised.
  • Your bottleneck is review, not generation. Spend your best effort there.

None of this is finished, and my real bottleneck now is the one I just described. If you have actually solved review-at-machine-speed, I would genuinely like to hear how, because I have not.

And if you came for the engineering but your real world is investigations, breach data, financial crime, anything where a conclusion is only as good as the evidence beneath it: that is what I am building Tidebreak for, and the same discipline in this post is the reason every claim it makes traces back to a source. See it here.

Previous Hello, world Next I let AI agents run my life. They can read everything and send nothing.