Businesses that build custom software often find themselves, five or six years later, facing the same conversation: the system works, but it's becoming increasingly expensive to change, the team dreads touching certain parts of it, and at some point someone says 'we'd be better off starting again.'
There is a five year rebuild cycle in custom software. It is not universal, but it is common enough to be a pattern rather than a run of bad luck. The rewrites that result are expensive, disruptive, and often produce a new system that will itself face the same conversation five years later.
Understanding why this happens is the first step to building software that doesn't.
The pattern is predictable
Most rewrites don't happen because the original technology was wrong. They happen because of accumulated decisions that made perfect sense individually but compound into a structural problem. The data model was designed around the business rules of the time and doesn't accommodate the rules of now. The architecture was designed for the scale of the time and buckles under current load. The codebase has changed hands enough times that nobody holds a coherent mental model of how the pieces fit together.
By the time the rewrite conversation starts, the system has often been quietly degrading for years. New features have become progressively harder to add. The team has developed extensive local knowledge about which parts of the system are safe to touch and have verbal conventions for working around its limitations. The software is still running, but it's become an obstacle rather than an asset.
The decisions that cause it
The most common cause of a five year rebuild is a data model that encoded assumptions rather than facts. A field takes one of three values because that is how the business works today, not because there is a constraint that ensures it. A relationship between entities was implemented as a workaround and never revisited when the use case changed. A decision to denormalise was made 'for performance reasons' without understanding whether performance was actually the constraint.
The second common cause is coupling. When modules in a system are tightly coupled, changing one thing requires understanding and modifying several others. The cost of change grows with the size of the system. Features take longer to add. Bugs take longer to fix. The risk of regression increases with every change. This accumulates until changes start becoming tactically avoided, and the system ossifies.
The third cause is a test suite that does not actually catch regression. When tests exist but are unreliable, either because they are poorly targeted or because they have become outdated as the system changed, the team cannot refactor safely. Improvements become risky, so they do not happen, and the codebase accumulates weight it cannot shed.
What longevity actually requires
The systems that avoid the rewrite cycle share characteristics that are visible from the first version. The data model is designed around things that are genuinely stable: the facts of the domain rather than the current business rules about those facts. The modules have clear, documented interfaces that can be changed internally without affecting their callers. The test suite is targeted at the things that matter to the business, not the implementation details that change.
These properties require upfront discipline and ongoing maintenance. It is easier to hard code a value than to model it correctly. It is faster to add functionality inside an existing module than to assess whether it belongs there. The pressure to deliver features always argues against the investment in keeping the codebase healthy.
The counterargument is not abstract principle. It is arithmetic. The cost of a rewrite is almost always higher than the accumulated cost of the structural investment that would have prevented it, because the old system's behaviour has to be understood and replicated before you can improve on it.
The platform that didn't need a rebuild
The rewards platform we built seventeen years ago is still running across multiple tenants. It has absorbed years of new requirements, new regulatory obligations, new integrations, and major infrastructure changes. It has handled over four million users and consistent annual transaction volumes without requiring a full rebuild.
That's not because the original engineers were exceptional. It's because certain structural decisions were made correctly early on: the data model was designed to be extended without breaking existing data; the module boundaries were maintained as new engineers joined the team; the test suite was targeted at behaviour the business cared about rather than implementation details.
Longevity in software is an architecture quality, not a technology quality. The question to ask is not 'what framework should we use?' but 'what structural decisions will we have to live with for the next ten years?'
The Real Cost of Technical Debt in Operational Systems →
Building software that lasts is a design decision, not a hope
The five year rebuild cycle is common. It is not inevitable. The businesses that avoid it invested early in the structural properties that make software extensible over time: clear data models, genuine module separation, and test coverage targeted at what the business actually requires.
The investment is real. The return on that investment compounds over time, and the alternative of funding a rewrite every five years is the more expensive path.
More in this series
- The Difference Between a Demo and Production Software
- Why Software Gets Rebuilt Every Five Years and How to Avoid It
- Audit Ready by Design: Building Software That Passes Every Review
- Observability Is Not the Same as Logging
- The Real Cost of Technical Debt in Operational Systems
- Deployment Patterns for Business Critical Systems
- How to Design Software That Scales Without a RewriteComing soon
- Production Readiness Checklist: 12 Things Most Teams SkipComing soon
- Graceful Degradation: What Happens When Part of Your System FailsComing soon