A founder I’m talking to usually can’t see the codebase, and doesn’t want to. What they see is the product calendar: features that took two weeks now take two months, the roadmap keeps slipping, and the team that used to ship every Friday hasn’t shipped anything visible in a quarter. The conversation that follows has a script. Are the developers underperforming? Should we hire more? Should we replace someone?
Usually none of those. There’s a real differential here, and it’s worth a sentence: a team that was never fast, or one that’s slow on a two-year-old codebase, is a people conversation. But a team that used to ship every Friday and gradually stopped points somewhere else. After years of being called into exactly that situation, the most common answer is boring: your team is fine, and your codebase is fighting them. The good news is you don’t need to read code to diagnose it. The symptoms are visible from where you sit.
The symptoms you can see from the founder’s chair
Estimates inflated and nobody can explain why. The same developer who built the feature in a week two years ago now quotes a month for something that sounds smaller. They’re pricing in the minefield: in a codebase that fights change, most of the work is making sure the change doesn’t break something else.
There’s a part of the product nobody wants to touch. Billing, usually, or the permissions system. Tickets that go near it get rescheduled or quietly rescoped. Your team is routing around a structure they no longer trust, the way drivers route around a bridge with a weight limit.
Every fix breaks something else. You ship a change to invoices and search goes down. From your chair this looks like carelessness. Inside the code it’s coupling: parts of the system holding hands in the dark, so that touching one tugs all of them.
New developers don’t make it faster. You hired two more engineers six months ago and throughput didn’t move, or dropped. In a healthy codebase a new person contributes in weeks. In a fighting one, they spend months learning where the mines are, and your seniors spend their time drawing maps instead of shipping.
And the sharpest one: the person who built it left, and velocity left with them. The knowledge of how the system works lived in their head rather than in the code and its tests, and what remains is a machine with no manual.
What makes it worse
Two reflexes feel responsible and reliably deepen the hole.
Hiring more developers into a code problem. Adding people to a codebase that fights change adds people for the codebase to fight. The bottleneck was never headcount, so more salaries buy the same bottleneck, and each new hire spends months becoming productive while your seniors pay the onboarding bill.
Declaring the big rewrite out of frustration. The all-new version that will fix everything usually means the old system limps on while a second team spends a year rebuilding, and the business pays for both. There are cases where a rewrite is right, and I’ve written about how to tell them apart, but as a frustration reflex it’s the most expensive purchase in software.
What’s actually going on, translated
A codebase ages the way a city does. Every feature shipped under deadline leaves a shortcut behind, every departed developer leaves a district only they understood, and tests that should act as guardrails quietly stop guarding. None of this shows up on the product calendar for years, because teams compensate: people work around things, remember things, take the long route. The day the compensation runs out is the day it looks, from your chair, like the team suddenly got slow. It wasn’t sudden, and it wasn’t the team. We spent eleven months inside a thirteen-year-old codebase at Domestika where exactly this had happened to a strong team: four architectures pretending to be one app, dead code nobody could tell from live, tests that guarded nothing. Delivery had stalled, and nobody at the company was the villain.
What to do instead
Get the codebase read by someone whose job is reading codebases. That means a person inside the actual code, the release process, and the tests, talking to your team, who comes back with a concrete map of what’s blocking delivery: what to kill, what to keep, and what to build first. An architecture workshop or a slide deck won’t do it, because those collect opinions about the code instead of evidence from it. We run this as a two-week decision sprint, and the shape matters more than who does it. Short, inside the code, and it has to end in decisions.
Then fix the highest-tax problem before the most visible one. The thing slowing everyone is rarely the thing everyone complains about. At Domestika the kill that mattered was a piece of infrastructure that taxed every release; removing it made every later fix cheaper. Sequenced right, a rescue gets faster as it goes, because each removal pays for part of the next.
And hold the hiring until the structure can absorb it. The right time to add developers is when a new person can contribute in weeks again. You’ll know the rescue worked by the calendar you already watch: when estimates shrink back toward believable, and Friday means shipping again.