The microservices conversation in 2026 looks different from 2018. Back then the question was "how do we split this monolith." Now it's "which parts should actually be split, and which should stay together as a modular monolith with an internal event bus." Teams that spent years decomposing applications into dozens of services are, in meaningful numbers, consolidating back — not into the old tangled monolith, but into something more deliberate (Enqcode). Event-driven architecture (EDA) sits underneath both trends, because it's not really a competitor to microservices or monoliths — it's a communication pattern you can apply inside either.
What actually broke with naive microservices
The core problem is mechanical: every function call that used to be in-process becomes a network call once you split a service boundary. That single change means you're no longer just writing business logic — you're handling partial failures, retry storms, circuit breakers, and eventual consistency as first-class concerns (Java Code Geeks). Rising cloud costs, added latency, operational overhead, and cross-team coordination friction are the concrete reasons companies are rethinking the reflexive "microservices by default" posture (Java Code Geeks).
Event-driven systems have their own distinct failure mode worth naming directly: instead of one thing crashing loudly and visibly, small inconsistencies creep in quietly across services, which makes them some of the hardest bugs to trace back to a root cause (Java Code Geeks).
Warning
Choreography vs. orchestration: the central design choice
Once you're committed to event-driven communication, the next decision is how services coordinate multi-step workflows that span service boundaries. Two patterns dominate:
- Choreography — no central coordinator. Each service listens for events and emits the next event based on its own local logic. It's decentralized and fits event-driven principles cleanly, but becomes hard to understand and debug as the number of participating services grows (Encore).
- Orchestration — a central coordinator issues commands to each service and reacts to their results, maintaining the saga's state explicitly. This gives you visibility and easier testing, at the cost of a potential single point of failure and tighter coupling to the orchestrator (Encore).
The 2026 consensus has settled into a pragmatic middle: choreography for simple, naturally decoupled flows; orchestration for anything where sequencing, visibility, and compensation logic actually matter; and hybrid designs that use both within the same system depending on the subdomain (Encore).
| Choreography | Orchestration | |
|---|---|---|
| Coordination | Decentralized, event-driven | Centralized coordinator/orchestrator |
| Visibility into workflow state | Low — must be reconstructed from event history | High — orchestrator holds explicit state |
| Debuggability | Harder as service count grows | Easier — single place to trace flow |
| Coupling | Loose between services, but implicit | Explicit coupling to orchestrator |
| Best fit | Simple, few-step flows | Complex, multi-step flows needing compensation |
The saga pattern and compensating transactions
Distributed transactions don't have ACID guarantees across service boundaries, so the saga pattern trades strict consistency for eventual consistency with explicit recovery logic: a sequence of local transactions, each paired with a compensating transaction that semantically undoes it if a later step fails (Microsoft Learn). If step 3 of a 5-step order-fulfillment saga fails, the system runs compensations for steps 2 and 1 rather than attempting a cross-service rollback that doesn't actually exist at the infrastructure level.
Orchestrated saga (order placement):
1. OrderService: create order (pending)
2. PaymentService: charge card -- fails
-> compensate: OrderService: cancel order
-> compensate: InventoryService: release reserved stock
The outbox pattern: fixing the dual-write problem
A subtle but extremely common bug in event-driven systems: a service updates its database, then separately publishes an event about that update. Those two operations aren't atomic — if the process crashes between them, or the message broker is briefly unavailable, the database and the event stream disagree about what happened (Encore). The outbox pattern fixes this by writing the event into an "outbox" table inside the exact same database transaction as the state change, then using a separate relay process (often CDC-based) to publish outbox rows to the event stream asynchronously (Encore). This guarantees the event is eventually published if and only if the state change actually committed.
The modular monolith comeback
Perhaps the most notable 2026 trend is what looks, on the surface, like a retreat: teams that broke applications into dozens of microservices are reassembling them — not into the old tightly-coupled monolith, but into a modular monolith with clean internal module boundaries and, often, an internal event bus replacing what used to be inter-service HTTP calls (Enqcode). This isn't a rejection of event-driven design — it's a rejection of paying network-call latency and operational overhead for boundaries that didn't need to be physical processes in the first place.
The practical framing that's emerged: event-driven is a pattern you apply inside whichever structural choice fits your team and scale — a modular monolith can use an internal event bus for decoupling without the operational cost of a message broker and distributed tracing across dozens of deployables (Medium: Tara Prasad Routray).
Decision framework for 2026
Rather than defaulting to microservices because that's the industry-standard conference-talk architecture, the working framework teams are converging on:
- Start modular, not distributed. Build clean module boundaries inside a single deployable first. Split into a separate service only when you have a concrete, measured reason — independent scaling needs, a genuinely separate team owning it, or a hard deployment-cadence mismatch.
- Pick choreography or orchestration per-workflow, not globally. A simple two-step flow doesn't need a saga orchestrator; a checkout-to-fulfillment pipeline with five failure-prone steps probably does.
- Adopt the outbox pattern anywhere you publish events tied to a state change. It's cheap insurance against silent data/event divergence that is otherwise very hard to debug after the fact.
- Invest in observability before you split further. Distributed tracing, structured event logging, and correlation IDs across service boundaries are prerequisites for event-driven systems to be debuggable at all — not optional polish added later.
Tip
Sources: Encore: Event-Driven Architecture in 2026, Microsoft Learn: Saga Design Pattern, Java Code Geeks: Microservices vs Monoliths in 2026, Enqcode: Rethinking Microservices in 2026, Medium: Monolith vs Microservices vs Event-Driven Architecture
Get new posts as they publish
No spam — just the next post, straight to your inbox.