We like to tell ourselves fairy tales about “finished” systems. Version 1.0, a clean plateau where things settle. In reality, software doesn’t complete, it continues. It absorbs new requirements, new assumptions, new integrations. What can be called “maintenance mode” is really just development stretched over time.

Even the smallest tools evolve. A text editor starts simple, then picks up syntax highlighting, autosave, collaboration hooks, and yes, even Notepad got a spell check. The direction is usually outward: more surface area, more use cases, more interactions.
Entropy
Entropy, in this context, is the chaotic increase in possible behaviors. Every feature introduces branching and potentially multiplies the paths through the system. Left alone, this does erode the original functionality model.
Growth doesn’t automatically imply decay. Expansion and structure can coexist if the system is shaped intentionally. Systems don’t have to be left alone, they can be curated.
Some of the largest, longest-lived systems demonstrate this. The Linux kernel has been growing for decades, with thousands of contributors and an enormous surface area. By all accounts, it should be incomprehensible, yet it remains remarkably structured. Not because entropy doesn’t apply, but because it’s actively managed; through strict subsystem boundaries, a well-defined contribution process, and maintainers who act as long-term stewards of specific areas.
Similarly, PostgreSQL has grown steadily while maintaining a coherent architecture. Features are added, but rarely at the expense of conceptual integrity. There is a bias toward extensibility, letting new behavior plug into existing ones rather than bending the core. The result is a system that feels layered rather than tangled.
What these systems have in common is not a lack of entropy, but containment strategies.
Containment Strategies
Borders
Borders? I have never seen one. But I have heard they exist in the minds of some people.
Thor Heyerdahl
APIs are at the same time one of the best and one of the most hated containment strategies. They define borders: this side is your concern, that side is mine. They let teams and components evolve independently. But they’re not perfect barriers. They’re more like underwater fences: they mark a boundary, but they still collect barnacles. Edge cases, versioning quirks, backward-compatibility hacks. Over time, those become part of the interface.
The difference between a healthy system and a decaying one is how those barnacles are handled. In a healthy system, they are acknowledged and managed. Deprecated endpoints and interfaces are eventually removed. Versions are allowed to end. There is a willingness to say “this behavior was a mistake, and it will go away”. Without that, a fence becomes a reef.
Planning, Guidelines and Documentation
Planning helps, but only if it accounts for change. Rigid designs that assume a static world tend to fracture when change happens. Resilient systems define clear invariants – the things that must remain true – and allow everything else to transform around them. Modularity doesn’t need to be an aesthetic choice, but a way to localize change.
Guidelines matter just as much. Code review is not just about correctness, but about preserving shape. Does the code look good? Great. Does it work the right way? Fabulous. Does its thinking shift into a different direction than the rest of the project? Have it revised and reigned in. How does one determine what the direction should be? Documentation. Documentation is not just for users, but for future maintainers trying to reconstruct intent.
Analysis, Tooling and Refactoring
Sometimes tooling can help enforce consistency where humans inevitably drift.
I’m a vocal advocate of directing the use of LLMs towards what they’re great at – one example is analyzing existing information. Depending on the language and models available, this could be a potential avenue: create a CI analysis step to measure entropy.
Another way to fight entropy is periodic pruning. Remove dead code. Rewrite awkward abstractions. Simplify interfaces when possible. This is not a one-time cleanup, but an ongoing practice. Entropy increases by default; order requires continuous effort.
Don’t Contain Everything
So yes, software systems are ever-evolving entities. They grow, they shift, they accumulate history. But growth does not have to mean collapse. With deliberate structure, strong boundaries, and a willingness to revisit past decisions, even very large systems can remain understandable.
The goal of this process isn’t to stop entropy altogether. It’s to shape it – to let systems grow without losing their center of gravity.






Leave a Reply