Intuition What this page is
The parent note taught you the five styles. This page does one thing: it hands you a scenario, you forecast the answer, then we prove it step by step . By the end you will have seen every "shape" of problem this topic can throw at you — every quadrant of the decision space, the degenerate cases (a team of one, a bill that rounds to zero), the limiting cases (traffic → 0, traffic → huge), a real word problem, and an exam twist.
Nothing here contradicts the parent. It just goes deeper on the numbers and the choosing .
Because the whole page is about counting connections and dollars, let me name the few quantities we will keep re-using — in plain words, with a picture in mind — before they appear anywhere else.
Definition Every symbol you will meet (read this first)
producer ::: a piece of code that emits an event — announces "something happened."
consumer ::: a piece of code that reacts to an event.
n ::: the count of producers — how many announcers there are.
m ::: the count of consumers — how many reactors there are.
N ::: how many times a serverless function runs in the billing period (invocations).
GB-seconds ::: a unit of "memory held for time" — hold 1 gigabyte for 1 second = 1 GB-second. It measures how much work×memory the cloud rented you. In the worked examples below I abbreviate this to "GB-s" — same thing, shorter.
O ( ⋅ ) ::: read "on the order of." We ignore constants and ask only how fast a number climbs as the system grows. O ( n ⋅ m ) climbs like a rectangle's area; O ( n + m ) climbs like a straight line. See Scalability — Horizontal vs Vertical .
Now that n , m , N and O ( ⋅ ) are earned, here are the two formulas everything on this page plugs into.
Two more plain-words ideas we lean on for the team/scaling examples, defined here before they appear:
Definition The three "drivers for splitting" (why anyone breaks a monolith apart)
Whenever we weigh microservices, we score exactly three benefits — each is a reason to give a piece its own service (parent §4):
Independent deployment ::: you can ship a change to one piece without redeploying the whole app.
Independent scaling ::: you can run more copies of just the busy piece, not the whole stack. See Scalability — Horizontal vs Vertical .
Team autonomy ::: a separate team can own the piece end-to-end. Conway's Law says your architecture ends up mirroring your org chart.
If all three score near zero, splitting buys nothing and you keep a monolith.
Now enumerate the whole space. Every architecture decision is really a point in a grid. Below are the case classes — think of them as the quadrants and edge cases of our topic. Each worked example later is tagged with the cell it fills.
#
Case class
The knob that moves
Degenerate / limiting version
C1
Small team, simple CRUD
team size → small
team size = 1 (a solo dev)
C2
One data, many views
number of view types grows
exactly 1 view (MVC is overkill)
C3
Many independent reactions
consumers per event grows
1 producer, 1 consumer (events overkill)
C4
Fan-out wiring cost
n producers × m consumers
n = 1 or m = 1 (no savings)
C5
Independent scaling need
one part is hot, rest cold
all parts equally loaded (split useless)
C6
Bursty / idle traffic
invocation count N
N → 0 (idle) and N → huge (steady)
C7
Real-world word problem
mixed drivers
e-commerce at launch vs at scale
C8
Exam twist
a "gotcha" that inverts the naive answer
"microservices first" trap
Let us start here because it produces the single most-cited number in event-driven advocacy, and it is easy to get wrong at the edges.
The figure shows the two shapes side by side: on the left , direct calls — every violet producer draws a magenta line to every orange consumer, making a dense mesh. On the right , the broker — the magenta square in the middle — turns that mesh into two simple fans, so each dot connects only to the hub. Keep this picture in view for the counting below.
Worked example C4 — Direct calls vs a broker, general case
You have n = 4 services that each announce things, and m = 5 services that each need to react. Compare the number of connections you must wire and maintain under direct calls vs an event broker .
Forecast: Guess both numbers before reading. Direct = ? Event = ? Which is bigger?
Direct calls. Every producer must know and call every consumer that cares. Worst case each of the 4 producers wires to all 5 consumers.
direct = n × m = 4 × 5 = 20
Why this step? With direct calls the producer holds the address of each consumer (spatial coupling). No shortcut — each pairing is a real line of code, which is why the left of the figure is a full mesh.
Event broker. Each producer connects only to the broker (n lines). Each consumer subscribes only to the broker (m lines). Nobody wires to anybody else.
event = n + m = 4 + 5 = 9
Why this step? The broker is the single hub (the magenta square on the right of the figure) — see Message Queues and Brokers . It absorbs the many-to-many mesh into two simple fans, so we add the two sides instead of multiplying them.
The saving. 20 vs 9 — and the gap explodes as the system grows, because n ⋅ m is quadratic while n + m is linear.
Why this step? We compare the two totals to see which architecture we are actually recommending — the whole point of the count is the decision it drives.
Verify: Units are "connections," dimensionless counts — consistent on both sides. Sanity: at n = m = 10 you'd get 100 vs 20 ; the broker wins by more. This is the structural argument in the parent's [!formula] callout. Related idea: Coupling and Cohesion — we traded spatial coupling for one hub.
Worked example C4 (degenerate) — When the broker saves nothing
Now n = 1 producer and m = 1 consumer.
Forecast: Does the broker still help?
Direct: n × m = 1 × 1 = 1 .
Why this step? One producer, one consumer — a single direct line covers it.
Event: n + m = 1 + 1 = 2 .
Why this step? Even at the smallest scale the broker still needs one line in and one line out, so it can never be fewer than 2.
Result: the broker is worse — 2 > 1 ! You added a hop for nothing.
Why this matters: the O ( n + m ) advantage is asymptotic. At the smallest scale the constant overhead of the broker dominates. This is exactly the parent's warning: "events hurt for simple request–response."
Verify: 1 < 2 confirms direct is cheaper here. Rule of thumb: the broker pays off once n ⋅ m > n + m , i.e. once both sides exceed 1 meaningfully.
Recall When does the broker start winning?
Solve n ⋅ m > n + m for the smallest symmetric case ::: at n = m = 2 : 4 > 4 is false (tie); at n = m = 3 : 9 > 6 true — so the broker wins from about 3×3 upward.
This is the "quadrants" of serverless: traffic can be near-zero (idle), bursty, or huge-and-steady. We compute all three from one formula.
In the figure the magenta line rises with N (serverless is O ( N ) — every call costs) while the violet dashed line is flat at $70 (a reserved server you pay for regardless). The orange dotted crossover marks where they meet: left of it serverless is cheaper, right of it the flat server wins. The navy dot marks our 100-million-call worked example.
Worked example C6 (limit → 0) — The idle app
A hobby function, 128 MB memory, runs 200 ms per call. Prices (typical FaaS): \text{price}_{\text{gbs}} = \ 0.0000166667p er GB − seco n d , \text{price}_{\text{req}} = $0.0000002p er r e q u es t . T hi s m o n t hi tw a sc a l l e d N = 1000$ times.
Forecast: Will the bill be dollars? Cents? Fractions of a cent?
GB-s per call. Memory = 128 MB = 128/1024 = 0.125 GB . Time = 0.2 s .
GB-s per call = 0.125 × 0.2 = 0.025
Why this step? GB-s (our GB-seconds abbreviation) is the "memory rented × time held" unit — we must convert MB→GB and ms→s so the units match the price.
Compute cost. N × GB-s × price gbs = 1000 × 0.025 × 0.0000166667 = 0.000416667 .
Why this step? This is the first term of the cost formula — the money the cloud charges for actually running (memory × time), summed over all N calls.
Request cost. N × price req = 1000 × 0.0000002 = 0.0002 .
Why this step? This is the second term — a flat fee charged just for invoking the function, independent of how long it ran. We must add it or we undercount.
Total. 0.000416667 + 0.0002 = 0.000616667 dollars ≈ $0.0006 .
Why this matters: this is the parent's "idle cost ≈ 0." You pay a tiny fraction of a cent. A reserved server would cost several dollars/month sitting idle — see Cloud Computing — IaaS PaaS FaaS .
Verify: Units: [\text{count}]\times[\text{GB·s}]\times[\ /\text{GB·s}] = $$. ✓. Sanity: sub-cent for 1000 tiny calls is exactly why serverless dominates the idle quadrant (far left of the figure).
Worked example C6 (limit → huge, steady) — When a plain server wins
Same function, but now N = 100 , 000 , 000 invocations/month (steady, high). Compare the serverless bill to a reserved server costing a flat $70/month that can handle this load.
Forecast: Which is cheaper at 100 million calls?
Compute cost. 100 , 000 , 000 × 0.025 × 0.0000166667 = 41.6667 dollars.
Why this step? Same first term as before, just with a much larger N — the run-time charge scales linearly with call count.
Request cost. 100 , 000 , 000 × 0.0000002 = 20 dollars.
Why this step? The flat per-invocation fee, now multiplied by 100 million calls, becomes a big number ($20) — this is the overhead that eventually sinks serverless.
Serverless total. 41.6667 + 20 = 61.6667 ≈ $61.67 .
Why this step? Add the two terms to get the monthly bill we will compare against the flat server.
Compare. Serverless \ 61.67v sr eser v e d $70— h er eser v er l ess i s ∗ s t i l l s l i g h tl y c h e a p er ∗ , b u t n o t i ce t h e p er − r e q u es t f ee ( $20) i s n o w abi g c h u nk . P u s h Nhi g h er or r u n t im e l o n g er an d t h e f l a t ser v er w in s . ∗ W h y t hi s ma tt er s : ∗ t h e p a r e n t s a y s ∗ " W h e n Ni s h ug e an d s t e a d y , a r eser v e d ser v er i sc h e a p er b ec a u sey o u a v o i d p er − r e q u es t o v er h e a d ." ∗ A t e x a c tl y t hi s Nw es i t j u s tl e f t o f t h ecr osso v er in t h e f i g u r e — n u d g e N$ right and the flat line wins.
Verify: Total scales linearly with N (both terms have N ). ✓.
Worked example C6 (crossover) — Finding the exact tipping point
For this same function profile (0.025 GB-s/call), at what invocation count N does the serverless bill exactly equal the flat \ 70/\text{month}$ server?
Forecast: Bigger or smaller than our 100-million example?
Set the two costs equal. Serverless total = 70 :
N × 0.025 × 0.0000166667 + N × 0.0000002 = 70
Why this step? The crossover is by definition the N where the rising serverless line meets the flat \ 70$ line (the orange dot in the figure) — so we write "serverless cost = 70."
Factor out N . Both terms carry N , so:
N × ( 0.025 × 0.0000166667 + 0.0000002 ) = 70
The bracket is the cost of one call = 0.000000416667 + 0.0000002 = 0.000000616667 dollars.
Why this step? Pulling N out turns the equation into "N × (cost per call) = 70," which we can just divide.
Divide. N = 0.000000616667 70 ≈ 1.1351 × 1 0 8 calls.
Why this step? Dividing the flat budget by the per-call cost tells us how many calls the \ 70$ buys — that is exactly the crossover count.
Read it. About 113 million calls/month . Below this, serverless is cheaper; above it, reserve the server.
Why this matters: our 100-million example sat just below this line — that is why serverless still won there by a hair. The number is no longer a mystery; it is 70 ÷ ( cost per call ) .
Verify: Plug N = 1.1351 × 1 0 8 back: 1.1351 × 1 0 8 × 0.000000616667 ≈ 70 . ✓. And 1 0 8 < 1.1351 × 1 0 8 confirms the 100M example is on the serverless-wins side.
Common mistake Reading serverless cost as "always cheap"
Why it feels right: the idle example was sub-cent.
The fix: cost is O ( N ) — it grows with every call. At steady high volume the linear line crosses the flat server line. Look at the figure: serverless is a rising straight line, the server is a horizontal line; the winner depends on which side of the crossing you sit.
The figure below shows C5 concretely: on the left , a monolith replicated 50 times — each copy drags along all three modules (magenta search, violet profile, orange checkout), so the cold modules are duplicated needlessly. On the right , only search (magenta) is replicated 50 times while profile and checkout stay at one copy each. Count the boxes: the right side is far leaner.
Worked example C1 — Solo dev, simple CRUD (the degenerate team)
One developer builds an internal admin panel: list, create, edit, delete records. 5 users total.
Forecast: Layered monolith? Microservices? Serverless?
Score the three drivers for splitting (from our definition above). Independent deployment? No — one dev deploys everything. Independent scaling? No — 5 users, nothing is hot. Team autonomy? There is one team.
Why this step? Those three drivers are the entire case for microservices. With all three at zero, the case for splitting is zero.
Count the costs of splitting. Network latency between services, distributed transactions, monitoring N services — all pure overhead here.
Why this step? A fair decision weighs benefit against cost; we already found benefit is zero, so any positive cost settles it.
Decide. A layered monolith (or an MVC web app). One deploy unit, one database.
Why this step? We convert the benefit-vs-cost tally into the actual recommendation the reader asked for.
Verify: Drivers-for-split = 0 , costs-of-split > 0 ⇒ net benefit negative ⇒ don't split. Consistent with "start with a modular monolith." See Monolith vs Microservices and Conway's Law — one team → one service.
Worked example C5 — One hot part, everything else cold
A shopping site: the search service gets 50× the traffic of everything else. The rest (profile, checkout) is lightly loaded. This is the exact situation drawn in the figure above.
Forecast: Scale the whole app, or carve out search?
Layered monolith to scale: you must replicate the entire stack to give search more capacity. If search needs 50 copies, you run 50 copies of profile and checkout too — the wasted boxes on the left of the figure.
Why this step? In a monolith the deploy unit is the whole app (parent's [!mistake] "Layered = scalable"); you cannot replicate one module alone.
Extract search as its own service: now you scale only search horizontally — see Scalability — Horizontal vs Vertical — running 50 search instances but just 1–2 of the rest (the right of the figure).
Why this step? Independent scaling is precisely the second of our three drivers, and it is the only thing that lets the cold modules stay at one copy.
Count the waste avoided. Monolith: 50 copies × 3 modules = 150 module-instances. Split: 50 search + 2 (rest) = 52 . Saving = 150 − 52 = 98 .
Why this step? We turn the hot/cold asymmetry into a concrete number so the decision is evidence-based, not vibes.
Decide. Carve out the hot capability; keep the cold rest as a modular monolith. A partial split , not full microservices.
Why this step? We choose the smallest change that solves the actual bottleneck — splitting everything would pay full microservice overhead for no extra benefit.
Verify: Waste count: 150 − 52 = 98 instances saved. ✓ — the hot/cold asymmetry is what justifies the split. See Monolith vs Microservices .
Recall C5 degenerate: all parts equally loaded
If every part gets equal traffic, does splitting for scale help? ::: No — you'd scale all services equally, which is the same as replicating the monolith. The split only pays when load is uneven .
Worked example C2 — Same order data shown three ways
An Order must appear as: an HTML page, a printable PDF, and a JSON API response.
Forecast: How many Models? How many Views? Any Controllers reused?
Model count. The order's data + rules is one thing — 1 Model . It knows nothing about screens.
Why this step? Parent's MVC definition: the Model is the single source of truth, so no matter how many renderings we need, the data lives in one place.
View count. Three renderings ⇒ 3 Views (HTML, PDF, JSON). Each is "dumb" — just formats the same Model.
Why this step? Each output format has different presentation logic, and MVC isolates that logic per View so one format's change can't break another.
Controller. One controller can fetch the Model and pick which View by request type ⇒ 1 Controller with 3 branches.
Why this step? The Controller's job is "what to show," so choosing among the three Views is exactly its responsibility — see Design Patterns — MVC, Observer .
Verify: Models = 1, Views = 3, and the total distinct roles = 1 + 3 + 1 = 5 components. Adding a 4th view later touches 0 Model lines — that zero is the whole point.
Worked example C2 (degenerate) — Exactly one view, forever
A tiny script prints one report to the terminal, one format, never anything else.
Forecast: Is full MVC worth it?
Views needed now and ever = 1 . The "swap views" benefit is unused.
Why this step? MVC's payoff is reuse of the Model across many Views; with one View that payoff is exactly zero.
Splitting into Model/View/Controller here adds files and indirection with no payoff.
Why this step? We weigh the (zero) benefit against real overhead — the same benefit-vs-cost test as C1.
Decide. Skip formal MVC; a single well-named function is fine. Architecture is a trade-off, not a mandate.
Why this step? We turn the tally into a recommendation: no benefit + positive cost ⇒ don't apply the pattern.
Verify: View-count = 1 ⇒ reuse benefit = 0 ; overhead > 0 ⇒ don't apply MVC. Same logic as the C4 degenerate broker case — small scale inverts the advice.
The figure shows the C7 event flow: the violet Order code emits one OrderPlaced event into the magenta broker , which fans it out to four orange consumers (email, inventory, analytics, shipping). Note the caption — adding shipping later means drawing one new orange arrow from the broker, with zero edits to the order code on the left.
Worked example C7 — E-commerce "OrderPlaced" grows new reactions
Launch: when an order is placed, you send a confirmation email. Six months later you also want: update inventory, notify analytics, and trigger shipping. Four reactions total, all independent.
Forecast: Direct calls from the order code, or an event?
Direct-call version. The order-placing code calls email, then inventory, then analytics, then shipping. To add each reaction you edit the order code and it now knows 4 addresses.
Why this step? Direct calls mean the producer must know every consumer (spatial coupling), so every new reaction is a change to the producer.
Event version. Order code emits OrderPlaced once. Email, inventory, analytics, shipping each subscribe . Adding shipping later = add one consumer, order code unchanged .
Why this step? This is C3's driver: many independent reactions to one fact. Parent §3: "A never changes" — see the unchanged left box in the figure.
Cost you accept. No stack trace across services, and you must handle Eventual Consistency — inventory updates a moment after the order, not instantly.
Why this step? Honesty about the trade-off: we spend spatial simplicity but buy temporal complexity, and the reader must budget for it.
Decide. Event-driven — because reactions are many, independent, and expected to grow.
Why this step? We match the pattern's strength (fan-out to many independent listeners) to the problem's shape, which is exactly when events pay off.
Verify: Reactions to add over time: direct edits the producer 4 times; events edit it 0 times after the first. The "changes to producer" count going 4 → 0 is the decoupling win. Broker infrastructure: Message Queues and Brokers .
Worked example C3 (degenerate) — One producer, one consumer, request needs an answer
A checkout page calls a payment gateway and must wait for "approved/declined" before showing the result.
Forecast: Event or direct call?
Reactions = 1, and the caller needs the reply synchronously .
Why this step? We first identify the two facts that decide it: how many listeners, and whether the caller must wait for a result.
An event/broker here adds latency and you'd have to invent a way to wait for the async result — complexity for nothing.
Why this step? Brokers are fire-and-forget by nature; forcing a synchronous reply through one fights the tool's grain.
Decide. A direct synchronous call . Events shine for fire-and-forget fan-out, not for "I need the answer now."
Why this step? With one listener and a required reply, the event pattern's benefit is zero and its cost is positive — so we pick the direct call.
Verify: Consumers = 1 and reply-required = true ⇒ O ( n + m ) saving = 0 and temporal cost > 0 ⇒ direct wins. Same edge as C4's 1×1 case.
Worked example C8 — "A 3-person startup must use microservices to be scalable." True or false, and why?
Forecast: Your gut says…?
Spot the trap. The claim equates "scalable" with "microservices." But a well-built modular monolith scales horizontally too — you replicate the whole app behind a load balancer.
Why this step? Exam gotchas usually hide a false equivalence; naming it out loud is how we avoid the reflex answer — parent's [!mistake] "Layered = scalable."
Score our three drivers for this team. Independent deploy? 3 people, one release train — low. Independent scaling of a hot part? Unknown at a startup. Team autonomy across service boundaries? 3 people = one team — no.
Why this step? Same three-driver test as C1; scoring them keeps the decision evidence-based instead of fashion-based.
Weigh the cost of getting it wrong. Distributed transactions, N deployments to monitor, network latency — crushing overhead for 3 people (Conway's Law : a service-per-nothing architecture would mismatch a one-team org).
Why this step? A decision needs the cost side, not just the benefit side; here cost is high and benefit near zero.
Answer. False. Start with a modular monolith; split a service out only when a specific boundary proves it needs independent scaling or deployment.
Why this step? We convert the driver-vs-cost tally into a crisp true/false with the reasoning an examiner wants to see.
Verify: Drivers ≈ 0 , overhead high ⇒ microservices net-negative here. The word "must" is what makes the statement false — there is a cheaper path. Consistent with the parent's Forecast-then-Verify conclusion and Monolith vs Microservices .
Mnemonic The whole matrix, compressed
Small & simple → monolith. Many views of one data → MVC. Many independent reactions → events. One part hot → split that part. Bursty/idle traffic → serverless. When in doubt → start monolith, split on proven need.
Recall Serverless idle bill for 1000 tiny calls
Roughly how much? ::: about $0.0006, i.e. well under a cent.
Recall Serverless vs
70 ser v er a t 100 M c a l l s W hi c h w o n , an d b y h o w m u c h ? ::: ser v er l ess ≈ 61.67, just under the $70 server — near the crossover.
Recall The exact serverless/server crossover for this profile
How many calls? ::: about 1.1351 × 1 0 8 (≈113 million), from 70 ÷ (cost per call 0.000000616667 ).
Recall Direct vs broker wiring at 4 producers, 5 consumers
The two counts? ::: direct = 20 , event = 9 .