โšก
Zero to Platform Architect2026
Staff Battleground & Test Banks
Staff Battleground & Test Banksโฑ๏ธ 18 min readโšก Staff SRE Standard
๐ŸŽฏ Memory Bank →

๐Ÿšจ Round 4: SRE Practices, Incident Management & War-Room Debugging

In Staff SRE and Principal Reliability Architect interviews at top Indian high-concurrency unicorns (Swiggy, PhonePe, Zomato, Razorpay, CRED, Zepto), Round 4 is the crucible.

Indian interviewers simulate high-stress live production war-rooms: โ€œItโ€™s Friday 8:00 PM during an IPL final or Diwali flash sale. Latency spiked 100x, 504 Gateway Timeouts are flooding users, executive leadership is on the bridge, and your pods are crashlooping. Walk me through your first 5 minutes.โ€


๐Ÿง  Beginner Mental Model & Step-by-Step War-Room Interview Playbook

Think Like an Airline Captain During an Engine Failure: In Round 4 War-Room interviews, interviewers test whether you panic and randomly restart servers, or follow a calm, structured Step-by-Step Incident Triage Playbook: 1. Measure Impact (SLI/Error Budget) โ†’ 2. Stop the Bleeding (Rollback / Shed Load / Failover) โ†’ 3. Isolate the Bottleneck (Metrics, Traces, Logs) โ†’ 4. Remediate Root Cause.


๐Ÿ“Œ Question 1: Mathematical SLOs & Multi-Window Multi-Burn-Rate Alerting

๐ŸŽฏ The Scenario & Interviewerโ€™s Trap

โ€œYour e-commerce checkout service has a 99.9% availability SLO over a 30-day rolling window. What is your total allowable downtime in minutes? If you configure a traditional alert: alert when error rate > 0.1% over 5 minutes, why is this alert completely broken in production? How does the Google SRE multi-window multi-burn-rate alerting algorithm fix this?โ€

Interviewerโ€™s Intent: To verify whether you understand the mathematics of error budgets and how to construct production alerts that balance precision (no false positives) with recall (fast detection of fatal outages).

๐Ÿ’ก Staff-Level Model Answer

1. Error Budget Mathematics:

For a 30-day rolling window: ๐Ÿ“ Total Window Minutes = 30 ร— 24 ร— 60 = 43,200 minutes ๐Ÿ“ Allowed Downtime for 99.9% = 43,200 ร— (1 - 0.999) = 43,200 ร— 0.001 = 43.2 minutes

  • Your service can only experience 43.2 minutes of total downtime per month before breaching its SLA.

2. Why Naive Single-Window Alerts Fail:

  • The 5-Minute Window Trap (error rate > 0.1% for 5m):
    • If a transient blip causes 0.2% errors for 5 minutes, an engineer is paged at 3:00 AM. But this blip consumed only 5 ร— 0.002 = 0.01 error minutes out of 43.2 minutesโ€”less than 0.02% of your budget! Extreme alert fatigue.
  • The 24-Hour Window Trap (error rate > 0.1% for 24h):
    • If the service is 100% down, the 24-hour average error rate will take hours to cross the threshold. By the time the alert fires, your entire monthly error budget is burned 10 times over!

3. The Google SRE Standard: Multi-Window Multi-Burn-Rate Alerts:

A Burn Rate of 1.0 means you will exhaust exactly 100% of your error budget over 30 days. A Burn Rate of 14.4 means you will exhaust 100% of your budget in 30 days / 14.4 = 2 days (or 2% of budget in 1 hour).

flowchart TD
    subgraph MultiBurn["Multi-Window Multi-Burn-Rate Algorithm"]
        Long["Long Window (1 hour): Burn Rate > 14.4"]
        Short["Short Window (5 mins): Burn Rate > 14.4"]
        AND{"Both Windows True? (Logical AND)"}
        Long --> AND
        Short --> AND
    end

    AND -- "YES: Severe Outage Active!" --> Page["PAGE ON-CALL SRE IMMEDIATELY!"]
    AND -- "NO: Transient Blip (Reset)" --> Silence["No Page / Auto-Resolved"]

Production Prometheus Alert Rule:

- alert: CheckoutHighErrorBudgetBurnRate
  expr: |
    (
      sum(rate(http_requests_total{job="checkout", status=~"5.."}[1h]))
      /
      sum(rate(http_requests_total{job="checkout"}[1h]))
    ) > (14.4 * 0.001)
    and
    (
      sum(rate(http_requests_total{job="checkout", status=~"5.."}[5m]))
      /
      sum(rate(http_requests_total{job="checkout"}[5m]))
    ) > (14.4 * 0.001)
  for: 2m
  labels:
    severity: page
  annotations:
    summary: "Checkout service burning 2% of 30-day error budget in 1 hour!"
  • Why the Short Window is Essential: If the outage abruptly stops after 6 minutes, the 5-minute window immediately drops below the threshold, automatically resolving the alert and preventing spurious pages!

๐Ÿ“Œ Question 2: Prometheus TSDB High-Cardinality Outage & Memory Exhaustion

๐ŸŽฏ The Scenario & Interviewerโ€™s Trap

โ€œA developer merges a PR that adds the customerโ€™s user_id and order_id as Prometheus metric labels on payment_transactions_total. Within 30 minutes, the central Prometheus server spikes to 128GB RAM, becomes unresponsive to PromQL queries, and terminates with OOMKilled. Upon restarting, Prometheus crashes again during WAL replay. Walk through the internal TSDB mechanics, explain why this happened, and provide the exact steps to recover Prometheus.โ€

Interviewerโ€™s Intent: To test whether you understand the internal architecture of Prometheus TSDB (Head block, inverted index, postings tables, WAL replay) and how to sanitize high-cardinality label explosions.

๐Ÿ’ก Staff-Level Model Answer

flowchart TD
    Metric["payment_transactions_total{user_id='1000001', order_id='998822'}"] --> Explode["1,000,000 unique users ร— 5,000,000 orders"]
    Explode --> TSDB["Prometheus TSDB Head Block"]
    TSDB --> Index["Inverted Index: Label Names to Postings Lists"]
    Index --> RAM["RAM Explodes to 128GB! (OOMKilled Exit 137)"]
    RAM --> Restart["Prometheus restarts & replays Write-Ahead Log (WAL)"]
    Restart --> Replay["WAL reads massive high-cardinality series back into RAM"]
    Replay --> Crash["CRASH-LOOP REPEAT!"]

1. Why High Cardinality Destroys Prometheus TSDB:

  • In Prometheus, each unique combination of key-value label pairs constitutes a separate Time Series.
  • If a metric includes user_id (10 million active users), Prometheus must create 10,000,000 independent time series in the in-memory Head Block.
  • For each series, Prometheus creates:
    1. A chunk descriptor in memory.
    2. Entries in the Inverted Index (hash tables mapping label pairs to series IDs).
    3. A postings list on disk and RAM.
  • Storing 10M active series requires gigabytes of pointer references. When Prometheus writes to the Write-Ahead Log (WAL), the log grows uncontrollably.
  • The WAL Replay Trap: When Prometheus restarts after an OOMKill, its first task is to read the WAL from disk to restore the in-memory Head block state. It reloads the 10 million series back into RAM and crashes again before accepting any traffic!

2. The Surgical Emergency Recovery Procedure:

Step 1: Quarantine & Drop the Poisonous Label at Ingestion

Immediately modify the Prometheus scrape configuration using metric_relabel_configs:

scrape_configs:
  - job_name: 'payment-service'
    metric_relabel_configs:
      - action: labeldrop
        regex: "(user_id|order_id|device_ip)"
Step 2: Clear Corrupted WAL Segments (If in CrashLoop)

If Prometheus cannot boot due to WAL replay:

# Analyze TSDB memory usage using promtool:
promtool tsdb analyze /var/prometheus/data

# If Prometheus refuses to start, temporarily move the active WAL:
mv /var/prometheus/data/wal /var/prometheus/data/wal.bak

# Start Prometheus (it will start clean with empty Head block)
# Delete the rogue series via Prometheus Admin API:
curl -X POST -g 'http://localhost:9090/api/v1/admin/tsdb/delete_series?match[]=payment_transactions_total{user_id=~".+"}'

# Clean up tombstones:
curl -X POST 'http://localhost:9090/api/v1/admin/tsdb/clean_tombstones'
Step 3: Implement Head Block Series Limits

Protect Prometheus against future developer errors:

scrape_configs:
  - job_name: 'payment-service'
    sample_limit: 50000        # Aborts scrape if target exposes > 50,000 metrics
    series_limit: 100000

๐Ÿ“Œ Question 3: The Live War-Room Scenario: Cascading Downstream Failure

๐ŸŽฏ The Scenario & Interviewerโ€™s Trap

โ€œIt is Friday 8:30 PM. An Indian food-delivery super-app is handling 50,000 orders/minute. The order-placement service response time jumps from 45ms to 9,500ms. Ingress returns 504 Gateway Timeout. Worker node CPU is only 15%, but Kubernetes HPA has scaled the order-placement deployment to its maximum limit of 600 pods. Downstream Aurora PostgreSQL read replicas show 95% CPU and connection pool errors. What is your first 5-minute investigation protocol, what is the exact failure mechanism, and how do you stabilize the system?โ€

Interviewerโ€™s Intent: To evaluate your calm, structured triage ability under live outage conditions and verify if you understand thread starvation, connection pool exhaustion, and the difference between symptom and root cause.

๐Ÿ’ก Staff-Level Model Answer

flowchart TD
    subgraph Traffic["50,000 Orders/Min"]
        Clients["Mobile Apps"] --> ALB["AWS ALB"]
    end

    subgraph Service["order-placement Pods (Scaled to 600)"]
        ALB --> Pods["600 Pods ร— 50 DB Connections = 30,000 Connections!"]
    end

    subgraph DB["Aurora PostgreSQL Cluster"]
        Pods -->|Connection Storm| Aurora["Aurora Primary (max_connections: 5,000)"]
        Aurora --> Lock["Slow Query with Lock Contention"]
        Lock --> Hang["PostgreSQL worker processes stall"]
    end

    Hang --> ThreadStarve["Microservice Tomcat/Go worker threads stall waiting for DB socket"]
    ThreadStarve --> HPA["HPA sees high response time / scaling trigger -> SCALES MORE PODS!"]
    HPA --> Exacerbate["600 pods hammer DB with MORE connections: COMPLETE COLLAPSE!"]

1. First 5 Minutes: Rapid Triage Protocol (Do NOT Guess):

  1. Minute 1: Mitigate Ingress Blast Radius:
    • Do not restart pods blindly (restarts cause cold-start stampedes).
    • Enable an emergency rate-limiting tier on Cloudflare / AWS WAF or temporarily return a cached degraded response (โ€œWe are experiencing high demand, please wait 30sโ€) to shed 40% of ingress load.
  2. Minute 2: Check Thread & Connection States:
    • Why is CPU low (15%) while latency is high (9.5s)?
    • Low CPU + High Latency is the classic hallmark of I/O blocking / Thread Starvation (threads waiting on database sockets or external HTTP calls).
  3. Minute 3: Inspect Database Active Queries:
    -- Run on Aurora PostgreSQL:
    SELECT pid, now() - query_start AS duration, state, query 
    FROM pg_stat_activity 
    WHERE state != 'idle' 
    ORDER BY duration DESC LIMIT 10;
  4. Minute 4: Identify Lock Contention / Unindexed Table Scan:
    • Find queries stuck in idle in transaction or waiting on table/row exclusive locks (pg_locks).
  5. Minute 5: Terminate Poison Queries:
    SELECT pg_terminate_backend(<pid>);

2. The Root Cause Mechanism (The Cascade):

  • An unindexed query or row lock slowed query execution from 2ms to 2,000ms.
  • Because the microservice lacked a tight connection timeout, client requests backed up inside the application server thread pool.
  • Kubernetes HPA saw pod CPU or request counts rise and spawned more pods (scaling from 100 to 600 pods).
  • Each new pod opened a pool of 50 connections: ๐Ÿ“ Total Attempted Connections = 600 ร— 50 = 30,000 connections
  • PostgreSQL exceeded max_connections (5,000). The database kernel spent 90% of its CPU time context-switching between stalled backend processes rather than executing SQL!

3. Long-Term Architectural Immunization:

  1. Deploy In-Cluster Database Connection Pooling (PgBouncer / AWS RDS Proxy):
    • Decouples application pod connection scaling from database process limits. 600 pods connect to RDS Proxy over 30,000 lightweight multiplexed connections; RDS Proxy maintains a clean, fixed pool of 300 real connections to PostgreSQL.
  2. Enforce Strict Client-Side Timeouts:
    • Database socket timeout = 2000ms.
    • HTTP client downstream timeout = 1500ms.
  3. Bulkhead Pattern & Circuit Breaking:
    • If the payment database is degrading, trip an Envoy / Resilience4j circuit breaker immediately, returning fast failure rather than letting threads stall.

๐Ÿ“Œ Question 4: The Dogpile Effect (Cache Stampede) & Mitigation

๐ŸŽฏ The Scenario & Interviewerโ€™s Trap

โ€œYour Redis cluster caches product catalog items for an e-commerce platform. A flash sale starts for an iPhone with 200,000 requests/sec hitting a single Redis key (product:iphone-16). At 12:00:00 AM, the keyโ€™s TTL expires. What happens to the underlying MySQL / Aurora database within the next 200 milliseconds, and how do you architecturally eliminate this without increasing cache TTL to infinity?โ€

Interviewerโ€™s Intent: To verify whether you understand the Dogpile Effect (Cache Stampede) and know how to implement algorithmic cache defenses like distributed mutexes or probabilistic early recomputation (XFetch).

๐Ÿ’ก Staff-Level Model Answer

flowchart TD
    subgraph Traffic["200,000 Req/sec for 'product:iphone-16'"]
        R1["Req 1"] & R2["Req 2"] & R3["Req 3..."] & R4["Req 200,000"]
    end

    Traffic --> Redis{"Redis: GET product:iphone-16"}
    Redis -- "TTL Expired at 12:00:00! (Cache Miss)" --> Miss["200,000 SIMULTANEOUS CACHE MISSES!"]
    
    subgraph Stampede["The Thundering Herd / Dogpile"]
        Miss --> DB["Aurora MySQL Database"]
        DB --> Crash["Database Connection Pool Collapses in 50ms!"]
    end

The 3 Architectural Solutions:

Strategy 1: Distributed Mutex Locking (Single-Flight Pattern)

When a cache miss occurs, the application process does not immediately query the database. It attempts to acquire a short-lived distributed lock in Redis:

# Acquire a 2-second lock using Redis SETNX:
if redis.set("lock:product:iphone-16", "1", nx=True, ex=2):
    try:
        # Only ONE worker fetches from DB:
        data = db.query("SELECT * FROM products WHERE id='iphone-16'")
        redis.set("product:iphone-16", data, ex=3600)
    finally:
        redis.delete("lock:product:iphone-16")
else:
    # All other 199,999 threads sleep for 50ms and re-check Redis:
    time.sleep(0.05)
    return redis.get("product:iphone-16")
  • In Go microservices, use golang.org/x/sync/singleflight to collapse concurrent duplicate requests within the same pod into a single shared database call.
Strategy 2: Probabilistic Early Invalidation (The XFetch Algorithm)

Instead of waiting for the key to expire at t = expiry, workers probabilistically recompute the cache before it expires: ๐Ÿ“ Recompute If: -ฮฒ ร— ฮด ร— ln(random()) > (expiry - currentTime)

  • Where ฮด is the time taken to compute the value from the database, and ฮฒ > 0 is an aggressive factor.
  • As the remaining TTL decreases, the probability of a background request proactively refreshing the key approaches 1.0. The key never actually expires for real users!
Strategy 3: Asynchronous Background Refresh Daemon

Decouple client reads from cache updates entirely:

  • Set key TTL to infinity.
  • An asynchronous event-driven worker (Kafka / EventBridge) listens for product updates and writes to Redis, so user HTTP requests never perform read-through queries to the database.

๐Ÿ“Œ Summary: SRE Practices & Incident Triage Reference

Outage Pattern Diagnostic Signature Staff Remediation
Alert Fatigue Transient blips trigger midnight pages Implement Multi-Window Multi-Burn-Rate alerting (14.4x rate in 1h AND 5m windows)
Prometheus OOM Cardinality explosion (user_id in labels) Apply metric_relabel_configs to drop labels, quarantine WAL, enforce sample_limit
Cascading 504s Low CPU, high latency, HPA scaling to ceiling Deploy PgBouncer / RDS Proxy, configure circuit breakers, kill long-running queries
Dogpile Cache Stampede Massive DB spike when hot key expires Use SingleFlight / Mutex lock, XFetch probabilistic refresh, or async cache warming

๐Ÿง  Complete Lesson-by-Lesson One-Line Memory Bank (Round 4 Scope)

๐Ÿ›๏ธ Enterprise Observability, SRE & Database Lessons

Lesson 4: CloudFront Edge Delivery & Log Management

# One-Line Question One-Line Answer
1 How do you prevent attackers from bypassing Amazon CloudFront + AWS WAF and hitting your origin AWS ALB directly? Use CloudFront VPC Origins (keeping the ALB private) or restrict the ALB Security Group to the AWS-managed com.amazonaws.global.cloudfront.origin-facing prefix list + verify a secret custom header in WAF.
2 What is CloudFront Origin Shield, and how does it protect backend Kubernetes clusters during traffic spikes? An additional centralized caching layer placed in front of your origin that collapses duplicate cache misses from 600+ global Edge PoPs into a single origin fetch.
3 How does the Hot / Warm / Cold Tiered Log Architecture cut observability spend by 80%? Vector / FluentBit routes ERROR/SECURITY logs to Hot OpenSearch (7 days), operational metrics to Prometheus, and streams 100% of raw verbose logs compressed in Zstandard Parquet directly to Cold S3 queried via Amazon Athena.
4 What HTTP Cache-Control directive allows CloudFront to immediately serve a slightly expired cached object while asynchronously refreshing it in the background? Cache-Control: max-age=60, stale-while-revalidate=300, stale-if-error=86400.

Lesson 5: RUM Specs, Telemetry & SRE Standards

# One-Line Question One-Line Answer
1 What are the 3 Google Core Web Vitals tracked by Real User Monitoring (RUM) SDKs? LCP (Largest Contentful Paint < 2.5s), INP (Interaction to Next Paint < 200ms), and CLS (Cumulative Layout Shift < 0.1).
2 What W3C standard HTTP header connects a userโ€™s browser click in RUM all the way through API Gateways, Kafka queues, and database queries? traceparent (00-<32-hex-trace-id>-<16-hex-span-id>-<flags>).
3 What is the critical difference between Head-Based Sampling and Tail-Based Sampling in OpenTelemetry? Head-based makes a random coin-flip decision (1%) when the request enters (missing 99% of rare errors); Tail-based buffers spans in the OTel Collector and keeps 100% of traces containing errors or high latency.
4 Define SLI, SLO, and SLA in one crisp line. SLI is the actual measurement (99.92% good requests), SLO is the internal engineering target (99.95%), and SLA is the external legal contract with financial penalties (99.90%).
5 How many minutes of downtime per 30-day month are allowed by a 99.9% (โ€œThree Ninesโ€) vs 99.99% (โ€œFour Ninesโ€) SLO? 99.9% = 43.2 minutes/month; 99.99% = 4.32 minutes/month.

Lesson 6: Securing Scalable Systems, KPIs, KRIs & Auditing

# One-Line Question One-Line Answer
1 What is the fundamental difference between a KPI (Key Performance Indicator) and a KRI (Key Risk Indicator)? A KPI measures how efficiently you are achieving goals (Deployments/Day), whereas a KRI is an early-warning metric measuring how close you are to a failure or breach (% of unpatched critical CVEs or subnet IPs <15%).
2 What are the 4 DORA metrics used to measure engineering platform velocity and stability? Deployment Frequency, Lead Time for Changes, Change Failure Rate (CFR), and Failed Deployment Recovery Time (MTTR).
3 How does Falco or Cilium Tetragon detect a container breakout or reverse shell in real time? By attaching eBPF probes to Linux kernel syscalls (execve, connect, openat), alerting or killing the process in kernel-space the millisecond a web container spawns /bin/sh or reads /etc/shadow.

Lesson 8: DB Seeding, Migrations & Cyclic Dependencies

# One-Line Question One-Line Answer
1 Why must you never execute database schema migrations (flyway/alembic) inside the application containerโ€™s startup entrypoint script? When Kubernetes scales up 20 pods simultaneously, all 20 pods race to run DDL migrations at the same millisecond, causing schema lock contention and CrashLoopBackOff.
2 What mandatory SQL session timeout must be set at the top of every production migration script to prevent a blocked DDL statement from queuing all application SELECT queries? SET lock_timeout = '2s'; SET statement_timeout = '10s';.
3 Why must you always use CREATE INDEX CONCURRENTLY instead of CREATE INDEX on live PostgreSQL production tables? Standard CREATE INDEX locks the table against all writes (INSERT/UPDATE/DELETE); CONCURRENTLY builds the index in the background without blocking concurrent writes.
4 What are the 3 phases of the Expand-and-Contract (Parallel Change) Pattern for renaming or dropping a column with zero downtime? (1) Expand: Add new nullable column & deploy dual-write code โ†’ (2) Migrate: Backfill historical rows & switch reads โ†’ (3) Contract: Remove old column references in code, then drop old column in a future release.

Lesson 12: War Room Incident Defense & RCAs

# One-Line Question One-Line Answer
1 What is the golden rule of a Sev-1 War Room during the first 15 minutes of a catastrophic outage? Mitigate Customer Impact First, Diagnose Root Cause Secondโ€”stop the bleeding via rollback, traffic failover, feature flag kill-switch, or load shedding before debugging code.
2 Why must a Load Shedder use a LIFO (Last-In, First-Out) or CoDel queue instead of a long FIFO queue during an overload? In a deep FIFO queue, every request waits 10 seconds only to be processed after the client already timed out; LIFO serves fresh requests immediately in <50ms and drops stale expired requests.
3 What is Metastable Failure (Latching Overload), where a cluster remains 100% dead at 5xx even after external traffic drops back down to normal low levels? Retry storms, exhausted connection pools, and JVM garbage collection thrashing lock the system into a self-sustaining failure loop that cannot recover without shedding 100% of load or resetting retry queues.

๐Ÿšจ Incident Defense & Triage Modules (Modules 1โ€“7 One-Line Recall)

# Incident Triage Scenario One-Line Root Cause & Fix
1 Pod stuck in ContainerCreating across AZs EBS volume is single-AZ locked in AZ-a while pod scheduled in AZ-b; fix StorageClass with volumeBindingMode: WaitForFirstConsumer.
2 Pod stuck in Terminating forever Finalizer deadlock or stuck NFS/EBS unmount (D-state process); inspect metadata.finalizers and unmount stale volume.
3 WireGuard / ClusterMesh drops large TLS POSTs 60-byte WireGuard header exceeds 1500 MTU and firewall drops ICMP Type 3 Code 4; clamp TCP MSS or set interface MTU to 1420.
4 TGW stateful firewall drops 50% of return packets Outbound flow hits Firewall AZ-a while return flow hashes to Firewall AZ-b; enable ApplianceModeSupport = enable on the TGW attachment.
5 ArgoCD Application stuck in perpetual OutOfSync HPA or MutatingWebhook dynamically modifies fields (spec.replicas) defined statically in Git; add ignoreDifferences + RespectIgnoreDifferences=true.
6 Chaos Mesh deleted but 50% packet loss remains chaos-daemon crashed before removing kernel tc netem rule; clear manually via nsenter -t <pid> -n tc qdisc del dev eth0 root.
7 Milvus Vector DB QueryNode OOMKilled on load In-memory HNSW graph index requires 1.5ร—โ€“2ร— raw vector byte size in RAM; increase node memory or switch to SQ8 / DiskANN quantization.
8 vLLM GPU pod CUDA Out Of Memory under burst KV Cache + activation memory exceeded VRAM during long-context prefill; tune --gpu-memory-utilization 0.88 and cap --max-model-len.
9 RDS Proxy fails to reduce database connections Application executes SET session variables or prepared statements, triggering Connection Pinning; remove session state mutations.
10 ALB returns transient 502 Bad Gateway on deploy Pod shuts down on SIGTERM before ALB finishes deregistering target IP; add preStop: sleep 15 hook and enable ALB Pod Readiness Gates.