Concentric architecture rings with dependencies pointing inward

Every few months I review a codebase from a small team that read Uncle Bob’s Clean Architecture book and applied all of it. Entities, use cases, interface adapters, frameworks layer, an interface in front of every class, a mapper between every layer. Five developers, a simple product, and you need to touch six files to add one field to a form. The team is proud of the architecture and slow at everything else.

I want to be fair to the book. Clean Architecture, and Robert Martin’s writing in general, contains real wisdom. The core idea is solid gold. Your business rules should not depend on your framework, your database, or your delivery mechanism. Dependencies should point inward, toward the things that change slowly, away from the things that change fast. That idea has saved me many times over the years.

The problem is not the idea. The problem is applying the full ceremony at a scale where it does not pay. Architecture is not a moral question, it is an economic one. Every layer you add has a price, paid in every single change, forever. For a big system with many teams, the price buys isolation and it is worth it. For five people, often it buys nothing, and over engineering is a cost exactly like under engineering is. It just hides better, because it looks like discipline instead of looking like a mess.

What pays off for a small team

After many years and many codebases, here is what I keep from Clean Architecture even on the smallest team.

Keep the business logic out of the controllers and out of the framework. This is the heart of the whole book and it costs almost nothing. Your pricing rules, your eligibility checks, your domain decisions live in plain classes that know nothing about HTTP or the ORM. The payoff is immediate, those classes are trivial to test, and tests of business rules are the tests that protect actual money.

Keep a boundary in front of external services. The payment provider, the email service, the third party API. Put a small interface of your own in front of each one. Not because of architectural purity, but because these things change for business reasons. Providers raise prices, get acquired, go down. When my agency in Brazil had to swap a payment gateway, the project was two weeks instead of two months for exactly one reason, the gateway was behind one small interface. That boundary was the cheapest insurance we ever bought.

Keep the dependency direction rule. Even with few layers, domain code never imports infrastructure code. This is a one sentence rule that any team can check in code review and it prevents the worst kind of rot.

What to skip at this size

Now the part that makes some people angry.

Skip the interface for every class. An interface with exactly one implementation, where a second implementation is not even imaginable, is noise. It doubles your files and makes navigation slower. Add the interface when the second implementation arrives or when you need a boundary for testing. Adding it later is a thirty second refactoring in any modern IDE. You are not saving future time, you are spending present time.

Skip the mapper parade. Four nearly identical objects representing the same user, with hand written mapping between every pair, is a tax on every feature. For a small team, let the layers share simple data structures until you have a concrete reason to separate them. A concrete reason means the shapes actually need to differ, not the book said so.

Skip the deep folder ceremony. Five developers do not need the directory structure of a bank. You are not Google. That is fine, Google has other problems . Group code by feature, keep the dependency rule, and stop.

My filter is one question. If this abstraction disappeared, what would actually break, and when? If the honest answer is nothing and maybe someday, the abstraction is speculation. Speculation is fine in a design discussion and expensive in a codebase.

The cost nobody puts in the retro

Here is why I care about this beyond taste. A five person team has maybe four hundred productive hours a month, total. Every hour spent feeding ceremony is an hour not spent on the product, and small teams usually live in the phase where speed decides if the company exists next year. I have seen small products lose their market window while the team polished layers. The architecture was clean. The business was dead. That is the worst code quality outcome there is.

There is a team health angle too. Heavy ceremony codebases make new developers feel stupid for weeks, because simple changes require a tour of six files. Frustration like that compounds quietly.

So what I do on a small team is this. Take the dependency rule and the protected business core from Uncle Bob, those pay rent from day one. Treat everything else in the book as a menu, not a mandate, and order only when you are actually hungry. The cleanest architecture is the one where every piece can explain, in money or time or risk, why it deserves to exist.

Pax et bonum.