How do you tell an architecture problem from a capacity problem?
Most "technical debt" complaints from a CTO with two to four engineers describe two different problems under one label. One is architectural: the foundation blocks the business. The other is capacity: the design is workable, but too few senior engineers exist to change it safely.
What follows is our practical judgement, not research. Run these checks this week:
Where is change slow? If it is slow in one area, such as billing or permissions, suspect architecture. If it is slow everywhere because only one or two people can touch the code safely, suspect capacity.
Does a data model or platform block the business? If you cannot express a product you need to sell, or you cannot hire for or patch the platform underneath you, the problem is architectural.
Who can ship a risky change? If the answer is "you, and only you," you have a capacity problem, however good the design is.
Are releases frightening because nothing is tested? That is neither architecture nor capacity. Write characterization tests first, which pin down current behaviour before you touch it. Minimum Code makes this point in its refactoring guidance, and it applies before any of the three options below.
Do features in one module routinely break another? Tight coupling inside a workable design points to refactoring. Coupling that follows from the data model itself points to a rebuild of that part.
If most answers point to one or two people acting as the gate, read our piece on scaling without a VP of engineering before you commit months to a rewrite that will not fix that gate.
What can delivery metrics tell you?
Delivery metrics give you a starting point, not a verdict. DORA's five software delivery performance metrics, described at dora.dev/guides/dora-metrics, cover the throughput and stability of your delivery process. They show whether the pain is concentrated or systemic.
Read them as diagnostic signals. These three readings are our own practical judgement, not something DORA states:
Slow lead times in every area suggest a people or process constraint, which leans towards capacity.
Poor stability in one subsystem, with healthy numbers elsewhere, leans towards a targeted architectural fix.
Poor stability everywhere, with no tests behind the changes, calls for characterization tests before any decision.
We are not quoting benchmark figures here. Compare your own numbers over time and across parts of your system.
When is a rebuild actually justified?
Rarely, and only when the foundation blocks you. HighCircl's guidance is direct: rewrite only when the foundation is the constraint, and replace in slices rather than in one cutover. A messy codebase on a sound foundation does not qualify. Ugly code can be improved. A data model that cannot represent your business cannot.
Minimum Code adds conditions worth treating as a gate before you commit:
Confirmed funding and staffing to run two codebases at once, the old and the new.
Stakeholder acceptance that feature delivery will slow during the migration.
A phased migration with behaviour checks, so you can prove the new code does what the old code did.
If you cannot tick all three, you are not ready to rebuild, whatever the codebase looks like. The second condition is the hardest for a team of two to four engineers. Every engineer on the migration is an engineer not shipping product.
When a rebuild is justified, the strangler fig approach keeps the product alive while you replace it piece by piece. Our step-by-step strangler fig guide covers how to implement it. For a wider view of the options, see the four modernisation approaches and how to pick one.
When is refactoring the right call?
When the foundation holds and the problem is the code sitting on top of it. Martin Fowler's definition, as cited by Minimum Code, is the useful one: refactoring is a series of small changes that keep the system working after each step. That constraint is the point. The product is never down while you clean up.
Refactoring fits when:
The data model and platform can express where the business is going.
The pain is localised: a tangled module, duplicated logic, an unclear boundary.
You can put characterization tests around the area before you change it.
Each step is small enough to ship independently.
The failure mode is refactoring with no tests and no endpoint. Pick one constraint, such as the module that slows every release, and refactor until that constraint is gone. Then stop.
When is the real answer to add capacity?
When the design is workable but you are the only person who can change it safely.
The fix is to extend your existing team with senior engineers who work inside your workflow while you stay in control of the product. We run this as embedded engineering pods of 3 to 8 engineers. Product decisions stay with you.
If you want an outside view before choosing between the three options, a fixed-scope Technical Readiness Report audits the technical health of a codebase or system. Our article on what it covers and when you need one is the place to start.
How do the options compare at a glance?
Situation | Likely answer | First step |
|---|---|---|
Change is slow everywhere; only one or two people can ship safely | Add capacity | Embed senior engineers in your workflow |
Releases are risky and untested | Refactor | Write characterization tests first |
One module slows every release | Refactor | Isolate and refactor that module |
Data model cannot express the business | Rebuild, in slices | Confirm funding for two codebases |
Platform cannot be hired for or patched | Rebuild, in slices | Plan a strangler fig migration |
Unsure which of the above applies | Get an outside view | Commission an audit |
What to do this week
Name the one constraint that costs you the most. Then pick the smallest change that removes it. If you want an outside view first, the Technical Readiness Report article explains what an audit involves and when it is worth doing.
FAQs
Is a full rewrite ever the right call at seed stage?
Only when the foundation is the constraint, and even then in slices while the product keeps running. A big-bang rewrite stops feature delivery, which is hard for a small team to absorb.
How do I know if my problem is capacity rather than architecture?
If change is slow everywhere because only one or two people can make it safely, that is capacity. Architecture problems concentrate in specific areas or in the data model.
Should I write tests before refactoring?
Yes. Characterization tests pin down current behaviour, so you can confirm each small change preserves it.
Can DORA metrics tell me whether to rebuild?
No. They help locate where delivery is slow or unstable, which informs the diagnosis. The decision still rests on whether the foundation blocks the business.
Share




