It's (Still) All About Boundaries — bounded.dev Skip to content Why boundaries (module structure, clean interfaces, and strict types) are the single most important factor in whether AI-assisted development actually works.<br>There is one thing that separates a codebase you can move quickly in from one that slowly suffocates your team. It is not the language, the framework, the cloud provider, or the number of tests. It is boundaries.
This has always been true. In the age of AI, it is more true than ever.
Spaghetti
Picture a bowl of spaghetti. Now picture each strand as an artery (sorry, a little gruesome, I know), each one carrying blood, performing some vital function, connected at both ends to something important.
You are a surgeon who needs to operate on one section of this mass. You draw a circle around the area you are working on. Immediately you see a dozen arteries crossing the boundary, disappearing into the tangle in every direction. To understand what your section does, you have to trace each one. You follow an artery out, arrive somewhere else in the system, and now you have to understand what happens there too. Then you follow the next. And the next.
By the time you have traced enough to feel confident, you have accumulated an enormous amount of context. And here is the brutal reality: you cannot hold it all at once. The parts you understood first have already started to fade. You are perpetually chasing a complete picture you can never quite assemble.
And when the system needs to grow? Nobody wants to reach into the tangle. So the path of least resistance is to graft something onto the edge: a new piece bolted on the outside, with arteries spliced into various points in the existing mass. It works. It ships. And the tangle gets a little bigger, a little harder to trace, every time.
This is a codebase without boundaries. This is why engineering teams slow down. Not because the developers get worse, but because the system gets bigger and more entangled, and the cognitive cost of making any single change becomes prohibitive.
The Spotlight
Think of your working memory as a spotlight. Wherever you shine it, things brighten: you understand them, you can reason about them. Move it to illuminate a new area and the places you just lit start to dim. You can widen the beam, but only at the cost of less brightness everywhere. This is not a flaw in any particular engineer. It is how human cognition works.
Good software architecture is, at its core, a set of techniques for keeping the required size of the spotlight small.
If the part of the system you are changing has a clean, narrow interface (a small surface area), and the modules around it are equally well-defined, then your spotlight only needs to cover a small area. You understand your module. You understand the interface it exposes. You understand the interfaces it depends on. You do not need to understand the internals of anything else, because the boundaries guarantee those internals cannot surprise you.
Return to our arterial tangle: boundaries are the equivalent of a surgeon operating on an organ with clearly defined blood vessels in and out, rather than reaching into a mass of undifferentiated tissue. Same arteries, same vital functions, but now there are only a handful crossing your boundary, and each one has a known purpose.
The smaller and shorter-lived your spotlight, the more essential these boundaries become.
This Is Not New
Bounded modules with strictly defended interfaces are not a new idea. Eric Evans wrote Domain-Driven Design in 2003. Robert Martin has been articulating clean architecture for decades. The principles behind clean architecture, layered architecture, and hexagonal architecture patterns all converge on the same insight: keep modules focused, keep interfaces narrow, keep internals hidden.
The industry broadly agrees this is the right approach. And yet many production codebases are the arterial tangle.
Why? Because designing good boundaries is remarkably hard. It requires deep understanding of the domain: knowing where the natural seams are, which concepts belong together, and which should be kept apart. Get the boundaries wrong and you end up with modules that are constantly reaching into each other, or abstractions that fight the grain of the problem. Bad boundaries can be worse than no boundaries: they add indirection without reducing complexity.
And even when boundaries start well, they erode. Every shortcut (reaching into another module’s internals, leaking implementation details through a public interface, adding a dependency because it is convenient) widens the surface area a little. Over time, those erosions compound. The spotlight has to grow. Eventually you are back in the tangle.
This is not a reason to avoid boundaries. It is a reason to treat them as a discipline. Keep modules small and focused. Expose only what needs to be exposed. Treat every public interface as a contract. Enforce it. When you...