Legacy systems run more of the world than people realise. They're also expensive to maintain and impossible to hire for. But rewriting from scratch is one of the most reliable ways to destroy a company.
Signs You've Under-Engineered
The opposite side: production outages that could have been caught by tests nobody wrote. Customer data in states that shouldn't be possible because there's no validation layer. A rewrite conversation every eighteen months because the codebase has calcified.
Under-engineering and over-engineering are both real. The sweet spot moves with team size and maturity. Check in on it every quarter.
The Architecture Decision That Stays With You
Architectural decisions have a half-life of about three years before they either compound into a solid system or become the thing everyone's working around. The ones that compound well share a few traits: they match the team's skills, they leave room for the most likely changes, and they don't require rare talent to operate.
The ones that age poorly usually chased a trend, optimised for a scale that never arrived, or assumed a team composition that didn't materialise.
How We Make These Calls
On every project, we do a written architecture decision record for anything that's hard to change. What we're deciding. What options we considered. Why we picked this one. What we'd reconsider if conditions changed.
It takes thirty minutes per decision and saves literal months of future second-guessing. A year in, when someone asks "why did we do it this way?", the ADR has the answer. Fewer religious debates, more work.
Documentation That Actually Gets Read
Most developer documentation goes unread. The problem isn't usually that developers are lazy — it's that the documentation isn't targeted at what they need. Long architecture documents nobody reads. Outdated READMEs. Tribal knowledge that never makes it to a wiki.
The docs that actually get read are task-focused and short. How do I run this locally? How do I deploy? How do I debug a failing test? Answer those questions well and you've solved 80% of the documentation problem. Leave the comprehensive architecture docs for when someone has already decided to learn the system deeply. Related read: our post on microservices vs monolith covers the flip side of this.
Signs You've Over-Engineered
If onboarding a new engineer takes more than a few days, something's off. If a local dev environment needs Docker Compose and six services running to test a simple change, something's off. If every deploy requires a ritual that only two people understand, something's off.
Not all of these are urgent fixes. But they accumulate as tax on every future change. Budget occasional time to pay the tax down.
The Cost of Technical Debt, Realistically
Technical debt is real, but not every piece of it costs the same. The debt that hurts is the debt in code you touch often. Debt in code nobody touches is just code nobody touches.
So the actually useful question isn't "how much debt do we have?", it's "what debt is in our hot paths?" Fix the hot-path debt. Leave the cold-path debt. Life gets better.
The Testing Strategy That Matches Your Stage
Testing strategy varies by company stage and nobody tells you this. At pre-PMF, extensive test coverage can actually slow you down because the code you're testing is likely to get thrown away. At PMF and beyond, inadequate testing is a pure liability that will bite you repeatedly.
Our rough rule: pre-PMF, test the two or three things whose failure would embarrass you (auth, payments, data integrity). Post-PMF, grow coverage deliberately in the areas with the most change or the most risk. Don't chase coverage percentages as a vanity metric. Chase the confidence to ship without anxiety.
The State of Software Engineering in 2026
Software engineering has been through a few shifts in the last few years that are worth naming. AI-assisted development is now mainstream — most professional engineers use tools like GitHub Copilot, Cursor, or Claude for daily work. The productivity gains are real but less uniform than marketing suggests. Strong engineers get more out of AI than weak ones, which is widening the gap between the best and the rest.
Architecturally, the pendulum has swung back toward simplicity. Distributed systems are having a moment of re-evaluation. Microservices fever has cooled. Modular monoliths are respected again. Kubernetes is being rightly identified as overkill for most teams. These corrections are healthy and long overdue.
The craft of shipping software, though, remains unchanged in its essentials. Clear thinking, testability, observability, incremental improvement, and good relationships with the people you're building for. No framework or AI tool replaces those. The teams that win are the ones who've stayed disciplined about the fundamentals while adapting to new tools.
Myths That Slow Teams Down
One: 'we'll clean this up later'. Technical debt in hot paths compounds. Debt you don't fix soon becomes debt you'll never fix. Decide early whether something is worth cleaning up now versus leaving forever.
Two: 'we need to rewrite this from scratch'. Almost always wrong. Rewrites take longer than estimated, pause feature work, and often produce a worse version of the original. Refactor incrementally in nearly all cases.
Three: 'more testing is always better'. Diminishing returns are real. Testing infrastructure and test suites take time to build and maintain. Match testing investment to actual risk, not abstract coverage targets.
A Rewrite Decision We're Glad We Made
A SaaS client we work with had a core scheduling engine that had been rewritten from the original Python to Go in 2023 to handle scale. The Go rewrite worked for about eighteen months, then started showing architectural pain as new requirements landed.
The discussion in early 2025 was whether to rewrite again, to Rust this time, for better concurrency. We talked them out of it. The Go system was about 60% of ideal, which is fine. The pain points were concentrated in three specific modules, not the whole system.
We refactored those three modules instead. Six weeks of focused work, no Rust migration, no new team skills to hire for. Performance targets met, pain points resolved, roadmap preserved. This is usually the right answer. Rewrites feel clean. They're almost never the highest-ROI move on a running system.
The Short Checklist
If you take nothing else from this post, take this checklist. It's what we'd hand to someone just starting out in this area. None of it is revolutionary. All of it is worth doing. The compound effect of consistently doing these things, even without any other clever moves, is meaningful over a year or two. We'd rather see a team do the checklist competently than chase the latest trend while skipping the fundamentals.
- Write architecture decision records for anything hard to change.
- Pay down tech debt in your hot paths. Ignore debt in cold paths.
- Have a 20-minute local setup for any new engineer. Longer is a signal.
- Review your production error rate weekly. Every error above floor is a message.
- Keep deployments boring. Excitement during deploy is a process failure.
- Run retrospectives regularly. Act on two items per retro, not twelve.
- Monitor p95 and p99 latency, not just averages. Your worst experiences hurt most.
- Keep a running architecture decision log. Future-you will thank you.
- Review error rates weekly. Not monthly. Weekly.
- Run regular game-day exercises for critical failure modes.
None of this is rocket science. It's the accumulation of small good decisions, made consistently, over time. The teams that win at this aren't the ones with the cleverest tactics. They're the ones that keep showing up, doing the fundamentals, and improving a bit each quarter. That's the whole secret, and it's also why so few actually do it. The temptation to chase the novel and the exciting is real. The discipline to keep doing the boring work that actually produces results is rare. If you've read this far, you probably have the temperament to be one of the ones who makes this work. Start with one thing from the checklist above, ship it this week, and build from there.
Thanks for reading all the way to the end. If this was useful, the next most useful thing is usually to pick one concrete action from it and actually do it this week. Insight without action is just entertainment, and we suspect you've got better things to do than be entertained by a technology blog.
Frequently Asked Questions
Is it better to rewrite legacy systems from scratch or refactor them incrementally?
Refactor incrementally, almost always. Full rewrites are one of the most reliable ways to destroy a company — they take much longer than estimated, pause feature development, and often produce a worse version of the original. The strangler fig pattern (progressive replacement) delivers value continuously while reducing risk.
What's the strangler fig pattern?
You wrap the legacy system with an API gateway. New functionality goes in a modern system behind the gateway. Feature by feature, you migrate from legacy to new with traffic routing changes at the gateway. Eventually the legacy system has zero traffic and can be turned off. Takes years but ships value continuously.
How long does legacy modernization usually take?
Mid-sized enterprise systems: 18-36 months for meaningful modernization. Large mainframe migrations: 3-10 years. The timeline depends more on organizational capacity and business continuity requirements than on technical complexity.
When does a full rewrite make sense?
When the existing technology stack is dead and no developers are available. When the architecture is fundamentally incompatible with current requirements. When security issues in the legacy are unfixable. When the organisation is making a deliberate strategic bet and has capacity. Otherwise, refactor.
Need help with your project?
Orange Essence Technologies builds e-commerce, software, mobile apps and AI solutions for clients across India and around the world. If any of this is relevant to what you're working on, we'd love to chat.
Get in touch →