Operational Resilience and Incident Response: Best Practices for Distributed Systems¶
Objective: Master production-grade operational resilience across RKE2, Postgres, Prefect, Redis, ML pipelines, and air-gapped clusters. When you need to survive incidents, maintain uptime, and recover gracefully—this guide provides complete operational playbooks and incident response frameworks.
Introduction¶
Operational resilience is the foundation of reliable distributed systems. Without proper operational practices, systems fail silently, incidents escalate, and recovery takes hours instead of minutes. This guide provides a complete framework for building, operating, and maintaining resilient systems.
What This Guide Covers: - Philosophy of operational readiness - SLAs, SLOs, and SLIs - Runbook architecture and templates - Incident response lifecycle - Failure Mode & Effects Analysis (FMEA) - Disaster recovery and business continuity - Observability for on-call reality - Test playbooks and chaos engineering - People, communication, and rotation practices - Anti-patterns and failure prevention - Agentic LLM integration for operations
Prerequisites: - Understanding of distributed systems and Kubernetes - Familiarity with Postgres, Redis, and orchestration systems - Experience with incident response and on-call rotations
Philosophy of Operational Readiness¶
What "Operational Maturity" Means¶
Operational Maturity is the ability to: - Detect incidents before users notice - Respond to incidents within defined SLAs - Recover from failures automatically or with minimal manual intervention - Learn from incidents and prevent recurrence - Scale operations without proportional increase in operational burden
Maturity Levels: 1. Reactive: Fix issues as they occur 2. Proactive: Monitor and prevent issues 3. Predictive: Anticipate and prepare for issues 4. Resilient: Absorb and recover from failures automatically
Why System Survivability Equals System Value¶
Survivability is the system's ability to: - Continue operating during partial failures - Degrade gracefully under load - Recover automatically from transient failures - Maintain data integrity during incidents
Value Equation:
A system that fails frequently or loses data has zero value, regardless of features.
Why Docs and Runbooks Matter More Than Architecture Diagrams¶
Runbooks are operational knowledge codified: - Architecture diagrams show "what should be" - Runbooks show "what to do when it isn't"
Runbook Value: - Reduces mean time to recovery (MTTR) - Enables junior engineers to handle incidents - Prevents knowledge loss when engineers leave - Standardizes incident response
Example: An architecture diagram shows Postgres primary → replica flow. A runbook shows: 1. How to detect replication lag 2. How to failover if primary fails 3. How to restore replication 4. How to verify data integrity
The Difference Between Robustness vs Resilience vs Antifragility¶
Robustness: System resists failure (hard to break).
Resilience: System recovers from failure (breaks but heals).
Antifragility: System improves from failure (gets stronger).
Example: - Robust: Postgres with strong constraints (hard to corrupt) - Resilient: Postgres with automatic failover (recovers from primary failure) - Antifragile: Postgres that learns from failures to improve replication logic
How Incident Response is Part of System Design¶
Design for Operations: - Systems should be observable (logs, metrics, traces) - Systems should fail loudly (not silently) - Systems should degrade gracefully (not catastrophically) - Systems should be recoverable (not permanently broken)
Example: A microservice that: - Logs all errors with context - Exposes health endpoints - Implements circuit breakers - Supports graceful shutdown - Has automated rollback capability
SLAs / SLOs / SLIs¶
Service Level Definitions¶
SLA (Service Level Agreement): Contract with users about service quality.
SLO (Service Level Objective): Internal target for service quality.
SLI (Service Level Indicator): Measured metric of service quality.
Availability¶
Targets: - 99.9% (Three Nines): 8.76 hours downtime/year - 99.95%: 4.38 hours downtime/year - 99.99% (Four Nines): 52.56 minutes downtime/year - 99.999% (Five Nines): 5.26 minutes downtime/year
Example SLOs:
availability_slos:
postgres_primary:
target: 99.95%
measurement: "Uptime of primary database"
window: "30 days rolling"
api_endpoints:
target: 99.9%
measurement: "HTTP 200 responses / total requests"
window: "7 days rolling"
ml_inference:
target: 99.5%
measurement: "Successful inference requests / total requests"
window: "24 hours rolling"
Durability¶
Targets: - 99.999999999% (Eleven Nines): 1 object loss per 10 billion objects - 99.999999% (Eight Nines): 1 object loss per 100 million objects
Example SLOs:
durability_slos:
postgres_data:
target: 99.999999999%
measurement: "Data loss events"
window: "Annual"
lakehouse_tables:
target: 99.999999%
measurement: "Table corruption events"
window: "Annual"
ml_model_artifacts:
target: 99.999%
measurement: "Model artifact loss"
window: "Annual"
Latency¶
Targets: - P50 (Median): 50% of requests below this - P95: 95% of requests below this - P99: 99% of requests below this - P99.9: 99.9% of requests below this
Example SLOs:
latency_slos:
api_p50:
target: "< 100ms"
measurement: "50th percentile response time"
api_p95:
target: "< 500ms"
measurement: "95th percentile response time"
api_p99:
target: "< 1000ms"
measurement: "99th percentile response time"
postgres_query_p95:
target: "< 50ms"
measurement: "95th percentile query time"
ml_inference_p95:
target: "< 200ms"
measurement: "95th percentile inference time"
Throughput¶
Targets: - Requests per second (RPS) - Transactions per second (TPS) - Messages per second (MPS)
Example SLOs:
throughput_slos:
api_rps:
target: "> 1000 RPS"
measurement: "Requests per second"
postgres_tps:
target: "> 500 TPS"
measurement: "Transactions per second"
redis_stream_mps:
target: "> 10000 MPS"
measurement: "Messages per second"
Data Freshness¶
Targets: - Time between data creation and availability - ETL pipeline latency - Replication lag
Example SLOs:
freshness_slos:
etl_pipeline:
target: "< 5 minutes"
measurement: "Time from source to destination"
postgres_replication:
target: "< 1 second"
measurement: "Replication lag"
lakehouse_updates:
target: "< 15 minutes"
measurement: "Time from write to queryable"
Geospatial ETL Timeliness¶
Example SLOs:
geospatial_etl_slos:
tile_generation:
target: "< 30 minutes"
measurement: "Time to generate tiles for new data"
spatial_indexing:
target: "< 10 minutes"
measurement: "Time to index new geometries"
geospatial_aggregation:
target: "< 5 minutes"
measurement: "Time to aggregate spatial data"
ML Inference Stability¶
Example SLOs:
ml_inference_slos:
model_availability:
target: 99.5%
measurement: "Model serving availability"
inference_latency_p95:
target: "< 200ms"
measurement: "95th percentile inference time"
prediction_accuracy:
target: "> 95%"
measurement: "Prediction accuracy vs ground truth"
Postgres Replication Lag Ceilings¶
Example SLOs:
postgres_replication_slos:
streaming_replication:
target: "< 1 second"
measurement: "WAL lag"
logical_replication:
target: "< 5 seconds"
measurement: "Logical replication lag"
cross_region_replication:
target: "< 10 seconds"
measurement: "Cross-region replication lag"
Redis Stream Consumer Lag¶
Example SLOs:
redis_stream_slos:
consumer_lag:
target: "< 1000 messages"
measurement: "Pending messages in consumer group"
processing_latency:
target: "< 5 seconds"
measurement: "Time from message arrival to processing"
Kubernetes Pod Readiness Windows¶
Example SLOs:
kubernetes_slos:
pod_startup:
target: "< 30 seconds"
measurement: "Time from pod creation to ready"
deployment_rollout:
target: "< 5 minutes"
measurement: "Time for complete deployment rollout"
node_ready:
target: "< 2 minutes"
measurement: "Time from node join to ready"
Tolerable Drift Windows¶
Example SLOs:
drift_slos:
configuration_drift:
target: "< 1 hour"
measurement: "Time before drift detection and alert"
time_drift:
target: "< 100ms"
measurement: "Clock skew between nodes"
schema_drift:
target: "< 24 hours"
measurement: "Time before schema drift detection"
Runbook Architecture¶
Startup Runbooks¶
Purpose: Ensure systems start correctly after deployment or restart.
Structure: 1. Prerequisites check 2. Dependency verification 3. Service startup sequence 4. Health check validation 5. Smoke tests
Example: Postgres Cluster Startup:
#!/bin/bash
# runbooks/postgres-cluster-startup.sh
set -euo pipefail
echo "=== Postgres Cluster Startup Runbook ==="
# 1. Prerequisites
echo "Checking prerequisites..."
kubectl get nodes | grep -q Ready || exit 1
kubectl get pvc -n postgres | grep -q Bound || exit 1
# 2. Start PGO operator
echo "Starting PGO operator..."
kubectl scale deployment postgres-operator --replicas=1 -n pgo-system
# 3. Wait for operator ready
echo "Waiting for PGO operator..."
kubectl wait --for=condition=ready pod -l name=postgres-operator -n pgo-system --timeout=5m
# 4. Start Postgres cluster
echo "Starting Postgres cluster..."
kubectl patch postgrescluster postgres-cluster -n postgres --type merge -p '{"spec":{"shutdown":false}}'
# 5. Wait for cluster ready
echo "Waiting for Postgres cluster..."
kubectl wait --for=condition=ready postgrescluster postgres-cluster -n postgres --timeout=10m
# 6. Verify replication
echo "Verifying replication..."
kubectl exec -it postgres-cluster-instance1-0 -n postgres -- psql -c "SELECT * FROM pg_stat_replication;"
# 7. Run smoke tests
echo "Running smoke tests..."
kubectl exec -it postgres-cluster-instance1-0 -n postgres -- psql -c "SELECT 1;"
echo "=== Postgres cluster startup complete ==="
Troubleshooting Runbooks¶
Purpose: Diagnose and resolve common issues.
Structure: 1. Symptom identification 2. Diagnostic steps 3. Common causes 4. Resolution steps 5. Verification
Example: Postgres Replication Lag:
#!/bin/bash
# runbooks/postgres-replication-lag-troubleshooting.sh
set -euo pipefail
echo "=== Postgres Replication Lag Troubleshooting ==="
# 1. Check replication status
echo "Checking replication status..."
kubectl exec -it postgres-cluster-instance1-0 -n postgres -- psql -c "
SELECT
client_addr,
state,
sync_state,
pg_wal_lsn_diff(pg_current_wal_lsn(), sent_lsn) AS sent_lag_bytes,
pg_wal_lsn_diff(pg_current_wal_lsn(), write_lsn) AS write_lag_bytes,
pg_wal_lsn_diff(pg_current_wal_lsn(), flush_lsn) AS flush_lag_bytes,
pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) AS replay_lag_bytes
FROM pg_stat_replication;
"
# 2. Check WAL generation rate
echo "Checking WAL generation rate..."
kubectl exec -it postgres-cluster-instance1-0 -n postgres -- psql -c "
SELECT
pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), '0/0')) AS total_wal_size,
pg_size_pretty(pg_current_wal_lsn()) AS current_wal_lsn;
"
# 3. Check network connectivity
echo "Checking network connectivity..."
kubectl exec -it postgres-cluster-instance1-0 -n postgres -- ping -c 3 postgres-cluster-instance2-0.postgres-cluster-pods.postgres.svc.cluster.local
# 4. Check replica resources
echo "Checking replica resources..."
kubectl top pod -n postgres | grep postgres-cluster-instance2
# 5. Common resolutions
echo "Common resolutions:"
echo "1. Increase replica resources if CPU/memory constrained"
echo "2. Check network latency between primary and replica"
echo "3. Verify WAL archiving is not blocking"
echo "4. Check for long-running queries on replica"
"Break Glass" Runbooks¶
Purpose: Emergency procedures for critical failures.
Structure: 1. Emergency assessment 2. Immediate containment 3. Service restoration 4. Data integrity verification 5. Post-incident review
Example: Postgres Primary Failure:
#!/bin/bash
# runbooks/postgres-primary-failure-break-glass.sh
set -euo pipefail
echo "=== BREAK GLASS: Postgres Primary Failure ==="
echo "WARNING: This is an emergency procedure. Proceed with caution."
# 1. Verify primary is actually down
echo "Verifying primary failure..."
PRIMARY_POD=$(kubectl get pod -n postgres -l postgres-operator.crunchydata.com/role=master -o jsonpath='{.items[0].metadata.name}')
if kubectl get pod $PRIMARY_POD -n postgres | grep -q Running; then
echo "ERROR: Primary pod appears to be running. Aborting."
exit 1
fi
# 2. Promote replica to primary
echo "Promoting replica to primary..."
kubectl patch postgrescluster postgres-cluster -n postgres --type merge -p '{"spec":{"instances":[{"name":"instance2","replicationRole":"primary"}]}}'
# 3. Wait for promotion
echo "Waiting for promotion..."
sleep 30
# 4. Verify new primary
echo "Verifying new primary..."
kubectl exec -it postgres-cluster-instance2-0 -n postgres -- psql -c "SELECT pg_is_in_recovery();"
# 5. Update application connections
echo "Updating application connections..."
# Update connection strings to point to new primary
# This is application-specific
# 6. Verify data integrity
echo "Verifying data integrity..."
kubectl exec -it postgres-cluster-instance2-0 -n postgres -- psql -c "
SELECT
schemaname,
tablename,
n_live_tup,
n_dead_tup
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 10;
"
echo "=== Break glass procedure complete ==="
echo "NEXT STEPS:"
echo "1. Investigate root cause of primary failure"
echo "2. Restore failed primary as new replica"
echo "3. Schedule postmortem"
Maintenance Playbooks¶
Purpose: Standard procedures for planned maintenance.
Structure: 1. Pre-maintenance checks 2. Maintenance steps 3. Verification 4. Rollback procedures
Example: Postgres VACUUM Maintenance:
#!/bin/bash
# runbooks/postgres-vacuum-maintenance.sh
set -euo pipefail
echo "=== Postgres VACUUM Maintenance ==="
# 1. Pre-maintenance checks
echo "Pre-maintenance checks..."
kubectl exec -it postgres-cluster-instance1-0 -n postgres -- psql -c "
SELECT
schemaname,
tablename,
n_live_tup,
n_dead_tup,
last_vacuum,
last_autovacuum
FROM pg_stat_user_tables
WHERE n_dead_tup > 1000
ORDER BY n_dead_tup DESC;
"
# 2. Run VACUUM ANALYZE on high-dead-tuple tables
echo "Running VACUUM ANALYZE..."
kubectl exec -it postgres-cluster-instance1-0 -n postgres -- psql -c "
VACUUM ANALYZE VERBOSE;
"
# 3. Verify results
echo "Verifying VACUUM results..."
kubectl exec -it postgres-cluster-instance1-0 -n postgres -- psql -c "
SELECT
schemaname,
tablename,
n_live_tup,
n_dead_tup
FROM pg_stat_user_tables
WHERE n_dead_tup > 1000;
"
echo "=== VACUUM maintenance complete ==="
Recovery and Reinstatement Workflows¶
Purpose: Restore services after incidents.
Structure: 1. Damage assessment 2. Recovery planning 3. Data restoration 4. Service reinstatement 5. Verification and monitoring
Example: Postgres Data Corruption Recovery:
#!/bin/bash
# runbooks/postgres-data-corruption-recovery.sh
set -euo pipefail
echo "=== Postgres Data Corruption Recovery ==="
# 1. Damage assessment
echo "Assessing damage..."
kubectl exec -it postgres-cluster-instance1-0 -n postgres -- psql -c "
SELECT
datname,
pg_database_size(datname) AS size
FROM pg_database
WHERE datname NOT IN ('template0', 'template1', 'postgres');
"
# 2. Identify corrupted tables
echo "Identifying corrupted tables..."
kubectl exec -it postgres-cluster-instance1-0 -n postgres -- psql -c "
SELECT
schemaname,
tablename,
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS size
FROM pg_tables
WHERE schemaname = 'public';
"
# 3. Restore from backup
echo "Restoring from backup..."
# This is backup-system specific
# Example: pg_restore from S3 backup
# 4. Verify restoration
echo "Verifying restoration..."
kubectl exec -it postgres-cluster-instance1-0 -n postgres -- psql -c "
SELECT COUNT(*) FROM important_table;
"
echo "=== Recovery complete ==="
Hot Path vs Cold Path Failure Diagnosis¶
Hot Path: User-facing, real-time operations.
Cold Path: Batch processing, non-real-time operations.
Diagnosis Strategy:
graph TB
subgraph Hot["Hot Path Failure"]
Detect["Detect Failure<br/>(< 1 minute)"]
Triage["Triage Impact<br/>(< 5 minutes)"]
Contain["Contain Failure<br/>(< 10 minutes)"]
Restore["Restore Service<br/>(< 30 minutes)"]
end
subgraph Cold["Cold Path Failure"]
Detect2["Detect Failure<br/>(< 1 hour)"]
Triage2["Triage Impact<br/>(< 4 hours)"]
Contain2["Contain Failure<br/>(< 8 hours)"]
Restore2["Restore Service<br/>(< 24 hours)"]
end
Detect --> Triage
Triage --> Contain
Contain --> Restore
Detect2 --> Triage2
Triage2 --> Contain2
Contain2 --> Restore2
style Hot fill:#ffebee
style Cold fill:#e8f5e9 Dependency-Aware Troubleshooting¶
Dependency Map:
graph TB
subgraph Frontend["Frontend Layer"]
NiceGUI["NiceGUI App"]
end
subgraph API["API Layer"]
FastAPI["FastAPI Service"]
end
subgraph Data["Data Layer"]
Postgres["Postgres"]
Redis["Redis"]
end
subgraph ML["ML Layer"]
MLflow["MLflow"]
Inference["Inference Service"]
end
subgraph ETL["ETL Layer"]
Prefect["Prefect"]
DuckDB["DuckDB"]
end
NiceGUI --> FastAPI
FastAPI --> Postgres
FastAPI --> Redis
FastAPI --> Inference
Inference --> MLflow
Prefect --> Postgres
Prefect --> DuckDB
style Frontend fill:#e1f5ff
style API fill:#fff4e1
style Data fill:#e8f5e9
style ML fill:#f3e5f5
style ETL fill:#ffebee Troubleshooting Flow: 1. Start from user-facing symptoms 2. Trace dependencies backward 3. Check each dependency's health 4. Identify root cause 5. Resolve from bottom up
Incident Response Lifecycle¶
1. Detection¶
Detection Methods: - Automated monitoring alerts - User reports - Synthetic monitoring - Log analysis - Metric anomalies
Detection SLO: Detect incidents within 1 minute of occurrence.
2. Triage¶
Triage Steps: 1. Confirm incident is real 2. Assess impact (users affected, severity) 3. Classify incident (P0, P1, P2, P3) 4. Assign incident commander 5. Open incident channel
Severity Levels: - P0 (Critical): Service down, data loss, security breach - P1 (High): Major feature broken, significant degradation - P2 (Medium): Minor feature broken, limited impact - P3 (Low): Cosmetic issues, no user impact
3. Containment¶
Containment Strategies: - Isolate affected systems - Rollback deployments - Disable features - Rate limit traffic - Failover to backup systems
Containment SLO: Contain incidents within 15 minutes of detection.
4. Remediation¶
Remediation Steps: 1. Follow runbooks 2. Apply fixes 3. Verify fixes 4. Monitor recovery 5. Document actions
Remediation SLO: Resolve incidents within 1 hour for P0, 4 hours for P1.
5. Root-Cause Analysis¶
RCA Process: 1. Gather evidence (logs, metrics, traces) 2. Timeline reconstruction 3. Identify root cause 4. Document findings 5. Propose preventive measures
6. Postmortem Documentation¶
Postmortem Template:
# Postmortem: [Incident Title]
## Summary
- **Date**: [Date]
- **Duration**: [Duration]
- **Impact**: [Users affected, services impacted]
- **Severity**: [P0/P1/P2/P3]
## Timeline
- [Time] - Incident detected
- [Time] - Triage started
- [Time] - Containment achieved
- [Time] - Remediation completed
- [Time] - Service restored
## Root Cause
[Detailed explanation of root cause]
## Impact
- Users affected: [Number]
- Services impacted: [List]
- Data loss: [Yes/No, details]
## Resolution
[Steps taken to resolve]
## Prevention
- [Action item 1]
- [Action item 2]
- [Action item 3]
## Lessons Learned
[Key takeaways]
## Action Items
- [ ] [Action item 1] - Owner: [Name] - Due: [Date]
- [ ] [Action item 2] - Owner: [Name] - Due: [Date]
7. Resilience Enhancement¶
Enhancement Steps: 1. Implement preventive measures 2. Update runbooks 3. Add monitoring 4. Improve automation 5. Test improvements
8. Preventive Engineering¶
Preventive Measures: - Chaos engineering - Load testing - Failure injection - Disaster recovery drills - Security audits
Failure Mode & Effects Analysis (FMEA)¶
FMEA Process¶
- Identify Failure Modes: How can each component fail?
- Assess Severity: Impact of failure (1-10 scale)
- Assess Occurrence: Likelihood of failure (1-10 scale)
- Assess Detection: Ability to detect failure (1-10 scale)
- Calculate RPN: Risk Priority Number = Severity × Occurrence × Detection
- Prioritize Actions: Address highest RPN first
Compute Layer FMEA¶
| Component | Failure Mode | Severity | Occurrence | Detection | RPN | Mitigation |
|---|---|---|---|---|---|---|
| K8s Node | Node crash | 9 | 3 | 2 | 54 | Node health checks, auto-replacement |
| K8s Pod | Pod OOM | 7 | 4 | 3 | 84 | Resource limits, HPA |
| GPU Node | GPU failure | 8 | 2 | 4 | 64 | GPU health monitoring, workload migration |
| Container | Image corruption | 6 | 2 | 5 | 60 | Image scanning, immutable tags |
Database Layer FMEA¶
| Component | Failure Mode | Severity | Occurrence | Detection | RPN | Mitigation |
|---|---|---|---|---|---|---|
| Postgres Primary | Primary crash | 10 | 2 | 2 | 40 | Automatic failover, replication |
| Postgres Replica | Replica lag | 7 | 3 | 3 | 63 | Replication monitoring, lag alerts |
| WAL Archive | Archive failure | 9 | 2 | 4 | 72 | Multiple archive locations, verification |
| Connection Pool | Pool exhaustion | 8 | 3 | 3 | 72 | Pool monitoring, connection limits |
Message Bus Layer FMEA¶
| Component | Failure Mode | Severity | Occurrence | Detection | RPN | Mitigation |
|---|---|---|---|---|---|---|
| Redis | Redis crash | 9 | 2 | 2 | 36 | Redis Sentinel, replication |
| Kafka | Broker failure | 8 | 2 | 2 | 32 | Multi-broker cluster, replication |
| NATS | NATS crash | 7 | 2 | 3 | 42 | NATS clustering, JetStream |
| Consumer | Consumer lag | 6 | 4 | 3 | 72 | Lag monitoring, auto-scaling |
ML Inference Layer FMEA¶
| Component | Failure Mode | Severity | Occurrence | Detection | RPN | Mitigation |
|---|---|---|---|---|---|---|
| Model Server | Server crash | 8 | 2 | 2 | 32 | Multiple replicas, health checks |
| Model Registry | Registry outage | 7 | 2 | 3 | 42 | Backup registry, caching |
| Feature Store | Feature stale | 6 | 3 | 4 | 72 | TTL monitoring, freshness checks |
| GPU | GPU OOM | 8 | 3 | 3 | 72 | GPU memory monitoring, batch sizing |
NiceGUI/API Layer FMEA¶
| Component | Failure Mode | Severity | Occurrence | Detection | RPN | Mitigation |
|---|---|---|---|---|---|---|
| NiceGUI | App crash | 7 | 3 | 2 | 42 | Health checks, auto-restart |
| FastAPI | API timeout | 6 | 4 | 3 | 72 | Timeout monitoring, circuit breakers |
| Load Balancer | LB failure | 9 | 2 | 2 | 36 | Multiple LBs, health checks |
| WebSocket | Connection drop | 5 | 4 | 4 | 80 | Reconnection logic, monitoring |
Storage Layer FMEA¶
| Component | Failure Mode | Severity | Occurrence | Detection | RPN | Mitigation |
|---|---|---|---|---|---|---|
| S3/MinIO | Object loss | 10 | 1 | 5 | 50 | Versioning, replication |
| Parquet | File corruption | 9 | 2 | 4 | 72 | Checksums, validation |
| Lakehouse | Table corruption | 9 | 2 | 3 | 54 | Table validation, backups |
| PVC | Volume failure | 8 | 2 | 3 | 48 | Volume replication, backups |
Network Layer FMEA¶
| Component | Failure Mode | Severity | Occurrence | Detection | RPN | Mitigation |
|---|---|---|---|---|---|---|
| Network | Partition | 9 | 2 | 2 | 36 | Multi-path routing, health checks |
| DNS | DNS failure | 8 | 2 | 3 | 48 | Multiple DNS servers, caching |
| Load Balancer | LB failure | 9 | 2 | 2 | 36 | Multiple LBs, health checks |
| Firewall | Rule misconfiguration | 7 | 3 | 4 | 84 | Automated testing, validation |
Disaster Recovery & Business Continuity¶
Backup & Restore Strategy for Postgres¶
Backup Strategy:
#!/bin/bash
# backup/postgres-backup.sh
# 1. Full backup
pg_dumpall -h postgres-primary -U postgres > backup_$(date +%Y%m%d_%H%M%S).sql
# 2. WAL archiving
# Configure in postgresql.conf:
# archive_mode = on
# archive_command = 'aws s3 cp %p s3://backups/postgres/wal/%f'
# 3. Point-in-time recovery
# Restore from backup + replay WAL to target time
Restore Strategy:
#!/bin/bash
# restore/postgres-restore.sh
# 1. Stop Postgres
kubectl scale statefulset postgres-cluster-instance1 --replicas=0 -n postgres
# 2. Restore from backup
psql -h postgres-primary -U postgres < backup_20240115_120000.sql
# 3. Replay WAL to target time
# Configure recovery_target_time in recovery.conf
# 4. Start Postgres
kubectl scale statefulset postgres-cluster-instance1 --replicas=1 -n postgres
Lakehouse Table Version Rollback¶
Rollback Strategy:
# lakehouse/rollback.py
import pyiceberg
def rollback_table(table_path: str, target_version: int):
"""Rollback lakehouse table to target version"""
table = pyiceberg.Table.from_path(table_path)
# Get current version
current_version = table.metadata.current_snapshot_id
# Rollback to target version
table.rollback_to_snapshot(target_version)
# Verify rollback
assert table.metadata.current_snapshot_id == target_version
MLflow Experiment Rehydration¶
Rehydration Strategy:
# mlflow/rehydrate.py
import mlflow
def rehydrate_experiment(experiment_id: str, backup_path: str):
"""Rehydrate MLflow experiment from backup"""
# Restore experiment metadata
mlflow.restore_experiment(experiment_id, backup_path)
# Restore runs
runs = mlflow.search_runs(experiment_ids=[experiment_id])
for run in runs:
mlflow.restore_run(run.info.run_id, backup_path)
Cross-Cluster Cold-Standby Design¶
Architecture:
graph TB
subgraph Primary["Primary Cluster"]
PrimaryK8s["K8s Cluster"]
PrimaryDB["Postgres Primary"]
PrimaryApp["Applications"]
end
subgraph Standby["Standby Cluster"]
StandbyK8s["K8s Cluster"]
StandbyDB["Postgres Standby"]
StandbyApp["Applications (Stopped)"]
end
PrimaryDB -->|"Replication"| StandbyDB
PrimaryApp -->|"Monitoring"| StandbyApp
style Primary fill:#e1f5ff
style Standby fill:#fff4e1 Failover Procedure:
#!/bin/bash
# failover/standby-activation.sh
# 1. Promote standby database
kubectl exec -it postgres-standby-0 -n postgres -- psql -c "SELECT pg_promote();"
# 2. Start standby applications
kubectl scale deployment app --replicas=3 -n standby
# 3. Update DNS/load balancer
# Point traffic to standby cluster
# 4. Verify services
kubectl get pods -n standby
Distributed Checkpointing¶
Checkpoint Strategy:
# checkpointing/distributed_checkpoint.py
class DistributedCheckpointer:
def checkpoint(self, state: dict, checkpoint_id: str):
"""Create distributed checkpoint"""
# Store checkpoint in multiple locations
self.store_checkpoint(state, checkpoint_id, "s3://checkpoints/")
self.store_checkpoint(state, checkpoint_id, "postgres://checkpoints/")
self.store_checkpoint(state, checkpoint_id, "redis://checkpoints/")
def restore(self, checkpoint_id: str) -> dict:
"""Restore from checkpoint"""
# Try to restore from any location
for location in ["s3", "postgres", "redis"]:
try:
return self.load_checkpoint(checkpoint_id, location)
except Exception:
continue
raise ValueError(f"Checkpoint {checkpoint_id} not found")
Air-Gapped Restore Operations¶
Restore Strategy:
#!/bin/bash
# airgap/restore.sh
# 1. Transfer backup to air-gapped cluster
# Via secure USB or physical media
# 2. Verify backup integrity
sha256sum backup.tar.gz > backup.sha256
sha256sum -c backup.sha256
# 3. Extract backup
tar -xzf backup.tar.gz
# 4. Restore services
./restore/postgres-restore.sh
./restore/redis-restore.sh
./restore/app-restore.sh
# 5. Verify restoration
./verify/verify-all.sh
Multi-Region Failover Patterns¶
Architecture:
graph TB
subgraph Region1["Region 1 (Primary)"]
R1App["Applications"]
R1DB["Postgres Primary"]
end
subgraph Region2["Region 2 (Standby)"]
R2App["Applications (Standby)"]
R2DB["Postgres Standby"]
end
subgraph Region3["Region 3 (Standby)"]
R3App["Applications (Standby)"]
R3DB["Postgres Standby"]
end
R1DB -->|"Replication"| R2DB
R1DB -->|"Replication"| R3DB
style Region1 fill:#e1f5ff
style Region2 fill:#fff4e1
style Region3 fill:#e8f5e9 Chaos Testing for Recovery Drills¶
Chaos Test Suite:
# chaos/recovery_drills.py
import chaosmesh
class RecoveryDrills:
def test_postgres_failover(self):
"""Test Postgres primary failover"""
# Kill primary pod
chaosmesh.kill_pod("postgres-primary")
# Verify automatic failover
assert self.verify_new_primary()
# Verify data integrity
assert self.verify_data_integrity()
def test_network_partition(self):
"""Test network partition recovery"""
# Partition network
chaosmesh.network_partition("app", "database")
# Verify graceful degradation
assert self.verify_graceful_degradation()
# Restore network
chaosmesh.restore_network()
# Verify recovery
assert self.verify_recovery()
Observability for On-Call Reality¶
Alert Tiers¶
Tier 1 (Critical): Page on-call immediately - Service down - Data loss - Security breach
Tier 2 (High): Page on-call within 15 minutes - Major degradation - Significant user impact
Tier 3 (Medium): Create ticket, no page - Minor issues - Limited impact
Tier 4 (Low): Log only - Informational - No action required
Actionable vs Noisy Alerts¶
Actionable Alert Criteria: - Clear symptom - Known resolution path - Actionable information - Appropriate severity
Noisy Alert Examples: - Alert on every error (should alert on error rate) - Alert on expected behavior - Alert without context - Alert that can't be acted upon
On-Call Rotations¶
Rotation Schedule: - Primary: Handles all Tier 1 and Tier 2 alerts - Secondary: Handles Tier 3 alerts, backup for primary - Escalation: Senior engineer for complex issues
Rotation Best Practices: - Rotate weekly - Include context in handoff - Document common issues - Provide runbooks
Operational Dashboards¶
Rancher Cluster Health Dashboard:
{
"dashboard": {
"title": "Rancher Cluster Health",
"panels": [
{
"title": "Node Status",
"targets": [
{
"expr": "kube_node_status_condition{condition=\"Ready\"}",
"legendFormat": "{{node}}"
}
]
},
{
"title": "Pod Status",
"targets": [
{
"expr": "kube_pod_status_phase",
"legendFormat": "{{pod}}"
}
]
},
{
"title": "Resource Usage",
"targets": [
{
"expr": "kube_node_status_allocatable_cpu_cores",
"legendFormat": "CPU: {{node}}"
},
{
"expr": "kube_node_status_allocatable_memory_bytes",
"legendFormat": "Memory: {{node}}"
}
]
}
]
}
}
Postgres Replication + WAL Backlog Dashboard:
{
"dashboard": {
"title": "Postgres Replication & WAL",
"panels": [
{
"title": "Replication Lag",
"targets": [
{
"expr": "pg_replication_lag_bytes",
"legendFormat": "{{replica}}"
}
]
},
{
"title": "WAL Generation Rate",
"targets": [
{
"expr": "rate(pg_wal_bytes_written[5m])",
"legendFormat": "WAL/s"
}
]
},
{
"title": "Replication Slots",
"targets": [
{
"expr": "pg_replication_slot_lag_bytes",
"legendFormat": "{{slot}}"
}
]
}
]
}
}
Redis Stream Lag Dashboard:
{
"dashboard": {
"title": "Redis Stream Lag",
"panels": [
{
"title": "Consumer Lag",
"targets": [
{
"expr": "redis_stream_consumer_lag",
"legendFormat": "{{consumer_group}}/{{consumer}}"
}
]
},
{
"title": "Stream Length",
"targets": [
{
"expr": "redis_stream_length",
"legendFormat": "{{stream}}"
}
]
},
{
"title": "Processing Rate",
"targets": [
{
"expr": "rate(redis_stream_messages_processed[5m])",
"legendFormat": "{{consumer_group}}"
}
]
}
]
}
}
Prefect Orchestration Failures Dashboard:
{
"dashboard": {
"title": "Prefect Orchestration",
"panels": [
{
"title": "Flow Run Failures",
"targets": [
{
"expr": "rate(prefect_flow_runs_failed[5m])",
"legendFormat": "{{flow_name}}"
}
]
},
{
"title": "Task Run Failures",
"targets": [
{
"expr": "rate(prefect_task_runs_failed[5m])",
"legendFormat": "{{task_name}}"
}
]
},
{
"title": "Agent Status",
"targets": [
{
"expr": "prefect_agent_status",
"legendFormat": "{{agent_name}}"
}
]
}
]
}
}
Inference Pipeline Stalls Dashboard:
{
"dashboard": {
"title": "ML Inference Pipeline",
"panels": [
{
"title": "Inference Latency",
"targets": [
{
"expr": "histogram_quantile(0.95, ml_inference_duration_seconds_bucket)",
"legendFormat": "P95"
}
]
},
{
"title": "Inference Failures",
"targets": [
{
"expr": "rate(ml_inference_failures_total[5m])",
"legendFormat": "{{model}}"
}
]
},
{
"title": "Queue Depth",
"targets": [
{
"expr": "ml_inference_queue_depth",
"legendFormat": "{{model}}"
}
]
}
]
}
}
NiceGUI Application Health Dashboard:
{
"dashboard": {
"title": "NiceGUI Application Health",
"panels": [
{
"title": "Request Rate",
"targets": [
{
"expr": "rate(nicegui_requests_total[5m])",
"legendFormat": "{{endpoint}}"
}
]
},
{
"title": "Error Rate",
"targets": [
{
"expr": "rate(nicegui_errors_total[5m])",
"legendFormat": "{{endpoint}}"
}
]
},
{
"title": "WebSocket Connections",
"targets": [
{
"expr": "nicegui_websocket_connections",
"legendFormat": "{{instance}}"
}
]
}
]
}
}
Tracing Needs for Multi-Hop Chains¶
Distributed Tracing:
# tracing/multi_hop_trace.py
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
tracer = trace.get_tracer(__name__)
def process_request(request):
"""Process request with distributed tracing"""
with tracer.start_as_current_span("process_request") as span:
# Add context
span.set_attribute("request_id", request.id)
span.set_attribute("user_id", request.user_id)
# Call downstream services
with tracer.start_as_current_span("call_database"):
result = call_database(request)
with tracer.start_as_current_span("call_ml_service"):
prediction = call_ml_service(result)
return prediction
Structured Logging Patterns¶
Structured Logging:
# logging/structured_logging.py
import structlog
logger = structlog.get_logger()
def process_data(data: dict):
"""Process data with structured logging"""
logger.info(
"processing_data",
data_id=data["id"],
data_type=data["type"],
timestamp=data["timestamp"]
)
try:
result = transform_data(data)
logger.info(
"data_processed",
data_id=data["id"],
result_size=len(result)
)
return result
except Exception as e:
logger.error(
"data_processing_failed",
data_id=data["id"],
error=str(e),
exc_info=True
)
raise
User-Facing Synthetic Monitors¶
Synthetic Monitoring:
# monitoring/synthetic_monitors.py
class SyntheticMonitor:
def monitor_api_endpoint(self, endpoint: str):
"""Monitor API endpoint with synthetic requests"""
response = requests.get(endpoint)
# Check response
assert response.status_code == 200
assert response.json()["status"] == "ok"
# Record metrics
self.record_metric("synthetic_api_latency", response.elapsed.total_seconds())
self.record_metric("synthetic_api_status", response.status_code)
def monitor_database_query(self, query: str):
"""Monitor database with synthetic queries"""
start = time.time()
result = self.execute_query(query)
duration = time.time() - start
# Check result
assert len(result) > 0
# Record metrics
self.record_metric("synthetic_db_latency", duration)
self.record_metric("synthetic_db_rows", len(result))
Test Playbooks & Chaos Engineering¶
Controlled Failure Injection¶
Failure Injection Framework:
# chaos/failure_injection.py
class FailureInjector:
def inject_cpu_stress(self, pod_name: str, duration: int):
"""Inject CPU stress"""
kubectl.exec(
pod_name,
"stress-ng",
"--cpu", "4",
"--timeout", str(duration)
)
def inject_memory_pressure(self, pod_name: str, size: str):
"""Inject memory pressure"""
kubectl.exec(
pod_name,
"stress-ng",
"--vm", "1",
"--vm-bytes", size,
"--timeout", "60"
)
def inject_network_delay(self, pod_name: str, delay: int):
"""Inject network delay"""
kubectl.exec(
pod_name,
"tc", "qdisc", "add", "dev", "eth0", "root", "netem", "delay", str(delay) + "ms"
)
def inject_packet_loss(self, pod_name: str, loss: float):
"""Inject packet loss"""
kubectl.exec(
pod_name,
"tc", "qdisc", "add", "dev", "eth0", "root", "netem", "loss", str(loss) + "%"
)
Canary Rollouts¶
Canary Deployment:
# canary/deployment.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: app-rollout
spec:
replicas: 10
strategy:
canary:
steps:
- setWeight: 10 # 10% traffic to canary
- pause: {}
- setWeight: 25 # 25% traffic to canary
- pause: {duration: 5m}
- setWeight: 50 # 50% traffic to canary
- pause: {duration: 5m}
- setWeight: 100 # 100% traffic to canary
canaryService: app-canary
stableService: app-stable
template:
spec:
containers:
- name: app
image: app:latest
Pod Kill Testing¶
Pod Kill Test:
# chaos/pod_kill_test.py
class PodKillTest:
def test_pod_restart(self, deployment: str):
"""Test pod restart recovery"""
# Get pod
pod = self.get_pod(deployment)
# Kill pod
kubectl.delete_pod(pod.name)
# Wait for restart
self.wait_for_pod_ready(deployment, timeout=5*60)
# Verify service
assert self.verify_service_health(deployment)
def test_all_pods_kill(self, deployment: str):
"""Test all pods kill recovery"""
# Kill all pods
kubectl.delete_pods(deployment, all=True)
# Wait for recovery
self.wait_for_deployment_ready(deployment, timeout=10*60)
# Verify service
assert self.verify_service_health(deployment)
Network Delay Injection¶
Network Delay Test:
# chaos/network_delay_test.py
class NetworkDelayTest:
def test_api_timeout(self, api_endpoint: str):
"""Test API behavior under network delay"""
# Inject delay
self.inject_network_delay("api-pod", delay=5000) # 5 seconds
# Make request
try:
response = requests.get(api_endpoint, timeout=10)
assert response.status_code == 200
except requests.Timeout:
# Expected behavior
pass
finally:
# Remove delay
self.remove_network_delay("api-pod")
Postgres Primary Failover Drills¶
Failover Drill:
#!/bin/bash
# chaos/postgres-failover-drill.sh
echo "=== Postgres Primary Failover Drill ==="
# 1. Verify current primary
PRIMARY=$(kubectl get pod -n postgres -l postgres-operator.crunchydata.com/role=master -o jsonpath='{.items[0].metadata.name}')
echo "Current primary: $PRIMARY"
# 2. Kill primary
echo "Killing primary pod..."
kubectl delete pod $PRIMARY -n postgres
# 3. Wait for failover
echo "Waiting for failover..."
sleep 30
# 4. Verify new primary
NEW_PRIMARY=$(kubectl get pod -n postgres -l postgres-operator.crunchydata.com/role=master -o jsonpath='{.items[0].metadata.name}')
echo "New primary: $NEW_PRIMARY"
# 5. Verify data integrity
echo "Verifying data integrity..."
kubectl exec -it $NEW_PRIMARY -n postgres -- psql -c "SELECT COUNT(*) FROM important_table;"
echo "=== Failover drill complete ==="
Replaying Message Queues¶
Queue Replay Test:
# chaos/queue_replay_test.py
class QueueReplayTest:
def test_redis_stream_replay(self, stream: str):
"""Test Redis stream replay"""
# Get messages
messages = self.get_stream_messages(stream, count=100)
# Replay messages
for message in messages:
self.replay_message(stream, message)
# Verify processing
assert self.verify_messages_processed(messages)
def test_kafka_replay(self, topic: str):
"""Test Kafka topic replay"""
# Get messages from beginning
consumer = KafkaConsumer(topic, auto_offset_reset='earliest')
# Replay messages
for message in consumer:
self.replay_message(topic, message)
Resilience Scoring¶
Resilience Score Calculation:
# chaos/resilience_scoring.py
class ResilienceScorer:
def calculate_score(self, test_results: dict) -> float:
"""Calculate resilience score"""
scores = {
'pod_restart': self.score_pod_restart(test_results['pod_restart']),
'failover': self.score_failover(test_results['failover']),
'network_partition': self.score_network_partition(test_results['network_partition']),
'load_test': self.score_load_test(test_results['load_test'])
}
# Weighted average
weights = {
'pod_restart': 0.2,
'failover': 0.3,
'network_partition': 0.3,
'load_test': 0.2
}
total_score = sum(scores[key] * weights[key] for key in scores)
return total_score
def score_pod_restart(self, result: dict) -> float:
"""Score pod restart recovery"""
if result['recovery_time'] < 60: # < 1 minute
return 1.0
elif result['recovery_time'] < 300: # < 5 minutes
return 0.8
else:
return 0.5
Sample Chaos Engineering Test Suite¶
Complete Test Suite:
# chaos/test_suite.py
import pytest
class ChaosTestSuite:
@pytest.mark.chaos
def test_pod_kill(self):
"""Test pod kill recovery"""
# Implementation
pass
@pytest.mark.chaos
def test_network_partition(self):
"""Test network partition recovery"""
# Implementation
pass
@pytest.mark.chaos
def test_database_failover(self):
"""Test database failover"""
# Implementation
pass
@pytest.mark.chaos
def test_load_spike(self):
"""Test load spike handling"""
# Implementation
pass
People, Communication, and Rotation Practices¶
Escalation Ladders¶
Escalation Levels: 1. L1 (On-Call): Initial response, follow runbooks 2. L2 (Senior Engineer): Complex issues, architecture decisions 3. L3 (Principal Engineer): Critical issues, system design 4. L4 (Engineering Manager): Business impact, resource allocation
Escalation Criteria: - L1 → L2: Issue unresolved after 30 minutes - L2 → L3: Issue unresolved after 2 hours - L3 → L4: Business impact > $10k/hour
Communication Templates¶
Incident Communication Template:
Subject: [SEVERITY] Incident: [Brief Description]
Status: [Investigating/Mitigating/Resolved]
Impact:
- Services affected: [List]
- Users affected: [Number/Percentage]
- Estimated resolution: [Time]
Actions taken:
- [Action 1]
- [Action 2]
Next update: [Time]
Postmortem Communication Template:
Subject: Postmortem: [Incident Title]
Summary:
[Brief summary]
Root Cause:
[Root cause explanation]
Impact:
[Impact details]
Resolution:
[Resolution steps]
Prevention:
[Preventive measures]
Action Items:
- [ ] [Action item 1]
- [ ] [Action item 2]
Handoff Protocols¶
Handoff Checklist: - [ ] Current incidents documented - [ ] Runbooks updated - [ ] Monitoring alerts reviewed - [ ] Known issues communicated - [ ] Escalation paths confirmed - [ ] Contact information verified
Incident Commander Roles¶
Incident Commander Responsibilities: - Coordinate response - Make decisions - Communicate status - Escalate when needed - Document actions
Incident Commander Rotation: - Rotate weekly - Include training - Provide context - Document decisions
Engineering vs Ops Responsibilities¶
Engineering Responsibilities: - System design - Feature development - Performance optimization - Architecture decisions
Ops Responsibilities: - Incident response - Monitoring setup - Runbook maintenance - On-call rotation
Shared Responsibilities: - System reliability - Performance monitoring - Capacity planning - Security
Avoiding Burnout¶
Burnout Prevention: - Limit on-call hours - Provide adequate coverage - Rotate responsibilities - Encourage time off - Recognize contributions
Cross-Training Across Subsystems¶
Cross-Training Plan: - Weekly knowledge sharing - Pair programming - Documentation reviews - Incident shadowing - Training sessions
Anti-Patterns & Failure Horror Stories¶
"Fix in Prod" Spirals¶
Problem: Quick fixes in production without proper testing.
Example: Hot-patching Postgres configuration without testing, causing cascading failures.
Prevention: - Enforce change management - Require testing before production - Use feature flags - Implement canary deployments
Missing Runbooks Leading to Multi-Hour Outages¶
Problem: No runbooks, engineers guessing during incidents.
Example: 4-hour outage because no one knew how to failover Postgres cluster.
Prevention: - Maintain up-to-date runbooks - Test runbooks regularly - Include runbooks in onboarding - Review runbooks after incidents
Time-Skewed Clusters Causing ML Inference Corruption¶
Problem: Clock drift between nodes causes timestamp mismatches.
Example: ML models trained on misaligned timestamps, producing incorrect predictions.
Prevention: - Enforce NTP synchronization - Monitor clock drift - Validate timestamps - Use logical clocks where appropriate
Postgres Failing Silently for Weeks¶
Problem: No monitoring, issues go undetected.
Example: Postgres replica lagging for weeks, no alerts.
Prevention: - Implement comprehensive monitoring - Set up alerts for all critical metrics - Regular health checks - Automated testing
Dead Letter Queues Never Drained¶
Problem: DLQ messages accumulate, never processed.
Example: 1 million messages in DLQ, system performance degraded.
Prevention: - Monitor DLQ depth - Set up alerts - Implement DLQ processing - Regular DLQ reviews
GPU Node Drift Breaking Inference Reproducibility¶
Problem: GPU nodes drift from expected configuration.
Example: CUDA version mismatch causes inference failures.
Prevention: - Enforce configuration management - Monitor node drift - Use immutable infrastructure - Regular configuration audits
Rancher Agents Stuck in Perpetual NotReady¶
Problem: Rancher agents fail to join cluster.
Example: Nodes stuck in NotReady state, unable to schedule pods.
Prevention: - Monitor node status - Set up alerts - Automate node recovery - Regular node health checks
Redis Stream Backpressure Avalanches¶
Problem: Consumer lag causes system overload.
Example: Redis stream consumer lag causes memory exhaustion.
Prevention: - Monitor consumer lag - Implement backpressure handling - Auto-scale consumers - Set up alerts
ETL Pipelines Silently Dropping Partitions¶
Problem: ETL pipelines fail silently, data missing.
Example: Partition processing fails, no alerts, data gaps.
Prevention: - Validate ETL outputs - Monitor partition processing - Set up data quality checks - Regular data audits
Agentic LLM Hooks¶
Generate Runbooks¶
LLM Runbook Generation:
# llm/runbook_generator.py
class LLMRunbookGenerator:
def generate_runbook(self, system: str, failure_mode: str) -> str:
"""Generate runbook using LLM"""
prompt = f"""
Generate a runbook for {system} failure mode: {failure_mode}
Include:
1. Symptom identification
2. Diagnostic steps
3. Resolution steps
4. Verification steps
5. Rollback procedures
"""
response = self.llm_client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "You are a runbook generation expert."},
{"role": "user", "content": prompt}
]
)
return response.choices[0].message.content
Review Logs During Incident Triage¶
LLM Log Analysis:
# llm/log_analyzer.py
class LLMLogAnalyzer:
def analyze_logs(self, logs: List[str]) -> dict:
"""Analyze logs during incident triage"""
prompt = f"""
Analyze these logs for incident triage:
{json.dumps(logs, indent=2)}
Identify:
1. Error patterns
2. Root cause indicators
3. Affected components
4. Recommended actions
"""
response = self.llm_client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "You are a log analysis expert."},
{"role": "user", "content": prompt}
]
)
return json.loads(response.choices[0].message.content)
Recommend RCA Hypotheses¶
LLM RCA Hypothesis Generation:
# llm/rca_hypothesis.py
class LLMRCAHypothesis:
def generate_hypotheses(self, incident_data: dict) -> List[str]:
"""Generate RCA hypotheses using LLM"""
prompt = f"""
Generate root cause analysis hypotheses for this incident:
{json.dumps(incident_data, indent=2)}
Provide:
1. Most likely root causes
2. Supporting evidence
3. Investigation steps
4. Confidence levels
"""
response = self.llm_client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "You are an RCA expert."},
{"role": "user", "content": prompt}
]
)
return json.loads(response.choices[0].message.content)
Generate Postmortems¶
LLM Postmortem Generation:
# llm/postmortem_generator.py
class LLMPostmortemGenerator:
def generate_postmortem(self, incident_data: dict) -> str:
"""Generate postmortem using LLM"""
prompt = f"""
Generate a postmortem for this incident:
{json.dumps(incident_data, indent=2)}
Include:
1. Summary
2. Timeline
3. Root cause
4. Impact
5. Resolution
6. Prevention measures
7. Action items
"""
response = self.llm_client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "You are a postmortem writing expert."},
{"role": "user", "content": prompt}
]
)
return response.choices[0].message.content
Propose Resilience Upgrades¶
LLM Resilience Proposal:
# llm/resilience_proposer.py
class LLMResilienceProposer:
def propose_upgrades(self, system_analysis: dict) -> List[dict]:
"""Propose resilience upgrades using LLM"""
prompt = f"""
Propose resilience upgrades for this system:
{json.dumps(system_analysis, indent=2)}
Provide:
1. Upgrade recommendations
2. Implementation steps
3. Expected impact
4. Priority levels
"""
response = self.llm_client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "You are a resilience engineering expert."},
{"role": "user", "content": prompt}
]
)
return json.loads(response.choices[0].message.content)
Monitor Drift from Runbook Expectations¶
LLM Runbook Drift Detection:
# llm/runbook_drift_detector.py
class LLMRunbookDriftDetector:
def detect_drift(self, actual_actions: List[str], runbook: str) -> dict:
"""Detect drift from runbook expectations"""
prompt = f"""
Compare actual incident response actions to runbook:
Actual actions:
{json.dumps(actual_actions, indent=2)}
Runbook:
{runbook}
Identify:
1. Deviations from runbook
2. Missing steps
3. Additional steps taken
4. Recommendations
"""
response = self.llm_client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "You are a runbook compliance expert."},
{"role": "user", "content": prompt}
]
)
return json.loads(response.choices[0].message.content)
Forecast Future Failure Modes¶
LLM Failure Mode Forecasting:
# llm/failure_forecaster.py
class LLMFailureForecaster:
def forecast_failures(self, system_state: dict) -> List[dict]:
"""Forecast future failure modes using LLM"""
prompt = f"""
Forecast potential failure modes for this system:
{json.dumps(system_state, indent=2)}
Provide:
1. Likely failure modes
2. Probability estimates
3. Impact assessments
4. Prevention recommendations
"""
response = self.llm_client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "You are a failure mode forecasting expert."},
{"role": "user", "content": prompt}
]
)
return json.loads(response.choices[0].message.content)
Analyze Failure Cascades in Diagrams¶
LLM Cascade Analysis:
# llm/cascade_analyzer.py
class LLMCascadeAnalyzer:
def analyze_cascade(self, system_diagram: str, failure_point: str) -> dict:
"""Analyze failure cascade using LLM"""
prompt = f"""
Analyze failure cascade for this system:
System diagram:
{system_diagram}
Failure point:
{failure_point}
Identify:
1. Cascade path
2. Affected components
3. Mitigation points
4. Recovery strategies
"""
response = self.llm_client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "You are a failure cascade analysis expert."},
{"role": "user", "content": prompt}
]
)
return json.loads(response.choices[0].message.content)
Suggest Tests to Close Reliability Gaps¶
LLM Test Suggestion:
# llm/test_suggester.py
class LLMTestSuggester:
def suggest_tests(self, reliability_gaps: List[str]) -> List[dict]:
"""Suggest tests to close reliability gaps"""
prompt = f"""
Suggest tests to close these reliability gaps:
{json.dumps(reliability_gaps, indent=2)}
Provide:
1. Test recommendations
2. Test implementation steps
3. Expected outcomes
4. Priority levels
"""
response = self.llm_client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "You are a test design expert."},
{"role": "user", "content": prompt}
]
)
return json.loads(response.choices[0].message.content)
Checklists¶
Pre-Incident Checklist¶
- Monitoring configured
- Alerts tested
- Runbooks updated
- On-call rotation scheduled
- Escalation paths defined
- Communication channels ready
- Backup procedures tested
- Recovery procedures documented
Incident Response Checklist¶
- Incident confirmed
- Severity assessed
- Incident commander assigned
- Communication sent
- Runbook consulted
- Containment attempted
- Remediation in progress
- Status updated regularly
Post-Incident Checklist¶
- Service restored
- Impact assessed
- Root cause identified
- Postmortem scheduled
- Action items created
- Runbooks updated
- Monitoring improved
- Prevention measures implemented
See Also¶
- System Resilience, Rate Limiting, Concurrency Control & Backpressure - Resilience patterns
- Configuration Management - Config governance
- Release Management - Deployment practices
This guide provides a complete framework for operational resilience. Start with runbooks, implement monitoring, practice incident response, and continuously improve. The goal is systems that survive incidents and recover gracefully.