Failure Mode Interview Questions
Questions about failure modes test your operational experience and ability to design resilient systems.
Detection & Diagnosis
Q1: You notice that every day at 3 AM, response times spike for 5 minutes. How would you investigate?
Answer:
- Check for scheduled jobs: Look at crontabs, batch jobs, or scheduled tasks that run at 3 AM
- Check cache expiration: If cache TTLs are set to expire around that time, it could be a cache stampede
- Check backups: Database backups can cause I/O spikes
- Check log rotation: Log rotation and compression can spike CPU/disk
- Check for thundering herd: If multiple instances run the same scheduled job at 3 AM
- Check external dependencies: Maybe a third-party service has maintenance at that time
Investigation tools:
- APM traces during the spike window
- Correlate metrics: CPU, memory, disk I/O, network during the spike
- Check application logs for errors during that period
- Query slow query logs for the database
Most likely fix: Add jitter to scheduled jobs, move batch processing to a queue, or stagger cache TTLs.
Q2: A service shows 100% CPU usage but normal request rates. What could be wrong?
Answer: Several possibilities:
- Infinite loop or tight loop bug: A code path that spins without yielding
- Garbage collection thrashing: Memory pressure causing constant GC
- Cryptocurrency miner: Security breach — a process consuming CPU for mining
- Log processing: Excessive logging or log shipping consuming CPU
- DNS resolution loop: Misconfigured DNS causing constant resolution attempts
- Connection retry storm: Rapidly retrying failed connections
Investigation:
# What's consuming CPU?
top -c -p $(pgrep -d',' java)
# Thread dump (Java)
jstack <pid>
# Profile the process
perf top -p <pid>
# Check for suspicious processes
ps aux --sort=-%cpu | head -20
Q3: How would you diagnose a memory leak in a production Java service?
Answer: Systematic approach:
- Confirm the leak: Monitor heap usage over time — look for sawtooth pattern where each GC cycle frees less memory
- Get a heap dump:
jmap -dump:format=b,file=heap.bin <pid>or configure-XX:+HeapDumpOnOutOfMemoryError - Analyze the dump: Use Eclipse MAT or VisualVM to find:
- Objects with the most retained memory
- Dominator trees showing what’s keeping objects alive
- Leak suspects report
- Common causes:
- Unclosed resources (connections, streams)
- Growing caches without eviction
- Event listeners not being removed
- Thread-local variables not being cleaned
- Static collections that grow over time
- Verify the fix: Deploy to staging, run load tests, monitor heap usage
Pro tip: Use -XX:+UseG1GC -XX:MaxGCPauseMillis=200 to make GC behavior more predictable while investigating.
Prevention & Design
Q4: How would you design a system to handle a database failover without dropping requests?
Answer: Multi-layer approach:
- Connection layer: Use a connection pool that supports failover (PgBouncer, ProxySQL)
- Application layer:
- Retry logic with exponential backoff for transient failures
- Circuit breaker to stop retrying if the database is down for extended periods
- Read from replicas while primary is recovering
- Database layer:
- Streaming replication with synchronous commit for zero data loss
- Automatic failover (Patroni, RDS Multi-AZ)
- Health checks every few seconds
- Traffic layer:
- Queue writes during failover (accept the request, process later)
- Return cached data for reads during failover
- Return 202 Accepted for writes, process asynchronously
Architecture:
Client → Load Balancer → App Server → Connection Pool → Primary DB
→ Read Replica (for reads)
→ Queue (for writes during failover)
Q5: How do you prevent cascading failures in a microservices architecture?
Answer: Defense in depth:
-
Circuit breakers (every service-to-service call):
@CircuitBreaker(name = "userService", fallbackMethod = "getUserFallback") public User getUser(String id) { return userServiceClient.get(id); } public User getUserFallback(String id) { return User.cached(id); // or default user } -
Bulkheads (isolate thread pools per dependency):
@Bulkhead(name = "paymentService", type = Type.THREADPOOL) public PaymentResult processPayment(PaymentRequest req) { // ... } -
Timeouts (every external call has a timeout):
- Don’t use infinite timeouts
- Set timeouts based on the downstream service’s p99 latency
- Propagate timeout budgets through the call chain
-
Load shedding (drop low-priority traffic when overloaded):
- Priority queues: process critical requests first
- Rate limiting: reject excess traffic
- Return 429 Too Many Requests
-
Graceful degradation (serve partial results):
- If recommendation service is down, show popular items instead
- If search is down, show cached results
- If analytics is down, skip tracking
Q6: How would you handle a situation where a third-party payment provider goes down?
Answer: Layered fallback strategy:
-
Immediate (0-5 minutes):
- Circuit breaker trips, stop sending requests to the failed provider
- Queue payment requests for later processing
- Show users: “Payment is being processed, you’ll receive confirmation shortly”
-
Short-term (5-30 minutes):
- Switch to backup payment provider (Stripe → Adyen fallback)
- Process queued payments through the backup
- Notify operations team
-
Long-term (30+ minutes):
- If no backup, offer alternative payment methods (bank transfer, invoice)
- Send status updates to affected users
- Coordinate with the provider for ETA
-
Design for this from the start:
- Abstract payment logic behind an interface
- Implement multiple payment provider integrations
- Use feature flags to switch providers
- Queue all payment operations for retry capability
Incident Response
Q7: You’re paged at 2 AM because the system is down. Walk me through your process.
Answer: Structured incident response:
-
Assess (2 minutes):
- What’s the blast radius? (All users? Specific region? Specific feature?)
- What changed recently? (Deployment? Config change? Traffic spike?)
- Is it getting worse or staying stable?
-
Communicate (1 minute):
- Open an incident channel
- Notify stakeholders: “We’re aware of the issue, investigating”
- Assign roles: incident commander, communicator, investigator
-
Mitigate (5-15 minutes):
- Rollback if there was a recent deployment
- Failover if a component is down
- Scale if it’s a capacity issue
- Enable circuit breakers if it’s a cascading failure
- Implement load shedding if it’s an overload
-
Investigate (parallel with mitigation):
- Check dashboards: error rates, latency, traffic, resource usage
- Check recent changes: deployments, config changes, infrastructure changes
- Check dependencies: are third-party services healthy?
- Check logs: what errors are being reported?
-
Resolve:
- Apply the fix
- Verify the system is recovering
- Monitor for regression
-
Post-mortem (next day):
- Document the timeline
- Identify root cause
- Create action items to prevent recurrence
Q8: How would you handle a situation where a deployment causes data corruption?
Answer: Critical incident — highest priority:
-
Stop the bleeding:
- Immediately rollback the deployment
- Stop all writes to the affected tables/database
- Enable read-only mode if possible
-
Assess the damage:
- When did the corruption start? (correlate with deployment time)
- How many records are affected?
- Is the corruption still spreading?
-
Recover the data:
- Best case: Point-in-time recovery to just before the deployment
- If that’s not possible: Restore from the most recent clean backup
- If backup is too old: Use write-ahead logs (WAL) to replay transactions up to the corruption point
-
Verify:
- Run data integrity checks on the restored data
- Compare record counts and checksums
- Verify with users that their data is correct
-
Prevent recurrence:
- Add data validation to the code that caused corruption
- Implement database constraints (CHECK, FOREIGN KEY)
- Add integration tests for the specific scenario
- Implement canary deployments to catch issues before full rollout
Q9: What would you do if you discover that your system has been running with split brain for hours?
Answer: This is a serious data consistency issue:
-
Stop both partitions from accepting writes immediately
-
Assess the damage:
- How many writes went to each partition?
- Is there overlap (same records written to both)?
- What’s the time window of the split?
-
Choose a primary:
- Which partition has the most recent data?
- Which partition has the most writes?
- Which partition is more trustworthy (was it the original primary)?
-
Reconcile data:
- For non-conflicting writes: merge both sets
- For conflicting writes (same record, different values):
- Use last-write-wins (if timestamps are trustworthy)
- Use the primary partition’s version
- Flag for manual review if the data is critical
-
Recover:
- Promote the chosen primary
- Apply reconciled data
- Restart the other partition as a replica
- Verify data consistency
-
Prevent recurrence:
- Implement proper fencing tokens
- Use consensus algorithms (Raft/Paxos)
- Set up monitoring for split brain detection
- Reduce the time to detect partitions
Rapid-Fire Questions
| Question | Answer |
|---|---|
| What’s the OOM killer? | Linux kernel process that kills processes when the system runs out of memory. |
| How do you find what’s using all disk space? | du -sh /* | sort -rh or ncdu / for interactive exploration. |
| What’s a health check vs. a readiness check? | Health = “is the service alive?”; Readiness = “is the service ready to receive traffic?” |
| How do you detect a memory leak? | Monitor heap usage over time; look for sawtooth pattern where baseline keeps increasing. |
| What’s the difference between a hotfix and a rollback? | Rollback = revert to previous version; Hotfix = deploy a new fix forward. |
| How do you handle a thundering herd on startup? | Add jitter to startup delay, use readiness probes, gradually ramp up traffic. |
| What’s graceful degradation? | Serving partial/best-effort results instead of failing completely. |
| How do you test for cascading failures? | Chaos engineering — kill services, inject latency, simulate network partitions. |
| What’s a write-ahead log (WAL)? | A log of all database changes before they’re applied, used for recovery and replication. |
| How do you prevent data loss during failover? | Synchronous replication — don’t acknowledge writes until replicas confirm. |
| What’s the difference between RPO and RTO? | RPO = how much data you can lose; RTO = how long recovery takes. |
| How do you handle backpressure? | Rate limiting, queue depth limits, load shedding, tell senders to slow down. |