Availability and the nines
Availability and the nines for system design interviews: turn 99.9% or 99.99% into minutes of downtime, compute availability for serial chains and redundant replicas, spot correlated failures, pick a target per user journey and stay up through a zone loss with static stability.
On this page
🟢 What is availability?
Availability is the share of the time, or the share of requests, in which your system does its job when someone asks. It's usually written as a percentage with a lot of nines: 99.9% ("three nines") means the service may be unusable for about 8.76 hours a year. Think of a shop: availability is whether the door is open when a customer walks up, not whether the shelves are perfectly stocked.
For this lesson, we'll turn nines into minutes, do the two pieces of math every design round needs (boxes in a chain, boxes side by side), and look at the assumption that quietly breaks that math. Then we'll pick a target on purpose and keep it when a zone disappears. Interviewers like this topic because "highly available" is the most hand-waved phrase in system design, and a candidate who says "99.95% for writes, here's the chain, here's what degrades" stands out in under a minute.
Below the line (out of scope)
- The vocabulary (SLI, SLO, error budget mechanics, MTBF and MTTR): Reliability
- Finding the one box that takes everything down: Single point of failure
- How traffic actually moves to a standby: Failover
- Timeouts, retries, bulkheads and degradation in depth: Fault tolerance
The 30-second answer
Availability is uptime as a ratio: good time over total time, or successful requests over valid requests. Each extra nine cuts the allowed downtime by ten: 99.9% is about 8.8 hours a year, 99.99% about 53 minutes. Boxes in series multiply, so a chain is always less available than its weakest link. Redundant boxes in parallel fail only if all of them fail, so two independent 99.9% replicas give about 99.9999%, but only if their failures really are independent. I pick a target per user journey rather than 100%, spread replicas across zones with spare capacity already running, and decide up front what degrades instead of failing.
What you’ll learn
- Convert any number of nines into downtime per year, month and day with
(1 - A) x period - Compute availability for a serial chain (multiply) and redundant replicas (
1 - (1 - A)^n) - Explain why the parallel math depends on independent failures, and name what makes replicas fail together
- Pick an availability target per user journey instead of chasing 100%
- Describe static stability: spare capacity across zones so losing one needs no action
01Picture it first: nines are a downtime budget
A percentage feels abstract. Minutes don't. Here's the table I keep in my head, computed with a 365-day year (525,600 minutes), a 30-day month (43,200 minutes) and a 24-hour day.
| Availability | Down per year | Down per 30-day month | Down per day |
|---|---|---|---|
| 99% ("two nines") | 3.65 days (87.6 h) | 7.2 hours | 14.4 minutes |
| 99.5% | 1.83 days (43.8 h) | 3.6 hours | 7.2 minutes |
| 99.9% ("three nines") | 8.76 hours | 43.2 minutes | 86.4 seconds |
| 99.95% | 4.38 hours | 21.6 minutes | 43.2 seconds |
| 99.99% ("four nines") | 52.56 minutes | 4.32 minutes | 8.64 seconds |
| 99.999% ("five nines") | 5.26 minutes | 25.9 seconds | 0.86 seconds |
The rule behind every row is one multiplication: downtime = (1 - availability) x period. For 99.99% over a year that's 0.0001 x 525,600 minutes = 52.56 minutes. The yearly column matches the availability table in Google's SRE book, which is the one to quote if anyone asks where your numbers come from.
Two things to notice. Each extra nine is ten times less downtime, and usually far more than ten times the effort. And at four nines the daily budget is 8.6 seconds: no human can respond that fast, so detection and repair have to be automated.
There are two ways to count:
- Time-based: minutes up divided by total minutes. Easy to explain, but crude for a service that's half broken.
- Request-based: successful requests divided by valid requests. Google's SRE book prefers this for global services, because they're almost never fully up or fully down. Its example: a service handling 2.5 million requests a day with a 99.99% daily target can fail up to 250 of them.
I default to request-based in interviews, because it handles partial outages naturally.
02Under the hood: serial and parallel math
Almost every availability question reduces to two rules.
Serial (hard dependencies) multiply. If a request needs the load balancer AND the app AND the database, all three must be up, so you multiply their availabilities. AWS's reliability pillar uses this exact example: a 99.99% service with hard dependencies on two other 99.99% services can reach about 99.97%.
Parallel (redundant copies) multiply the failures. If either of two replicas will do, the tier is down only when both are down at once. So you multiply the unavailabilities and subtract from one: availability = 1 - (1 - a)^n. Two independent 99.9% replicas: 1 - (0.001 x 0.001) = 99.9999%.
Try it yourself first
Before reading on, try it. A request goes through a load balancer (99.99%), one app server (99.9%) and one database (99.95%). What's the end-to-end availability, and roughly how many hours of downtime a year is that? Then add a second app server in parallel. How much do you gain, and which box should you fix next?
Here's the worked version, all on a 365-day year:
| Design | Math | Availability | Down per year |
|---|---|---|---|
| One of each | 0.9999 x 0.999 x 0.9995 | ≈ 99.84% | ≈ 14 hours |
| Two app servers | 0.9999 x (1 - 0.001²) x 0.9995 | ≈ 99.94% | ≈ 5.3 hours |
| Two app servers, DB with standby | 0.9999 x (1 - 0.001²) x (1 - 0.0005²) | ≈ 99.99% | ≈ 53 minutes |
Serial boxes multiply, parallel boxes protect each other
Notice three things.
- The chain is always below its weakest link. 99.84% is worse than every single box in it.
- Redundancy pays where the failures are. Doubling the app tier removed most of its contribution, and the database now owns most of the remaining downtime. Fix the next weakest link, not the one you already fixed.
- Small numbers compound. Ten hard dependencies at 99.99% each come to about 99.90%. That's how a microservice graph of individually "four nines" services ends up at three.
When every component is all nines, parallel copies add their nines: two independent three-nines replicas give six nines. AWS's reliability pillar gives the same shortcut. It's handy on a whiteboard, as long as you say "if they fail independently" out loud.
03Where the math lies: independence
That last row says 99.99%, and I'd still not promise it. The parallel formula assumes the replicas fail independently and that switching between them is instant. Neither is free.
Things that make replicas fail together:
- Shared infrastructure. Same rack, same power feed, same zone, same region. That's why cloud zones are built not to share power and are physically separated.
- Shared change. A bad config push or deploy goes to every replica within minutes. Redundant boxes running the same broken config are one box.
- Shared dependency. Both app servers call one auth service, one secrets store, one DNS provider. Your redundancy ends at their availability.
- The same bug. A poison request or a leap-second edge case crashes every replica that sees it.
And switching isn't instant. A database standby that takes two minutes to promote costs you two minutes every time the primary dies. At 99.99% (52.56 minutes a year) you can afford about 26 of those; at 99.999% (5.26 minutes), two. We cover realistic switch times in Failover.
Many candidates multiply nines across replicas and announce "six nines" without asking what the replicas share. Interviewers hear that as textbook recall. The stronger answer is "two replicas in separate zones, so the math says about six nines for that tier, but in practice a shared config push or a slow failover will dominate, so I'll plan around those." Two other traps: excluding planned maintenance from downtime (AWS advises against it, because users don't stop clicking during your window), and calling a system available when it's answering quickly with wrong data. That's a reliability failure, and it's worse.
04Pick a target on purpose
The tempting target is 100%. It's the wrong one, for two reasons from Google's SRE book. Past a point users can't tell the difference, because their own phone and network fail more often than your service. And each extra nine can cost far more than the last, in hardware, slower releases and engineers working on risk instead of features.
The book also shows how to price a nine. For a service earning $1M, moving from 99.9% to 99.99% recovers 0.09% of revenue, about $900. If that extra nine costs more than $900 to build and run, it isn't worth it. That's the shape of argument I want to hear.
So I set targets per user journey, not per system:
| Journey | Target I'd propose | Why |
|---|---|---|
| Read a product page or feed | 99.99% | High traffic, and a stale cached copy still counts as "up" |
| Place an order or pay | 99.95% | Must be correct first; a short "try again" is better than a double charge |
| Admin dashboard, reports | 99.9% | Internal users, can wait |
| Nightly batch job | 99% | Can rerun; measure by records processed |
These are a starting proposal, not industry constants. AWS's reliability pillar has a similar table that pairs 99.95% with online commerce and 99.99% with video delivery. Once you've set a target, the gap between it and 100% is your error budget; how teams spend and alert on it lives in Reliability.
05Static stability: stay up without doing anything
The usual plan for losing a zone is reactive: "auto scaling will launch replacements in the other zones." Amazon's Builders' Library calls this out as the weaker pattern, because recovery now depends on the control plane (launching instances, fetching config, registering with discovery) at the exact moment things are already broken.
The alternative is static stability: run enough spare capacity, all the time, that losing a zone needs no action at all. Amazon describes running stateless fleets across three zones overprovisioned by 50%, so each zone normally runs at about 66% of the load it was tested for. When one zone drops, the load balancer's health checks steer traffic to the other two, which absorb it without launching anything.
Static stability: spare capacity is already running
In Static stability using Availability Zones, Amazon explains that the EC2 data plane keeps routing packets even when the control plane that launches instances is impaired: running hosts keep what they need locally, so they miss updates but keep working. For stateful systems the same idea means the database standby is already running in another zone, so failover promotes it instead of building a new one.
The arithmetic is worth knowing: with three zones you need 1.5x your peak capacity; with two zones each must carry the whole load, so you need 2x. That's a strong argument for three zones over two.
Static stability pairs with graceful degradation: when a non-critical dependency fails, serve something smaller instead of an error. Recommendations go blank, the feed shows cached posts, search falls back to popular items. The checkout path stays up. That's how a request-based availability number stays high during a partial outage. See Fault tolerance and the fallback pattern for the techniques.
- Downtime = (1 - availability) x period. A year is 525,600 minutes, a 30-day month 43,200.
- 99.9% ≈ 8.8 h/yr · 99.95% ≈ 4.4 h/yr · 99.99% ≈ 53 min/yr · 99.999% ≈ 5 min/yr.
- Three 99.9% hops in series ≈ 99.7%. Two 99.9% replicas in parallel ≈ 99.9999% (if independent).
- Three zones with static stability: 1.5x capacity. Two zones: 2x.
06How it shows up in design problems
Availability shows up as a non-functional requirement in almost every round. Name a number per path and show where it comes from.
- Design a payment system: writes favour correctness over uptime, so a payment can return "pending" and finish later rather than risk a double charge. This is where CAP and idempotent retries meet the nines.
- Design a notification system: the accept path must be very available, so you put a durable queue in front and let delivery lag behind during an outage.
- Design a key-value store: replicas across zones and quorum reads and writes; the availability question becomes "how many replicas can die before reads or writes stop?"
- Design a URL shortener: redirects are read-heavy and cacheable, so the read path can target four nines even if creating links targets three.
For region-level planning, backups and recovery objectives, go to Disaster recovery. For how health checks actually notice a dead node, see Heartbeats and the health checks pattern.
07How to say it in the interview
When I ask "how available does this need to be?", I'm listening for three things: a number per path instead of one number for everything, a dependency chain with the weak link named, and a story for what degrades instead of failing. Bonus points for mentioning correlated failure without being prompted.
In the interview
"I'd target 99.99% for reads and 99.95% for writes. That's about 53 minutes and 4.4 hours of downtime a year. Reads can be served from cache and replicas, so they're easier to keep up; writes go through a single primary, and I'd rather fail a write briefly than lose or duplicate it. The read path is load balancer, stateless app tier and cache, all hard dependencies, so they multiply, and the database is my weakest link. The app tier runs across three zones with about 50% headroom, so losing a zone needs no new servers. The primary has a synchronous standby in another zone, and a failover of a minute or two fits easily inside a 4.4-hour yearly write budget. The math assumes independent failures, so I'd also stage config pushes and deploys zone by zone. If recommendations or search are down, the page still loads without them."
On the whiteboard
- downtime = (1 - A) x period · year = 525,600 min
- 99.9 ≈ 8.8 h · 99.95 ≈ 4.4 h · 99.99 ≈ 53 min · 99.999 ≈ 5 min (per year)
- serial: A1 x A2 x A3 (always < weakest)
- parallel: 1 - (1 - A)^n (only if independent)
- correlated: zone, config push, deploy, shared dep, same bug
- target per journey, never 100%
- static stability: 3 zones x 66% load = survive 1 zone, no launches
- degrade non-critical features instead of failing the page
Further reading (4)
- Google SRE Book, Appendix A: Availability table: The canonical nines-to-downtime table; our yearly column matches it.
- Google SRE Book: Embracing Risk: Time-based vs request-based availability, why 100% is the wrong target, and how to price an extra nine.
- AWS Well-Architected Reliability Pillar: Availability: How AWS calculates availability for hard dependencies and redundant components, with a table of targets by workload type.
- Amazon Builders' Library: Static stability using Availability Zones: Why Amazon overprovisions across zones instead of scaling up during an outage, with the 3-zone, 50% headroom example.