IaaS, PaaS, SaaS, and cloud choice
Every cloud decision is the same decision asked at a different layer: which slices of the stack do you operate yourself, and which do you pay someone to operate for you? The bill and the blame move together.
The stack ladder: who owns each layer
Draw the stack as a ladder from bare metal up to the running business workflow, and mark — for each model — where the boundary between "provider operates this" and "you operate this" falls. The number of rungs below the line is your operational surface area; the number above it is what you've handed off (and lost direct control over).
That bottom row is the load-bearing count. On-prem you operate all nine rungs. IaaS hands off the four hardware/virtualization rungs and leaves you the four that actually differentiate nobody — OS, middleware, runtime, app — plus your workflow. PaaS pushes the line up to "app only": you ship code, the platform runs everything beneath it. SaaS pushes it to the top: you operate nothing but configuration of someone else's finished workflow. Read it as a dial, not three boxes: each rung you hand up the ladder removes an operational duty and a degree of control in the same motion.
| Model | Layers you operate | You still own | Canonical example | You give up |
|---|---|---|---|---|
| On-prem | 9 (everything) | Hardware → workflow | Your own datacenter | Nothing — and that's the problem (capex, capacity planning, all ops) |
| IaaS | 4 — OS, middleware, runtime, app | OS patching, scaling logic, code | EC2, GCE, bare VMs + K8s | Hardware control; gain elastic capacity |
| PaaS | 1 — app code only | Code + data + config | App Engine, Heroku, Cloud Run, RDS | Runtime/OS/scaling control; gain deploy speed |
| SaaS | 0 — config only | Config + your data inside it | Workday, Stripe, Datadog, Gmail | Almost all control; gain "it just works" |
This is DDIA Ch. 1's framing made concrete: reliability, maintainability, and operability are properties someone must provide, and the cloud model just decides who. Buying a managed service is buying operability — the question is always whether you can buy it cheaper than you can build and run it.
Put numbers on it — the cost crossover
The single calculation that decides most of these debates is the managed-vs-self crossover: a managed service charges a premium per unit (typically ~2–3× the raw compute/storage of running it yourself), and self-running charges you in SRE headcount. The break-even is where the premium equals the salary you'd otherwise pay to operate it well.
- Running Postgres well (backups, PITR, failover drills, version upgrades, 24/7 on-call) is roughly 0.5 of a competent DB-fluent SRE, fully loaded ≈ $200k/yr · 0.5 = $100,000/yr.
- Crossover: managed costs $72k/yr in premium; self-run costs $100k/yr in headcount plus the incident risk and the bus-factor. Managed wins at this scale.
- Now scale the DB tier 10× to $40k/mo raw: premium becomes $60k/mo · 12 = $720k/yr while the headcount to run it grows sublinearly — maybe 1.5 SREs ≈ $300k/yr. Above this size, self-run wins.
Egress is the multi-cloud killer and deserves its own number. Intra-cloud, same-region traffic is usually free; cross-cloud egress runs ~$0.08–0.12/GB. If a multi-cloud design shuttles 100 TB/mo between providers, that's 100,000 GB · $0.10 = $10,000/mo = $120,000/yr of pure tax for the privilege of spanning two clouds — before you've paid for the duplicated tooling, the doubled on-call surface, or the engineers who now must be fluent in two of everything. Egress is the gravity well that quietly makes "portable" architectures expensive, and it is why data, once it lands in a cloud, tends to stay there.
Clarify the contract
Treat the prompt as a decision contract, not a component diagram. What this case must do:
- Classify a workload's stack into layers and decide, per layer, who operates it.
- Choose managed vs self-managed for the stateful components (the DB is the load-bearing one).
- Reason explicitly about lock-in vs native-service leverage — and quantify it.
- Estimate the cost drivers: compute, storage, IO, egress, and support/headcount.
- Match the operating model to the team's size and maturity.
And, equally important, what it need not do: it need not produce a portable, cloud-agnostic design by default (portability is a cost, not a virtue — see the deep dive); it need not be multi-cloud (almost never worth it); and it need not minimize the per-unit bill (minimizing total cost, including headcount and risk, is the real objective).
Data model & surface
The artifacts that actually drive this decision are not request schemas — they're the operational records that let you reason about ownership and cost.
| Artifact | Why it exists |
|---|---|
service catalog | Maps each stack layer to a chosen operating model — the ladder, written down. |
cost line items (tagged) | Compute / storage / IO / egress / support, per service, so the crossover is measurable not guessed. |
SLA + runbook | For anything self-run: who gets paged, and the failover/backup procedure that headcount enforces. |
data residency policy | Encodes which regions/providers data may live in — the real driver behind multi-region/-cloud. |
Linearized design — deciding the line, layer by layer
Walk the decision the way you'd actually make it, top-down, and the first real bottleneck (stateful services + egress) surfaces naturally.
- 1. List the rungs. Hardware → network → OS → middleware → runtime → app → workflow. This is the ladder diagram above; the workflow rung is always yours.
- 2. Default the undifferentiated rungs to managed. Nobody differentiates by patching an OS or babysitting a load balancer. Hand those up the ladder unless a constraint forbids it. This is the same "buy operability" move as DDIA Ch. 5–6's managed replication and partitioning: a managed DB is bought-vs-built leader/follower replication and resharding.
- 3. Identify the rungs that differentiate you. Your application code and domain workflow — keep those. If a low-level rung genuinely encodes your competitive edge (a hand-tuned storage engine at hyperscale), keep that one too, deliberately.
- 4. Price the stateful tier both ways. The database is where the managed-vs-self crossover bites hardest. Run the premium-vs-headcount math above for your scale.
- 5. Model egress explicitly. Cross-region and especially cross-cloud traffic; this is the line item that silently dominates and the one that kills multi-cloud.
- 6. Document lock-in at three levels — API, data, operational — and design exit paths only where business risk justifies the recurring portability tax.
Deep dives
1. Lock-in vs native-service leverage
The reflexive fear is vendor lock-in, so teams reach for a "portable abstraction" — wrap everything behind interfaces, use only services with an open-source equivalent, avoid anything proprietary. The cost of that posture is rarely named: a portable abstraction can only expose the least-common-denominator of every backend it abstracts. If you insist your queue work on SQS and Pub/Sub and Kafka, you get the intersection of their features — not the union. You forgo SQS's native dead-letter ergonomics, Pub/Sub's exactly-once, the managed scaling — exactly the leverage you were paying the cloud for in the first place.
This is the same abstraction-leverage trade DDIA draws around storage engines: a generic interface buys you swappability and costs you the specialized behavior the underlying engine could have given you. Portability is a real, recurring tax (the engineering to maintain the abstraction, the features foregone, the testing matrix) paid every day against a migration that usually never comes.
When lock-in is actually fine — most of the time. Lock-in is bad only when it traps a critical system in a cost, compliance, or capability corner with no exit. For most components it's a non-issue: the switching cost is real but bounded, and the native-service leverage you gain every single day vastly outweighs a migration you'll likely never run. The mature move is deliberate, scoped lock-in: lean hard into native services for the 90% that's undifferentiated, and reserve portability investment for the narrow slice (often the primary datastore, or a regulated workload) where being trapped would genuinely be fatal.
2. Managed vs self-run — the total-cost picture
The crossover math above is the skeleton; here's the flesh. The per-unit premium (2–3×) is the visible cost of managed. The invisible cost of self-run is everything that makes a database production-grade and never appears on the AWS bill: the on-call rotation (you can't run a 24/7 rotation with fewer than ~4–5 people without burning them out), the backup/restore drills, the version-upgrade projects, the failover testing, and the single-point-of-knowledge risk when your one DB expert leaves.
So the honest comparison is not "managed premium vs. raw infra savings" — it's "managed premium vs. (headcount + incident risk + opportunity cost of those engineers not building product)." For a small or mid team the managed side wins decisively because headcount is lumpy and expensive and you can't hire half an SRE. The self-run side only wins at a scale where the premium dwarfs a full, well-staffed ops team — and at that scale you're also the kind of org that can run it well. Below that line, paying the premium is buying back engineering focus, which is almost always the scarcer resource.
3. When multi-cloud is worth it (usually not)
Multi-cloud is the most over-prescribed pattern in this space, usually justified by "avoiding provider lock-in" or "surviving a provider outage." Both arguments mostly don't survive the arithmetic.
The one place multi-cloud genuinely earns its keep is regulatory data residency: when law requires data to live in a jurisdiction or under a provider that your primary cloud can't serve, multi-cloud (or at least multi-provider for that slice) stops being a hedge and becomes a hard requirement. That — not availability, not lock-in fear — is the real driver. Default to single-cloud, multi-region; reach for multi-cloud only when compliance forces your hand.
Trade-offs
| Choice | Buys | Costs | Choose when |
|---|---|---|---|
| Managed vs self-managed | operability (backups, failover, on-call) bought as a unit | 2–3× per-unit premium, less low-level control | small/mid teams, or any time the premium < ~1.5 SRE salaries |
| Single cloud vs multi-cloud | simplicity, volume discounts, free intra-cloud traffic | provider dependency; outage blast radius | nearly all products — use multi-region instead |
| PaaS vs Kubernetes/IaaS | developer velocity, one rung to operate | platform constraints, less tuning headroom | standard web/CRUD apps without exotic infra needs |
| Portable abstraction vs native service | a migration option held in reserve | least-common-denominator features + ongoing tax | only the critical-data slice, or a regulated workload |
The sharpest of these is the multi-cloud row, and it's worth narrating because it's the one juniors get backwards. The instinct says "multi-cloud = resilient." The senior read is the opposite: multi-cloud adds failure surface (now two control planes can break you) and a permanent operational + egress tax, in exchange for an availability gain that a multi-region single-cloud design already captures more cheaply. Reach for it for residency law, not for nines.
Failure modes
| Failure | Mitigation |
|---|---|
| Unexpected bill (egress / scale-out surprise) | Tag every resource; alert on cost anomalies; model egress before shipping cross-region designs. |
| Managed service limit / quota hit | Know the quotas, design load tests around them, request increases ahead of launch. |
| Region / residency compliance violation | Encode data residency in provisioning policy; fail provisioning that would place data out of jurisdiction. |
| Provider outage | Multi-region within one cloud first (lesson 13's availability math); reserve multi-cloud for genuine residency needs. |
| Lock-in trap on a critical system | Identify the one or two systems where being trapped is fatal; invest portability there only, accept lock-in elsewhere. |
Interview prompts you should be ready for
- When is multi-cloud worth the complexity? (senior answer) Almost never for availability — a single hyperscaler multi-region design already gets you to ~99.99%, and true multi-cloud might add a few minutes a year while imposing two control planes, doubled IaC, least-common-denominator services, and a six-figure annual egress tax (100 TB/mo cross-cloud ≈ $120k/yr). The real driver is regulatory data residency: when law mandates a jurisdiction or provider your primary cloud can't serve. Default single-cloud, multi-region; go multi-cloud only when compliance forces it.
- How do you decide managed vs self-managed for a database? (senior answer) Price both: managed runs a ~2–3× per-unit premium; self-run costs ~0.5–1.5 fully-loaded SREs to do well (backups, PITR, failover drills, upgrades, 24/7 on-call). Crossover is where the annual premium exceeds ~1.5 SRE salaries. Below it, managed wins because you're buying back engineering focus; far above it, self-run wins on premium. Most teams are below the line.
- What's the cost of a portable, cloud-agnostic architecture? (senior answer) A portable abstraction can only expose the least-common-denominator of every backend it wraps, so you forgo the native-service leverage you were paying the cloud for. Plus a permanent engineering tax to maintain the abstraction and its test matrix — paid daily against a migration that usually never happens. Portability is a cost, not a default virtue.
- So is lock-in always bad? (senior answer) No. Lock-in is only bad when it traps a critical system in a cost/compliance/capability corner with no exit. For the 90% that's undifferentiated, lean into native services — the daily leverage beats a migration you'll likely never run. Make lock-in a deliberate, scoped decision: portability investment goes only to the slice where being trapped would be fatal.
- Map IaaS/PaaS/SaaS to who operates what. (senior answer) One axis, four cut points. On-prem: you run all nine rungs. IaaS: provider runs hardware/virtualization, you run OS+middleware+runtime+app (four rungs). PaaS: you run app code only. SaaS: you operate nothing but config. Each rung handed up removes an operational duty and a degree of control together — that's the whole trade.
- Why does egress dominate cloud cost models? (senior answer) Intra-region traffic is typically free, but cross-region and especially cross-cloud egress runs ~$0.08–0.12/GB, so 100 TB/mo between clouds is ~$120k/yr of pure tax. It's the gravity well that makes "portable" and multi-cloud designs quietly expensive and the reason data, once landed, tends to stay in one cloud.
- A small startup asks whether to run their own Kubernetes. (senior answer) Usually no. At small scale the operational rungs (cluster upgrades, node pools, networking, on-call) dominate, and a PaaS (Cloud Run, App Engine, a managed container platform) gets them to "app code only" — one rung — so the team builds product instead of operating infra. Adopt raw K8s when the team is large enough that the control it buys (custom scheduling, multi-tenancy, cost at scale) actually pays for the rungs you take back.
Related lessons
This case is the operating-model sibling of C42 (microservices / containers / serverless) — C42 decides how you decompose the app; C43 decides who operates each layer it runs on, and serverless is just PaaS pushed one rung further. The layer-by-layer "what do we own" reasoning is foundation lesson 17 (architecture decomposition) applied to the ops/vendor axis. The multi-cloud-vs-multi-region availability arithmetic leans directly on lesson 13 (fault tolerance) — you can't argue the nines without it. And 16 (observability) is where the cost tags and quota alerts that keep this decision honest actually live; 01 (method & napkin math) is the crossover arithmetic itself.