SwadhyAI Notes

All System Design notes

System Design Reliability

Graceful Degradation

Black Friday checkout is humming. Recommendations lag, the personalization service tips over, and CPU on the survivors climbs past 90%. Users still need to pay. They do not need a perfect “for you” rail.

is deciding that swap before the page: flip a , climb a , and low-value work so auth and payment stay up.

Degradation ladder

1

Rank what never drops vs what can go stale.

2

Disable personalization in seconds.

3

Fresh → stale → static → honest wait.

4

Drop P3 work before checkout.

Try it: climb the degradation ladder with feature flags

Black Friday load rises while a personalization dependency browns out. Turn flags off in priority order so checkout keeps working even when nice-to-have surfaces go stale or static.

Utilization
236%
Ladder step
Critical
Checkout
At risk
Optional load
1750 rps

Recommendations rail

P3

Costs ~400 rps when enabled. Tier P3 drops before checkout.

Personalized ranking

P2

Costs ~600 rps when enabled. Tier P2 drops before checkout.

Live inventory counts

P2

Costs ~500 rps when enabled. Tier P2 drops before checkout.

Real-time analytics beacons

P3

Costs ~250 rps when enabled. Tier P3 drops before checkout.

Critical · essential checkout only

Raise load or disable feature flags manually. Checkout stays tier P0; lower tiers drop first so payment keeps working under pressure.

Decide before the incident. Feature flags encode the ladder ahead of time so responders are not debating product policy while CPU is pegged.

Fallback chains beat hard failures. Live inventory may become yesterday's cached count with a banner. That is preferable to blocking payment when a read model is slow.

What actually happens

Overload and dependency brownouts are normal at scale. Without a plan, every service competes for the last CPU cycle and the whole site returns 500s. With a plan, you climb a ladder: personalized → cached → simplified → → queued → shed → essential only.

Automation and make those steps deliberate. A opens on a sick dependency and walks a so quality drops smoothly. Users see a banner for stale data; responders are not inventing policy at 3am.

Exit rules matter as much as entry. Use so the system does not flap between degraded and normal every few seconds under noisy load.

How to choose what to degrade

1. What is the product promise? For commerce, checkout beats recommendations. For messaging, send/receive beats avatar decoration. Name that promise first.

2. What scarce resource is on fire? DB write saturation, cache outage, and external API failure each want a different first cut: see the table later.

3. Can users understand the trade? Stale data needs labels, queued writes need receipts, and rejected work needs clear retry guidance, not silent failure.

Simple rule of thumb

Prefer a reduced experience over total failure. Pre-classify every feature by , wire flags and breakers before incidents, and climb back only after a healthy window.

In simple terms: plan the boring mode of your product. That is the mode that saves the business day.

The degradation ladder

Plan a ladder from rich experience to basic service. Each step should be deliberate, reversible, observable, and understandable to users.

Normal / cachedDegradeCritical shed

Trigger

Choose a trigger tied to the resource that is actually constrained. If database connections are saturated, disabling a CPU-heavy animation service will not release them; pausing expensive database-backed recommendations may. Require the signal to persist for a defined interval and record which rule activated the mode. Keep a manual override for incidents that automation cannot classify reliably.

User signal

Show a small banner for stale data, queued writes, or temporary feature limits.

Exit rule

Climb back only after metrics are healthy long enough to avoid flapping. That is . For example, enter a reduced mode when queue age stays above 30 seconds for two minutes, but return to normal only after it stays below 10 seconds for five minutes. Different entry and exit thresholds create hysteresis, preventing noisy measurements from repeatedly toggling the feature. Increase restored traffic gradually because recovery itself can refill caches and create fresh load.

Degradation playbooks

A playbook converts "degrade gracefully" into exact triggers, actions, user messages, owners, exit rules, and metrics.

Incident signalTriggerActionUser-visible behaviorExit rule
Database write latency highP99 write latency above target for 5 min or queue age high.Disable non-critical writes; queue low-priority writes with receipts.Some updates may take a few minutes.Latency healthy for 15 min and backlog below threshold.
Cache outageCache hit rate drops below target and database load rises.Disable personalization and wide fanout reads.Popular or stale results are shown.Cache warmup complete and DB load below threshold.
Surviving region overloadedUtilization above 90% after failover.Shed background work, cap retries, lower media quality.Core flows continue with reduced quality.Utilization below 85% for the recovery window.

Feature flags for controlled degradation

flip functionality without redeploying binaries: perfect for instantly disabling risky widgets when metrics spike or dependencies lag.

Feature degradation contract

  • What is disabled or reduced.
  • Who can flip the flag.
  • Which metric triggers it.
  • What users see.
  • How to verify flag propagation.
  • How to recover without flapping.

Tier 0: Critical

Auth, payment, core reads. Never degrade.

Tier 1: Important

Recommendations → popular. Notifications → queue. Search → basic.

Tier 2: Nice-to-have

Avatars → placeholder. Feeds → 5-min stale. Analytics → drop.

Tier 3: Expendable

A/B telemetry, social, background jobs. Disable first.

javascript
if (featureFlags.isEnabled("recommendations")) {
  return recommendationService.getPersonalized(userId)
}
return fallbackService.getPopularItems()  // Static cache
// Circuit breaker triggers flag. Propagation: < 5s across 10K servers

Static fallbacks and cache-only mode

Serving last-known-good HTML or CDN assets buys minutes to hours while databases recover. Users notice staleness but stay productive versus staring at 500s: often via . A stale response is acceptable only within the data’s correctness contract. An old catalog description may still be useful, while a cached permission decision or inventory quantity can authorize an invalid action. Mark freshness when it affects decisions and revalidate critical state at the write boundary. Ensure the fallback can be served without contacting the same failed dependency it is meant to replace.

Static fallback

Pre-cache homepage (hourly), product (daily), recommendations (top-100). CDN + disk + memory. Backend dead = users still see content.

Cache-only mode

Normal: cache miss → service → DB. Degraded: cache hit or stale with a "data may be outdated" banner.

When writes are overloaded, keep safe reads available and accept deferred mutations only if the product supports pending work. A successful acceptance response must mean the command is durably recorded with an operation ID, not merely buffered in process memory. Show “queued” and later completion or failure. For operations such as reserving the last seat, rejecting promptly may be safer than promising a write that cannot yet be validated.

Queue-based load leveling

Queues absorb bursts: clients enqueue work instead of hammering synchronous endpoints, but backlog grows if consumers lag. Monitor depth and age alongside enqueue latency, and apply when the queue is no longer useful.

A queue absorbs a temporary excess of arrivals over processing capacity. If traffic reaches 100,000 jobs/s for ten seconds while workers handle 10,000 jobs/s, backlog grows by 900,000 jobs, assuming all are durably accepted. If arrivals then stop, draining takes 90 seconds; if arrivals remain at 10,000 jobs/s, there is no spare capacity to drain it. Bound acceptance by useful waiting time and storage.

Client → API (enqueue) → "Processing..." | Durable queue | Workers → DB

depth < 1K

Normal, < 1s

depth < 100K

Elevated, < 2 min

depth > 100K

Critical: enable shedding

Queue backlog math

Arrival rate 100K/s and worker capacity 40K/s means backlog grows by 60K/s. If work expires after 5 minutes, max useful backlog is 12M items. Beyond that, shed work instead of accepting false promises.

After a 10-minute surge, backlog is 36M items. At 40K/s drain with no new arrivals, drain time is 15 minutes; with normal traffic continuing, drain time may be much longer.

Backpressure tells producers that the system cannot safely accept more work. Use a queue-age or projected-wait threshold alongside queue depth, because a thousand slow jobs can be worse than a million tiny ones. Reject with retry guidance before the waiting time exceeds the job’s value. Expire only work whose semantics allow it, and record an explicit failure for accepted commands that require a final outcome.

Choosing what to degrade under pressure

Degrade the work that consumes scarce resources without protecting the main promise of the product.

PressureDegrade firstProtectTradeoff
DB write saturationNon-critical writes, analytics, profile edits.Orders, payments, identity changes.Some actions queue or become read-only.
Cache outageExpensive personalization and wide fanout reads.Small critical reads with rate limits.Users see popular or stale content.
External API failureLive enrichment, fraud score refresh, shipping estimate refresh.Previously authorized flows and safe defaults.Lower freshness, higher manual review later.

Million-user degraded modes

A dependency outage at million-user scale should turn into lower-quality answers, not a blank page. Predefine the fallback for each expensive feature.

Feature tier

Recommendations

Search

Media

Core account

TriggerFallbackProtect

Recommendations outage

Skip personalization, serve popular/category lists from cache, and cap refresh frequency to avoid stampedes.

Search outage

Use last-built index, simpler ranking, fewer filters, and explicit "results may be limited" messaging.

Media pressure

Lower bitrate, defer transcodes, pause previews, and queue uploads with receipts instead of failing the whole flow.

Priority-based load shedding

When CPUs saturate, drops lowest-value requests first: analytics, previews, heavy personalization. So carts and authentication stay responsive under siege.

Fairness and isolation rules

  • Reserve capacity for critical user journeys.
  • Cap heavy tenants, expensive queries, and bulk exports.
  • Shed background and analytics work before interactive traffic.
  • Return retry guidance for retryable requests so clients do not stampede.

P0 Critical

Payment, auth, health

P1 High

Product, search, cart

P2 Medium

Recs, reviews

P3 Low

Analytics, webhooks

Load signalWhat to shed
CPU > 80%Disable or queue P3 (analytics, webhooks).
CPU > 90%Also shed P2; keep product-critical paths.
CPU > 95%Run P0 only (payments, auth, health): return 503 with Retry-After elsewhere.

Pair shedding with client backoff; golden-path checkout staying up under stress is the usual product bar.

Circuit breaker with fallback chains

stop hammering sick dependencies; chain multiple fallbacks (fresh → stale cache → static) so each hop degrades quality smoothly instead of failing closed immediately. Keep fallback chains short and cheaper at each step. If personalized ranking times out, a precomputed popular list can avoid the failed ranking service entirely. If that list is unavailable, a static response may preserve navigation. Give the whole chain one deadline; assigning a full timeout to every fallback can make degraded mode slower than the original failure.

Fallback chain

  1. Primary: ML recs (P99 50ms)
  2. Fallback 1: Simplified model (5ms)
  3. Fallback 2: Category popular (cached, 1ms)
  4. Fallback 3: Global top-100 (CDN)
  5. Fallback 4: "Check back later"

Media-service fallback

1. Personalized results 2. Daily cached results 3. Top trending from static object storage 4. Editorial fallback. Users still see usable content.

Degradation strategy patterns

Pattern-match to your domain: pre-ranked services, ruthless protection of media/checkout paths, and manual toggles exercised quarterly.

Media-first product

Every service ranked by criticality. Non-critical paths throttle first. Personalization, social, and analytics degrade before playback. Video remains last standing.

Commerce peak event

Pre-plan tiers weeks ahead. Recommendations, recently viewed items, and reviews are shedable. Incident room toggles flags. Checkout is protected while homepage personalization can be disabled to free payment capacity.

How to talk about degradation tradeoffs

  • Lead with product priorities: name which features are P0, P1, P2, and why.
  • Connect degradation to reliability controls: circuit breaker opens, feature flag flips, cache-only mode starts, and clients receive Retry-After.
  • Call out user trust: stale data needs labels, queued writes need receipts, and rejected work needs clear retry guidance.
  • Explain recovery: use and health windows so systems do not flap between degraded and normal modes.

Key takeaway

At scale, total availability is a myth: partial degradation is the reality you design for. Pre-classify features by criticality, build fallback chains from rich to basic, use feature flags and circuit breakers, and shed load with priority so critical paths survive. Users tolerate degraded features far better than total outages. Plan those paths before the page.

Deepening: feature degradation contracts

For each non-critical feature, define entry and exit conditions, user messaging, correctness boundaries, and fairness under shed load. Automate degraded-mode tests so the fallback is not imaginary.

Primary sources

Practice and further reading

Use these exercises to connect the lesson to a design decision. State your assumptions, trace what happens to one request, and explain the rule that must remain true even during a failure. That rule is the design's correctness invariant.

Focus for this lesson: Define per-feature degradation contracts, correctness boundaries, fair shedding, user messaging, entry/exit gates, and continuous degraded-mode tests.

Explain the decision

What should degrade first in an e-commerce checkout?

Read the reasoning

Recommendations, reviews, and rich media before inventory, price, identity, payment correctness, or order confirmation.

Apply it to a production scenario

Search is overloaded. How do you preserve a useful product?

Read one approach

Reduce facets/personalization, serve cached popular results, cap expensive queries, shed anonymous traffic fairly, and show honest freshness.

Work through the numbers

Dropping a personalization stage saves 45 ms and 25% CPU from a 180 ms path. What is degraded latency?

Read the worked calculation

About 135 ms if stages are serial, while capacity benefit must be load-tested rather than inferred solely from CPU.

Reason through a failure

What must degraded mode never do?

Read the recovery reasoning

It must not fabricate success, bypass security, violate money/inventory invariants, or return stale data beyond the stated contract.