Event-Driven Architecture & P2P
Introduction
Picture the marketplace's checkout the way you'd first draw it. An order arrives, and orders gets to work: call billing, call inventory, call notifications, call analytics. Four arrows out of one box. It reads like a to-do list, and it runs like one.
Now it's 2 a.m. and the notifications service dies. Checkout starts failing.
Sit with that for a second: customers cannot buy things because the service that sends emails is down. Nothing about payment is broken. Nothing about stock. The caller simply wired its own fate to every name on its list — and one of those names stopped answering.
Two lessons ago, the coupling map showed one seam on that diagram that was different: orders→notifications carried only asynchronous events, and cutting there was clean. This lesson is about what happens when you take that observation to its logical end — when events stop being one seam and become the spine of the whole system. The previous lesson ended by pointing here: serverless functions are usually what an event spine wakes up.
In this lesson: the three couplings hidden in every synchronous arrow, the inversion that severs all three, what the word "event" precisely means (it's three different designs wearing one name), what the spine buys and what it charges, peer-to-peer — the style that deletes even the spine — and the ports-and-adapters trick that lets you change your mind later.
Scope: the machinery under the spine — queues, broker-vs-log, delivery guarantees — was taught in Fundamentals of System Design (Message Queues, Queue Models: Broker vs Log, Delivery Semantics) and is referenced, not repeated. Coordinating multi-step work over events is the next section's territory (Saga: Orchestration vs Choreography, Event Sourcing, CQRS).

Three Couplings in Every Arrow
Look closely at one synchronous arrow — orders → billing — and count what it actually welds together.
Space. The caller names its target. Somewhere in orders lives the knowledge that billing exists, where it is, and how to speak to it. New consumer of order data? That's an edit to orders.
Time. The target must be up right now. The previous lessons priced this: a synchronous chain's availability is the product of every link. Four calls at 99.9% each and checkout is down for the sum of everyone's bad days.
Knowledge. The caller encodes what happens next. orders knows that an order means a charge, a stock decrement, an email, a metric. The business process lives in the caller's code — which means every change to the process is a change to orders.
Three couplings, one innocent-looking arrow — and a fan-out of four arrows means twelve. That's the checkout that died over email.
Everything this section has taught so far attacked these one at a time: tiers priced the arrow, the split moved it, serverless changed who runs its endpoints. The event-driven move is different in kind. It doesn't soften the arrow. It deletes it — and replaces it with something that points the other way.
The Inversion: Facts on a Spine
Here is the whole style in one move. orders stops issuing instructions and instead states a fact: order_placed, with the details attached. It writes that fact to a shared channel — the spine — and goes back to work. It does not know who reads the fact. It does not wait for them. It does not care, in the most architecturally productive sense of the phrase.
On the other side, billing, inventory, notifications, and analytics each subscribe to the facts they care about and own their reactions. The email is now the notification team's business, encoded in the notification service, deployed on their schedule.
Check the three couplings against this shape. Space: the producer names a topic, not a consumer — strangers can subscribe without orders learning their names. Time: the spine holds the fact; a consumer that's down reads it when it returns. Knowledge: what-happens-next moved out of the caller entirely — each reaction lives with its owner. All three welds, cut by one inversion.
The spine itself you already know how to build: it's a broker or a log — Queue Models: Broker vs Log taught the two shapes and why replayable logs changed this style's ceiling. What's new here is the architectural claim: when the spine carries the system's primary flow — not just one offloaded task — the boxes stop being a call graph and become a set of independent reactions to a shared stream of facts.
Notice what quietly disappeared: the coordinator. Nobody orchestrates checkout anymore; it emerges from subscriptions. Architects call that choreography — everyone dances to the music, nobody calls the steps — and its disciplined sibling, orchestration, gets a full lesson soon (Saga: Orchestration vs Choreography). Hold the word; you've now seen the thing.
What "Event" Actually Means (Three Different Things)
Before going further, a warning from the person who's written most carefully about this. Martin Fowler observed that "when people talk about 'events', they actually mean some quite different things" — and that conversations go sideways because the patterns get conflated. Three of them matter now; two get their own lessons later.
Event notification — the thin event. The fact says that something happened and little more: order_placed, id 4127. A consumer who needs details calls back and asks. Smallest events, one source of truth, but consumers still lean on the producer being up for the follow-up question.
Event-carried state transfer — the fat event. The fact carries the state: the whole order, items and totals and address. Consumers keep their own copy and never call back. Fowler's accounting is exactly the trade you'd expect by now: "greater resilience, since the recipient systems can function if the customer system becomes unavailable" — paid for with "lots of data schlepped around and lots of copies," which means copies that lag. You met that bill in Read Replicas & Replication Lag; here it arrives by design.
Event sourcing — the stream as the ledger. Go all the way: every state change is recorded as an event, and current state is just what you get by replaying them. The log stops describing the system and becomes it. That inversion deserves its own hour — Event Sourcing, next section — as does its frequent partner CQRS, which splits read models from write models. Today, just know the words point at different designs.
The practical payoff of the taxonomy is a sharper question at the whiteboard. Not "should we use events?" but: thin or fat? Thin keeps one truth and adds call-backs; fat buys resilience and buys staleness with the same coin. Most real spines carry both, chosen per fact — and now you can say why.

What the Spine Buys
Run the 2 a.m. failure again, this time against the spine.
Notifications dies. orders — which does not call it, does not know it, does not wait for it — keeps selling. The facts notifications would have read pile up on the spine, exactly the burst-absorbing behavior Message Queues taught, and when the service returns it drains its backlog and sends slightly late emails. Checkout never blinked. The failure was contained to the reaction that owned it — compare that with the availability product you computed two sections ago.
Now the quieter superpower. The analytics team wants order data. In the call-the-world design, that's an edit to orders: add the call, handle its failures, redeploy the most important service in the company for a dashboard. Against the spine, it's a subscription — the analytics service starts reading order_placed, and orders is never touched, never redeployed, never told. Whole capabilities attach to the system without the system noticing. That property compounds: it's how a company keeps shipping when it has hundreds of teams.
Which is not hypothetical. LinkedIn — where the log-as-spine idea was industrialized — publicly runs its event backbone at seven trillion messages a day across a hundred-plus clusters and a hundred thousand topics. At that scale, "who consumes this fact?" stops having a knowable answer — and that is the design working, not failing. Producers state facts; the organization subscribes.
Add the shape bonus you can now name from the serverless lesson: reactions are spiky, idle-heavy work — born to be functions the spine wakes per fact, billed by the millisecond. The styles in this section aren't rivals; they stack.
Drive It: Cut the Caller Loose
The inversion is the kind of thing you believe abstractly and then feel when a kill switch is in your hand.
Try this first: in call-the-world mode, kill notifications and watch checkout fail — then check the latency readout and notice checkout was paying for four round-trips even on good days. Press add a consumer and read the fine print: editing and redeploying orders. Now flip to event-spine mode and repeat everything. Kill notifications: checkout sails on while the dead consumer's backlog counts up; revive it and watch the drain. Add the same consumer: one subscription, producer untouched. The scoreboard underneath keeps the honest ledger — what each mode does to checkout's latency, its blast radius, and the cost of change.

What the Spine Costs
Every lesson in this section has paid for its superpower on the same page it earned it. The spine's bill has five lines.
The flow turns invisible. Fowler's warning, verbatim, because it's the one that bites hardest: "it can be hard to see such a flow as it's not explicit in any program text." There is no file where checkout is written down anymore — the process exists only at runtime, as a pattern of reactions. The 2 a.m. question changes from "why did this call fail?" to "where did my event go?" — and answering it needs the machinery this course builds in its observability section (Correlation IDs, Distributed Tracing).
The coupling moves; it doesn't die. Consumers parse event bodies. Rename a field in order_placed and strangers you've never met break in production. You traded compiler-checked coupling at call sites for runtime-checked coupling in schemas — looser, but sneakier. The discipline is versioned, compatible schemas; Schema Evolution & API Versioning taught the rules, and event spines are where they earn rent.
Reactions can feed back. A consumer that emits in response to events, consumed by another that does the same, builds loops nobody designed. A bad deploy can echo through the mesh as an event storm — choreography's dark twin: when no one calls the steps, no one can call them off.
Readers lag. Fat events mean copies, and copies mean the user who updates their address and sees the old one on the next screen. Eventual consistency isn't a bug here; it's the purchase. Design the UX for it or don't buy it.
The substrate's fine print applies. Facts arrive at-least-once and sometimes out of order — Delivery Semantics named the lies, Idempotency as a Discipline built the armor. One sentence of it here: a consumer that isn't idempotent will eventually be betrayed by its spine.
And the honest boundary: some interactions are conversations, not announcements. "Charge this card — did it work?" needs its answer in-line; forcing it through a fire-and-forget spine turns one question into a saga. Mixed systems — synchronous where answers matter, events where reactions do — aren't a compromise. They're the design.
P2P: Now Delete the Spine Too
Every topology so far kept a center — a server everyone calls, or a spine everyone reads. Peer-to-peer asks the radical follow-up: what if there's no center at all? Every node is both client and server; peers find each other and exchange directly.
Where that shape rules, it's unbeatable, and the reason is a property no centered design has: demand creates supply. In a BitTorrent-style swarm, every downloader is also an uploader — the more popular a file gets, the more capacity exists to serve it. A centered system melts under its biggest hit; a swarm gets stronger. The same logic powers realtime media (you met the mesh-vs-SFU trade in the WebRTC lesson) and trustless ledgers, where the entire point is that no single party owns the record.
So why isn't your marketplace peer-to-peer? Three walls, each fatal on its own:
- State needs an owner. Inventory is a fact with consequences; "the swarm thinks there are 3 left" is not a number you charge cards against. Every lesson of the data course assumed an accountable owner — P2P dissolves exactly that.
- Trust needs an anchor. Peers are strangers' machines. Verifying them is either impossible or it's a blockchain — and consensus among strangers is the most expensive way to agree that computer science has produced.
- Nobody pages a swarm. Operations, upgrades, compliance: with no center, there's no one accountable when it breaks.
The style isn't dead — it moved to where its one superpower pays: distributing content that's identical for everyone, carrying media between the people already talking, and keeping ledgers no one should own. Business state kept its center, and should.

The Hexagonal Beat: Keep the Core Deaf to All of This
One short beat before the decision, because it changes how expensive your choice is to reverse.
Nothing in "an order was placed, decrement stock" cares whether the news arrived as an HTTP call or an event. That's business logic. What varies is the delivery. The ports and adapters shape (you'll also hear hexagonal architecture) takes that seriously: the core exposes ports — "place order," "reserve stock" — as plain interfaces, and thin adapters translate the outside world into port calls. A REST adapter today. An event-spine adapter tomorrow. Both, during the migration.
Do this and the styles in this section stop being marriages and become configurations: the monolith-to-services split gets easier (your modules already talk through ports), the sync-to-events move stops touching business logic, and testing gets the seam Fowler promised back in the tier lesson. Skip it, and every style change is open-heart surgery.
That's the whole beat: keep the core deaf to transport. It's one sentence of discipline that keeps every door in this section open.
The Decision This Lesson Enables
The test that sorts every interaction in your system fits on a sticky note: is this an announcement or a conversation?
Announcements — something happened; the world may react. Order placed, user signed up, stock changed, payment settled. (The industry word is events.) These want the spine: fire the fact, let reactions subscribe, absorb bursts, add consumers freely. If the producer doesn't need the answer to proceed, it shouldn't wait for one.
Conversations — I need your answer to continue. Authorize this card. Is this item in stock right now? (The industry words: commands and queries.) These stay synchronous, and that's not a failure of nerve — an answer needed in-line is the definition of request/response.
Run the marketplace through it and the architecture writes itself: checkout's card-authorization is a conversation; everything downstream of "the order exists" — email, analytics, search indexing, the loyalty points — is announcements on the spine, reacted to by services (or serverless functions) that each own their step. The previous three lessons' verdicts don't move: the core stays a modular deployable, notifications lives across its clean seam, and the seam's traffic is now precisely specified — facts, flowing one way.
Two review questions expose an event architecture that hasn't been thought through, and they're the ones to have ready:
"Where is the business process written down?" — if the answer is "nowhere, it emerges," ask how you'll debug it at 2 a.m., and budget for the tracing machinery honestly.
"Who breaks if this event changes shape?" — if the answer is "we don't know," the coupling didn't disappear. It went underground.
Mental-Model Corrections
"We use Kafka, so we're event-driven." Using a queue somewhere is a tool; events as the spine is a style. The test is behavioral: can a new consumer attach without any producer changing? Does the producer learn outcomes? If orders still waits on four answers, you bought a broker, not an architecture.
"Fire-and-forget means unreliable." Usually backwards. A fact written to a replicated log persists; a missed HTTP response is simply gone. What you gave up is the in-line answer — reliability of delivery is the substrate's job, and Delivery Semantics told you exactly which promises exist.
"Events remove coupling." They move it. Space and time decouple; meaning doesn't — every consumer is coupled to the event's schema, invisibly. Renaming a field is now a distributed breaking change. Govern schemas or rediscover the distributed monolith, events edition.
"Everything should be an event." Conversations exist. A caller that needs the answer to proceed is request/response by definition, and forcing it through the spine turns one question into a multi-step saga. Mixed systems are the norm because the test is per-interaction, not per-system.
"P2P is dead tech." It relocated to where demand-creates-supply wins: content swarms, realtime media, public ledgers. What died is putting owned business state on strangers' machines — which was never the style's job.
Key Takeaways
- Every synchronous arrow welds three things: who you call (space), whether they're up (time), what happens next (knowledge). The 2 a.m. checkout that died over email died of all three.
- The event inversion severs all three: producers state facts on a spine; consumers own reactions. Kill a consumer and its backlog waits; add one and no producer changes; the process becomes choreography.
- "Event" is three designs, not one word: thin notifications (one truth, call-backs), fat state-carrying events (resilience bought with staleness), and the stream-as-ledger (Event Sourcing, soon). Pick per fact — thin or fat is the real question.
- The bill is real and specific: invisible flows (trace or suffer), coupling relocated into schemas, feedback storms, lagging readers, and at-least-once fine print. Announcements ride the spine; conversations keep their answers.
- P2P deletes even the spine — unbeatable where demand should create supply, wrong wherever state needs one accountable owner. And the hexagonal beat keeps your core deaf to all of it, so today's choice stays reversible.
The style palette is complete: integrated, split, metered, event-spined, and — for the rare right case — centerless. What's left is the part interviews actually probe: choosing. Next — Choosing a Style: The Rubric: constraints in, style out, and the honest sentence that defends the pick.