Agentic development changes what “good architecture” looks like. When implementation throughput is no longer the bottleneck, the old reflex to split everything into tiny services can add more drag than value. The better default for many teams is a slightly larger, cohesive deployable unit built with the best tools for each layer.
Radical simplicity made sense (then) Link to heading
For years, the “radical simplicity” architecture approach usually meant one move: small services with narrow responsibilities and strong boundaries. In the right context, that was rational.
Many copied the pattern and some have felt the sprawl strangling them. Think five services to do one job, plus coordination tax, integration drift, duplicated plumbing, and a local setup that took half a day to get every service talking to the others.
That trade-off used to be easier to justify because coding speed was constrained by human throughput.
Agentic development changes the constraint Link to heading
In agentic workflows, writing and refactoring code is cheaper. Spinning variants is cheaper, and generating test scaffolds is much cheaper. The expensive part is now coherence:
- The stack should be quickly understood end to end.
- Developers should be able to run it locally without friction.
- Changes should be validated quickly across boundaries.
When that’s the bottleneck, architecture should optimize for coherence first.
Build cohesive units, not service confetti Link to heading
A practical pattern is to package it as one deployable system, no matter how many internal layers it has. For example, a web application might have three distinct layers:
- UI
- Middle-tier API
- Data path (cache + database)
The reverse proxy belongs in that unit too.
It’s a deliberate, balanced monolith with explicit internal boundaries. You still get separation of concerns, but you drop a lot of cross-service friction:
- fewer network hops in the critical path
- fewer deploy and version-coordination events
- simpler observability topology
- easier local parity with production behavior
If those capabilities must always move together, deploy them together.
A concrete example Link to heading
A product-facing web application is a good example: every request path traverses UI, API, cache checks, and relational storage anyway. Instead of four separately deployed services plus an external reverse proxy, package the stack as one deployable unit:
- reverse proxy for routing/termination
- server-rendered or static UI layer
- API layer for business logic
- cache for hot paths/session acceleration
- database for durable state
Operationally, this gives you one release boundary and one rollback boundary. Architecturally, it keeps the team focused on domain boundaries instead of spending disproportionate effort on distributed-system boundaries between tightly coupled components.
Local DX determines whether this model works Link to heading
If this model is going to succeed, development should feel effortless.
The best tool I’ve found for that is overmind.
Overmind is a process manager built around Procfile workflows.
It launches processes together and clearly shows their logs in one screen, replacing fragile shell scripts and the ritual of opening six terminals to run commands in order.
Minimal example:
# Procfile.dev
proxy: caddy run --config Caddyfile
ui: npm --prefix ui run dev
api: go run ./cmd/api
cache: redis-server ./dev/redis.conf
db: docker compose up postgres
Run the full stack with:
overmind start -f Procfile.dev
Or even better, wrap that in a justfile so you type just start.
For agentic loops, this means you can watch agents propose or apply changes across layers and see the whole system react in one place.
Overmind is in need Link to heading
Overmind just works, and it’s great — but it needs contributors. Credit to Evil Martians for maintaining it.
When microservices still make sense Link to heading
That’s true when you have genuine independence:
- different scaling profiles that materially diverge
- strict fault isolation requirements
- team ownership that is truly decoupled
- compliance or blast-radius constraints that require hard runtime boundaries
But “future flexibility” alone is rarely enough. If everything ships together and breaks together, model it as one deployable unit until reality proves otherwise.
Choosing the best tool for the job Link to heading
The shift here is less ideological than practical:
- Keep architecture boundaries where they create leverage.
- Avoid boundaries that only create ceremony.
- Use specialized tools per layer inside a cohesive system.
- Optimize for fast, reliable end-to-end change.
With agentic tooling, teams can stop distributing complexity for ease. You can keep strong engineering discipline and still choose a larger monolith when that’s the sharper instrument.
The goal is shipping correct systems quickly, with confidence.