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. Narrow responsibilities. 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 felt like launching a satellite.
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:
- Can the stack be quickly understood end to end?
- Can developers run it locally without friction?
- Can changes 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)
And yes, why not include the reverse proxy onboard.
It’s a deliberate, balanced monolith with explicit internal boundaries. You still get separation of concerns, but 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 together.
A Concrete Example Link to heading
Think of a product-facing web application where 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 Is Where This Either Works or Dies 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.
No fragile shell scripts. No “open six terminals and copy these 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 with a justfile to type: just start.
For agentic loops, this is a breakthrough. Agents can propose or apply changes across layers, and you can watch the whole system react in one place; making the feedback loop immediate.
Overmind is in need Link to heading
Side note, Overmind just works, it’s great… but it needs contributors. Shout out to Evil Martians for maintaining it.
This Is Not “Never Use Microservices” Link to heading
Microservices still make sense 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, tests 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.
Agentic development gives us permission to 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 was never “smallest services possible.” The goal is shipping correct systems quickly, with confidence. In this era, that often means bigger units, clearer boundaries, and better local tooling.