Lesson 15 / 25
Availability Arithmetic
Calculate composite availability for components in series and in parallel.
Multiply for chains, add redundancy for parallel
When a request needs every component in a chain (load balancer → app → database), the components are in series and availabilities multiply: three components at 99.9% each give about 99.7%, lower than any single part. Every synchronous dependency you add lowers the ceiling. When components are in parallel (redundant copies, any one of which can serve), the system fails only if all fail: availability = 1 − (1 − a)^n, assuming independent failures. Two copies at 99% give 99.99%. That independence assumption is the catch: copies in the same zone, with the same bug or the same bad config push, fail together, so real gains are smaller. The arithmetic explains common advice: keep critical paths short, make non-critical dependencies optional (degrade gracefully instead of failing), and put redundancy where failures are truly independent.
Composite availability calculations
Series multiplies; parallel combines failure probabilities.
def series(*avail):
total = 1.0
for a in avail:
total *= a
return total
def parallel(a, n):
return 1 - (1 - a) ** n
chain = series(0.9999, 0.999, 0.999) # LB, app tier, database
# about 0.9979 -> roughly 99.8%
two_db = parallel(0.99, 2) # two independent replicas
# 0.9999 -> 99.99%
improved = series(0.9999, parallel(0.999, 3), parallel(0.999, 2))
# redundancy at each tier lifts the whole chainOptional dependencies should not count
If recommendations fail, show the page without them. A dependency that can fail without failing the request drops out of the series calculation entirely.
Quick check: Three components are each 99.9% available and all are required for a request. What is the approximate overall availability?
- 99.9%
- 99.97%
- About 99.7%
- 99.999%
Answer
About 99.7% — 0.999³ ≈ 0.997, so about 99.7%.