Writing code is the easy part. The hard part is making it something a human being can understand, change, and extend six months later without losing their mind.
I want to talk about maintenance, not in the "keep your dependencies updated" sense, but in the deeper sense of: will this thing survive contact with reality?
Most projects aren't maintainable
I've worked on a lot of codebases. One of the rarest things I've encountered is a project that's genuinely easy to maintain. Not "okay if you know the codebase" or "fine once you set up the dev environment", but actually clear, easy to change, and kind to the next person who touches it.
And before you blame AI slop: this was true long before LLMs were writing code. Humans did a fine job of building unmaintainable software on their own.
The real problem isn't outdated dependencies
Outdated dependencies get a lot of attention. Language versions change, libraries deprecate APIs, security vulnerabilities pile up. That's real. But you can automate most of that with Dependabot, Renovate, a good CI pipeline. Dependency maintenance is a solved problem if you care about it.
The thing that actually kills projects? Overly complex solutions to simple problems.
Look at what most business applications actually are: some form of CRUD, maybe some calculations, maybe a call to an external API. That's it. Not a distributed systems challenge. Not a novel algorithmic problem. Data goes in, data gets stored, data comes out in a slightly different shape.
And yet:
- Microservice architectures with twelve services for an app with three users
- Event sourcing for a table that gets updated twice a day
- A custom query builder wrapping an ORM that's already abstracting SQL
- Abstraction stacked on abstraction until nobody can trace what actually happens when a button gets clicked
Why does this happen?
Misaligned ambition. You hired smart engineers, smart engineers want interesting problems, so they find complexity where none exists.
Resume-driven development. Kubernetes looks impressive in a post-mortem. A boring REST API doesn't.
Well-intentioned overengineering. Designing for a scale that never comes, anticipating requirements that never materialize. The classic trap of building for the company you hope to be instead of the company you are.
Simple is hard
Here's the uncomfortable truth: simple code is harder to write than complex code. Complex code is easy: you just keep adding layers until it works. Simple code requires you to understand the problem deeply enough to see the straightforward path through it.
- Most CRUD applications don't need an event bus. They need a database, a few endpoints, and a clear data model.
- Most calculation logic doesn't need a strategy pattern with a factory. It needs a function that takes inputs and returns a result.
When you're reaching for a complex solution, ask yourself: is this complexity solving a real problem I have right now, or a hypothetical problem I might have later?
Nine times out of ten, it's hypothetical.
What maintainable actually means
Maintainable code isn't clever code. It's boring code: code where you can read a function and immediately understand what it does, where adding a new field doesn't require touching six files, where a new developer can be productive without a two-week onboarding session.
Boring doesn't mean lazy. It means that every decision (the data model, the abstraction boundaries, the naming) was made to serve clarity over cleverness.
The codebases I've seen that held up over time were the ones where someone made a conscious decision to keep things simple, pushed back on unnecessary complexity, and treated readability as a feature.
Conclusion
Code that works is the minimum. Code that someone else can safely change is the goal.
Before adding another layer of abstraction, ask whether the problem is actually complex, or whether you're making it complex. Most of the time, a straightforward solution exists. It just takes more discipline to find it than to build around it.
If you're not writing an ML framework or a high-frequency trading engine, there's a good chance your problem is simpler than your solution.