Teams keep asking what comes after microservices. They want a successor brand. I stopped giving them a topology name. Next is a goal, a set of tools, a budget, and an exit.
Teams keep asking me what comes after microservices. They want a successor brand. A slide they can take to a steering committee. Something that sounds as decisive as "we are going microservices" sounded in 2016. I stopped giving them a topology name. The next architecture is a goal, a set of tools, a budget, and an exit you can enforce. That loop sits on modules you already own. It does not sit on another fleet of nouns. The question is late, and that is useful I have been splitting and un-splitting Java systems for a long time. Hospital scheduling. Lending. Document pipelines. High-traffic digital platforms. The pattern repeats. A team inherits a monolith that is hard to change. Someone draws eleven boxes. Six months later the boxes are real, the release train is still shared, and Tuesday is still the day nobody wants to deploy. I already wrote about the seven decisions that decide whether that split works. This piece is the question that comes after those decisions: if microservices were the destination, why are so many good teams walking back toward fewer deployables, and why did "agents" show up in the same conversation? Because the destination was never "more processes." The destination was independent change plus coordinated work. Microservices were an expensive way to buy the first. They were a terrible way to buy the second. That tax is now visible. Platform teams exist because the tax got a department. Founders feel it faster: one Spring Boot backend, two frontends, and a calendar that does not have room for a service mesh. The part we keep missing is the glue. The saga service. The "orchestrator" that only exists to call seven other services. The BFF that fans out to twelve hops and still cannot explain a failed Tuesday. Those boxes were never capabilities. They were coordination we froze into a network. An agent is a better unit for that job. Not because it is fashionable. Because the path changes more often than the schema. Small services were never the same job as a coordinated system A microservice earns its keep when four things are true at once: a team can deploy it on a Tuesday without a Slack thread it can fail without taking the rest of the product with it it owns a consistency boundary you can explain in one sentence the operational cost (tracing, contracts, on-call, pipelines) is cheaper than the pain it removed Most programs I joined had the boxes. Few had all four. What they had instead was a distributed monolith: shared libraries pinned across repos, a schema that still leaked across "independent" services, and an on-call rotation that owned four codebases nobody fully understood. That is not a moral failure. It is what happens when you copy a Netflix slide into a ten-person team. The honest post-microservices move is not shame. It is a cheaper unit of coordination. An agent earns its keep when four different things are true at once: you can name the goal in one sentence, and you can name when to stop every side effect goes through a tool you own (a port, not a raw HTTP hop to a noun you invented last quarter) a budget exists: tokens, steps, wall clock, money a human owns the failure, and the audit trail can replay what the loop believed flowchart LR subgraph boxes [Eleven boxes] USER --- ORDER --- PAY --- SCHED AUTH --- MAIL --- JOB --- CACHE PIN[Shared lib pin] end subgraph job [The actual job] G[Goal] T[Tools] B[Budget] E[Exit] end boxes -->|coordinated change| job Small services optimize for deploy isolation. An agentic loop optimizes for a path that is allowed to change without a new repo. Those are different jobs. Treat them as different receipts. Three agentic options that are actually on the table I treat this as a design choice, not a prophecy. Option What you ship When it is honest Module-as-tool One deployable. Packages are seams. Modules expose ports the loop can call. One to three teams, one consistency story, workflows that still share a transaction Capability agents Three to five specialist loops over coarse modules (intake, match, score) A real workflow, cost, or ownership boundary already exists Supervisor team A supervisor plus specialists with typed handoffs and one shared budget The work is a pipeline of judgments, not a pipeline of tables flowchart TB subgraph A [Default: module-as-tool] LOOP[Agent loop] API[One API process] LOOP --> API API --- CAT[Catalog] API --- BILL[Billing] API --- ID[Identity] API --- JOBS[Jobs] end subgraph B [Capability agents] IN[Intake agent] --> MOD[Coarse modules] MT[Match agent] --> MOD SC[Score agent] --> MOD end subgraph C [Supervisor team] SUP[Supervisor] --> SP1[Specialist] SUP --> SP2[Specialist] SUP --> SP3[Specialist] BUD[One budget] SUP --- BUD end I default to the first. In Spring Boot that now has two names people can search: a modular monolith, and a tool port. Packages become the contract. Events stay in-process until a module proves it needs a wire. The agent does not own the database transaction. The module that already owns the table does. Tests fail when someone reaches across a seam they do not own, and they fail when a tool is called without a budget. That is not nostalgia for 2008. It is the monolith we should have written before we discovered Kubernetes, plus a loop for the work we used to hide in an orchestrator service. When I ship my own products, this is the shape I keep choosing. One API process. Clear packages. A second process only when the workload is genuinely alien: an LLM scoring job with a different latency budget, or a code runner that must not share a JVM with the product API. I do not split "Candidate" from "Application" because the nouns look tidy on a whiteboard. I do not stand up a service per tool because the canvas has a node for it. The middle option is the one conference talks skip. Document intake, matching, and scoring can be three agents. They should not be thirty services. Each agent still needs contracts, timeouts, and tracing at the tool boundary. They just stop pretending that every hop is a team. I have drawn that graph enough times to be boring about it. Sequence, parallel, conditional, supervisor. Those are control-flow types. They are not a reason to mint a deployable. The third option is a team of agents. I have built that shape in a lab: bounded roles, typed verdicts, one budget for the run. It is useful when the work is a chain of judgments (plan, implement, review). It is expensive when the work is "update an order." If you cannot name the handoff type, you are drawing a fleet again, only with warmer nouns. An agent replaces glue. It does not replace a boundary. This is the part of the "what is next" conversation I will defend, and the part I will not. An agent replaces the services we invented because we could not keep a workflow in one place: the saga orchestrator that only exists to call seven others the BFF that fans out to twelve hops and still returns a shrug the approval microservice that is a human checkbox with a REST wrapper the "notification" and "enrichment" boxes that never owned a consistency story It does not replace a consistency boundary. It does not replace a scale axis. It does not replace a pager. flowchart TB subgraph loop [Agent loop] G[Goal] --> T[Tools] --> BU[Budget] --> E[Exit] end PORT[Port / provider] subgraph product [Product modules, one process] J[Jobs] --- AT[Attempts] --- OR[Orders] --- TX[DB transaction] end subgraph ops [Same as a batch job] Q[Queue] --- K[Idempotency key] --- AU[Audit] --- OW[Owner] end loop --> PORT --> product --> ops X1[Not a saga service] X2[Not a 12-hop BFF] X3[Not a service per tool] If you extract anything around AI, extract the workload that has a different cost and blast radius. Keep the product language (jobs, attempts, itineraries, orders) in the module that already owns the database transaction. Let the model si...