Science and technology
3 min readThe code that survived
Every year, thousands of apps get rewritten from scratch. Not because the tech changed — because nobody left behind could understand what was built or why.
achou

Every year, thousands of apps get rewritten from scratch. Not because the tech changed — because nobody left behind could understand what was built or why.

Why most software doesn't survive
Every year, thousands of applications get rewritten from scratch. Not because the technology changed. Because the codebase became impossible to read, and everyone who understood it had already left.
That's not a technology problem. It's a design problem — and it's almost entirely avoidable.
Clarity beats cleverness. Every time.
Here's a useful test: if a new developer joined your team tomorrow, how long before they could make their first meaningful contribution? That number tells you more about your codebase than any metric.
Readable code isn't slower to write — it's slower to write once. But every hour spent on clarity saves ten hours of debugging and onboarding later. The math isn't close.
The best code reads like a well-written paragraph. It tells you what it does without requiring you to hold the entire system in your head first.
Small components, clear boundaries
A function should do one thing. A module should serve one purpose.
When boundaries are clear, changes stay local. A bug in the payment system doesn't ripple into the notification layer. A dashboard redesign doesn't require touching the API. That isolation isn't accidental — it's the result of decisions made early, before the system got complicated.
This applies at every level. Functions around 20 lines. Files with one clear concept. Services with defined interfaces and obvious ownership. The pattern is the same whether you're writing a utility function or designing a distributed system.
Boring technology is underrated
The most reliable systems tend to be built with boring tools. PostgreSQL instead of the newest distributed database. REST instead of the trendiest protocol. Server-rendered HTML when it fits.
Dan McKinley wrote about this years ago: the opportunity cost of adopting new technology is high, and most of the time you're trading well-understood problems for unfamiliar ones.
That's not an argument against new tools. It's an argument for earning their place. Every new dependency should solve a problem that existing tools genuinely can't — not a problem you might have someday.
The real cost of complexity
Every abstraction has a price. Every layer of indirection makes the system harder to debug. Every configuration option multiplies your test surface.
Before adding complexity, three questions worth asking:
Is this solving a problem you actually have right now, not one you might have in six months? Is this the simplest solution — not the most elegant, the simplest? And can you reverse this decision? If not, spend more time on it.
The engineers who build the most durable software aren't the ones who build the most sophisticated systems. They're the ones who resist improving what isn't broken.
Write for the next person
Every line of code you write will eventually be read by someone else. Maybe a teammate. Maybe a future version of yourself who has forgotten the context entirely.
Name things clearly. Structure logic so it reads top to bottom. Delete code that's no longer needed instead of commenting it out. Make the happy path obvious and the error cases explicit.
Software that lasts isn't software that never changes. It's software that's easy to change because the intent behind every decision is still visible in the code.
That's what durable software actually means.