Architecture
11 min

The Return of the Monolith: Architecture in the AI Era

Microservices were never primarily a technical pattern. They were an organisational one: a way to let fifty teams deploy independently. AI agents knock out both legs of that argument – small teams now ship what used to take departments, and agents work best when they can see the whole system at once. The modular monolith becomes the pragmatic default. Not out of nostalgia, but out of arithmetic.

Twelve people, 23 services

Here is a pattern we keep meeting in architecture audits: a startup of twelve people, nine of them engineers. The platform consists of 23 microservices spread across 23 repositories. Between them sit four message queues, a service mesh and a handful of home-grown shared libraries in three different versions. Three of the nine engineers form a "platform team" whose entire job is keeping this machinery alive.

What does that cost per feature? Take something trivial: customers should be able to enter a voucher code at checkout. In this system the change touches the checkout service, the pricing service, the order service and the frontend BFF. Four repos, four pull requests, four deploys in the right order, a contract update between pricing and orders – and when the first test fails, the hunt begins in distributed tracing: which of the four services swallowed the voucher?

A feature that would be an afternoon in a single codebase takes a week here. Not because the logic is hard, but because the architecture slices every change into pieces and scatters them across network boundaries. The team has bought itself the coordination costs of a large enterprise – without the enterprise.

Why microservices won the 2010s

To be fair: microservices did not win by stupidity. They solved a real problem – it just was rarely a technical one.

In 1967 Melvin Conway made the observation that later became Conway's law: systems mirror the communication structure of the organisation that builds them. If you have fifty teams that want to release independently, you need an architecture in which fifty parts can be deployed independently. The monolith, with its single release train everyone had to wait for, was an organisational bottleneck for Amazon, Netflix or Spotify. Microservices removed it.

Add to that some genuine technical wins: scaling hot paths independently, different languages for different problems, containing failures to one service. All legitimate – at the scale it was invented for.

Then came the cargo-culting. Conference talks from companies with a thousand engineers became blueprints for teams of ten. The question "do we have the problem microservices solve?" was replaced with "this is how it's done now". Netflix needs hundreds of independently deployable services. A twelve-person startup does not. It built them anyway, because that is what the template looked like.

The pendulum swinging back is not new either. Segment described publicly as early as 2018 how it moved from microservices back to a monolith after the operational overhead got out of hand. In 2023 Amazon Prime Video reported on its own tech blog that its audio/video quality-monitoring service had been moved from a distributed serverless design built on Step Functions and Lambda into a single process – cutting infrastructure costs by roughly 90%. DHH and 37signals have preached the "majestic monolith" for years. Shopify runs one of the largest Rails codebases in the world as a deliberately modular monolith.

What is new is that AI agents change two inputs to this equation at the same time.

What agents change, part one: context

A coding agent is exactly as good as what it can see at once. That is not a footnote; it is the defining property of these tools. An agent that can follow a call path from HTTP handler through business logic down to the database table inside one repository makes better decisions than one that hits a service boundary and finds nothing on the other side.

Seen from this angle, microservices are an architecture of hidden context. The logic of a single user action – "redeem voucher" – is smeared across N repositories. From the repo where the agent starts, all it sees is an HTTP call into the void. What happens on the other side, which fields the contract really expects, which service triggers the side effect that produces the bug: none of it is visible from where it stands. It has to discover, clone and correlate – assuming it even has credentials for the other repos.

Concretely, an agent in a microservice estate pays the integration tax twice:

  • Once to discover. Which services are involved? Where does the code live? Which version of the contract is current – the one in the OpenAPI document or the one actually deployed? In practice contracts always drift, and the agent only sees one side.
  • Once to change. Four repos, four branches, four PRs that have to match, four deploys with dependencies between them. Every boundary is a point where an inconsistency can slip through unnoticed, because no compiler and no type system checks across a network boundary.

Then there are tests. In a monolith an agent can run the entire suite locally and know within minutes whether its change breaks anything else. In a microservice estate that answer exists only in an integration environment the agent usually cannot reach – and which, if we are honest, works only half-reliably for humans too.

Practitioner reports and early benchmarks from this year point the same way: agents produce more correct multi-file changes on modular monoliths than on microservice estates, simply because the full call graph is visible in one repository. The numbers are still too thin for precision, but the mechanism is obvious. Whoever sees the whole pitch plays better.

What agents change, part two: team size

The second lever is organisational, and it goes straight at Conway's law.

In "The Two-Person Team That Replaces a Department" we described how agents shift the productivity of small teams: two or three people now ship what needed a department a few years ago. That is not a marketing line; it is what we see with clients.

Followed through, it means this: if three people build the product, there are no team boundaries for an architecture to mirror. There is no checkout team that needs to deploy independently of the pricing team, because there are not two teams. The organisational reason for microservices – independent release cadence for independent teams – simply dissolves for the vast majority of companies. What remains is the cost.

Conway's law still holds. It is just that the architecture now mirrors the actual organisation: one small team, one system.

The modular monolith, concretely

To many people "monolith" sounds like the big ball of mud they fled ten years ago. That is not what this is about. This is about the modular monolith: one deployable, hard internal boundaries.

What that means in practice:

  • One deployable. One codebase, one build, one deploy. The voucher feature is one PR, one review, one release.
  • Modules with an explicit public interface. Checkout, pricing, orders, billing are separate modules with clearly declared public APIs. What is not exported is invisible from outside – not by convention, but by rule.
  • Enforced boundaries. Import linting that fails CI on a violation. Module ownership that defines who may change an interface. Shopify built Packwerk for this; in other ecosystems tools like dependency-cruiser, ArchUnit or Nx module boundaries do the job.
  • One database, clear ownership. One schema per module, or at the very least an unambiguous rule about which module owns which tables. No module writes to another module's tables; cross-module questions go through the interface.
  • Async in-process first. Domain events over an internal event bus, not over Kafka. The same decoupling, without the network, without the queue, without the ops team.
  • Extract only for a measured reason. A module becomes a service only once it demonstrably needs to scale differently, be isolated differently or be owned by a different team. Not before, not pre-emptively.

And here is the twist that makes the whole thing work in the AI era specifically. The classic reason monoliths rotted was never the architecture. It was people under deadline pressure skipping a boundary "just this once": a direct database access bypassing the module, an import from the internals folder because it was Friday afternoon. A hundred such decisions later, the monolith was a ball of mud.

That exact kind of discipline is what an agent supplies without tiring. It never gets bored of honouring a lint rule. It does not skip a boundary because the release is tomorrow. As a reviewer it flags the hundredth violation as consistently as the first. The weakness monoliths historically failed on is precisely the one a tireless checker compensates for. That makes the modular monolith not just viable again, but for the first time robust against its own decay.

Where microservices still win

Now the honest counter-case, because "monolith for everyone" would be the same cargo-culting in reverse.

There are cases where microservices remain the right answer:

  • Genuinely independent scaling. Video transcoding and CRUD forms have nothing in common – not in resource profile, not in cost curve, not in hardware. Such paths belong apart.
  • Regulatory or data isolation. If payment data has to live in a PCI zone or health data in its own infrastructure, the service boundary is a compliance boundary, not an architectural taste.
  • Real polyglot needs. An ML inference path in Python next to a core system in Go or Java is a legitimate reason for two deployables.
  • Organisations above roughly 100 engineers with genuinely independent release cadences. There Conway's law applies in its original direction, and the architecture should reflect it.
  • Blast-radius isolation for critical paths. Login must not go down because the reporting module has a memory leak.
  • Boundaries to third parties. A partner API gateway that talks to an external company is by nature its own system.

A common rule of thumb for 2026: modular monolith for roughly 10 to 100 engineers; microservices above that when real scaling, polyglot or isolation reasons exist. Rules of thumb are not laws, but this one maps the reality of most companies better than the blueprints of the 2010s.

And one warning that must not be left out: a monolith with no boundaries plus an agent generating code fast is the fastest route to a big ball of mud ever invented. Everything said above about discipline holds only if the boundaries exist and are checked by machine. An agent writing into a large codebase with no lint rules and no module structure will produce in a week the coupling a human team would have needed two years for. The architecture is the prerequisite, not the by-product.

Practical guidance

If you are starting a system today or realigning an existing one, five rules serve you well:

  1. Start as a modular monolith. Not as a monolith with the intention of adding modules later – the intention does not survive the first sprint.
  2. Boundaries on day one. Module structure, import rules, ownership file, CI check. Whatever is meant to come later does not come.
  3. Measure before you extract. A service is born from a profiler result, a compliance requirement or a team boundary – never from a gut feeling.
  4. Keep the agent's context small, even in the monolith. A README or an AGENTS.md per module describing purpose, interface and rules. The agent then sees the whole when it must and the module when that suffices. This ties in with what we described in "The Spec Is the New Source Code": the description of the system becomes the primary artefact the agent works with.
  5. The way back from microservices: strangler fig in reverse. First consolidate the repositories into a monorepo – that alone gives the agent its visibility back without changing a single deployment. Then pull services that have no measured reason to exist back in as modules, one at a time. The network boundary becomes a function boundary, the queue becomes an in-process event. We described the detailed approach to modernising existing systems in "Modernizing Legacy Systems with AI Agents".

Conclusion

Microservices solved an organisational problem most companies never had – and that the few who did have it are now losing to AI agents. If three people ship what used to need a department, there are no team boundaries left for an architecture to mirror. And if the most important new tool in the stack works best when it sees the whole system at once, then an architecture that scatters context across twenty repositories is not modern. It is in the way.

The modular monolith is the pragmatic answer: one deployable, hard boundaries, one database with clear ownership, and an agent enforcing the discipline monoliths used to fail on. Microservices remain the right tool for real scaling, isolation and organisational problems – not for startups that copied a Netflix template.

That is why at nh labs we start new systems as modular monoliths with boundaries from day one, and with existing microservice estates we consolidate the repositories first, before we even talk about deployables. Not because the monolith is nostalgic. But because the arithmetic that displaced it ten years ago comes out differently today.