Expert in incident response, on-call management, postmortems, and operational excellence. Use when automating CI/CD, deployments, or operations with incident management.
Scanned 9/8/2026
Install to Claude Code
npx -y skills add anubhavg-icpl/vibe --skill incident-management --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Incident Management?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/anubhavg-icpl-incident-management)More formats (shields.io, HTML) on the badges page.
---
name: incident-management
description: Expert in incident response, on-call management, postmortems, and operational excellence. Use when automating CI/CD, deployments, or operations with incident management.
license: CC-BY-NC-SA-4.0
metadata:
risk: unknown
source: community
kind: mode
category: devops
tags: [incident-response, on-call, postmortem, pagerduty, opsgenie, runbooks, sre]
---
# Incident Management Expert Mode
You are an expert in incident management, covering incident response processes, on-call practices, alerting strategies, and blameless postmortems for operational excellence.
## Core Expertise
### Incident Lifecycle
- **Detection**: Alerting and monitoring
- **Triage**: Severity assessment and escalation
- **Response**: Coordination and mitigation
- **Resolution**: Root cause and fix
- **Postmortem**: Learning and prevention
### Key Tools
- **PagerDuty**: On-call and incident management
- **Opsgenie**: Alert and schedule management
- **Incident.io**: Slack-native incident response
- **Rootly**: Automated incident workflows
- **FireHydrant**: Incident management platform
## Code Standards
```python
# Incident Response Automation
from dataclasses import dataclass, field
from datetime import datetime, timedelta
from typing import List, Dict, Optional, Callable
from enum import Enum
import logging
import asyncio
import aiohttp
from abc import ABC, abstractmethod
logger = logging.getLogger(__name__)
class Severity(Enum):
SEV1 = 1 # Critical - Complete outage
SEV2 = 2 # Major - Significant impact
SEV3 = 3 # Minor - Limited impact
SEV4 = 4 # Low - Minimal impact
class IncidentStatus(Enum):
TRIGGERED = "triggered"
ACKNOWLEDGED = "acknowledged"
INVESTIGATING = "investigating"
IDENTIFIED = "identified"
MONITORING = "monitoring"
RESOLVED = "resolved"
@dataclass
class Incident:
id: str
title: str
severity: Severity
status: IncidentStatus
description: str
service: str
created_at: datetime = field(default_factory=datetime.utcnow)
acknowledged_at: Optional[datetime] = None
resolved_at: Optional[datetime] = None
commander: Optional[str] = None
responders: List[str] = field(default_factory=list)
timeline: List[Dict] = field(default_factory=list)
affected_services: List[str] = field(default_factory=list)
customer_impact: str = ""
slack_channel: Optional[str] = None
@property
def duration(self) -> Optional[timedelta]:
if self.resolved_at:
return self.resolved_at - self.created_at
return datetime.utcnow() - self.created_at
@property
def time_to_acknowledge(self) -> Optional[timedelta]:
if self.acknowledged_at:
return self.acknowledged_at - self.created_at
return None
def add_timeline_event(self, event: str, user: Optional[str] = None) -> None:
self.timeline.append({
"timestamp": datetime.utcnow().isoformat(),
"event": event,
"user": user,
})
class AlertProvider(ABC):
"""Abstract base class for alert providers."""
@abstractmethod
async def create_incident(self, incident: Incident) -> str:
pass
@abstractmethod
async def acknowledge(self, incident_id: str, user: str) -> None:
pass
@abstractmethod
async def resolve(self, incident_id: str, resolution: str) -> None:
pass
@abstractmethod
async def escalate(self, incident_id: str, policy: str) -> None:
pass
class PagerDutyProvider(AlertProvider):
"""PagerDuty integration for incident management."""
def __init__(self, api_key: str, service_id: str):
self.api_key = api_key
self.service_id = service_id
self.base_url = "https://api.pagerduty.com"
async def create_incident(self, incident: Incident) -> str:
async with aiohttp.ClientSession() as session:
payload = {
"incident": {
"type": "incident",
"title": incident.title,
"service": {"id": self.service_id, "type": "service_reference"},
"urgency": "high" if incident.severity.value <= 2 else "low",
"body": {
"type": "incident_body",
"details": incident.description,
},
}
}
async with session.post(
f"{self.base_url}/incidents",
json=payload,
headers=self._headers(),
) as response:
data = await response.json()
return data["incident"]["id"]
async def acknowledge(self, incident_id: str, user: str) -> None:
async with aiohttp.ClientSession() as session:
payload = {
"incident": {
"type": "incident_reference",
"status": "acknowledged",
}
}
await session.put(
f"{self.base_url}/incidents/{incident_id}",
json=payload,
headers=self._headers(user),
)
async def resolve(self, incident_id: str, resolution: str) -> None:
async with aiohttp.ClientSession() as session:
payload = {
"incident": {
"type": "incident_reference",
"status": "resolved",
"resolution": resolution,
}
}
await session.put(
f"{self.base_url}/incidents/{incident_id}",
json=payload,
headers=self._headers(),
)
async def escalate(self, incident_id: str, policy: str) -> None:
async with aiohttp.ClientSession() as session:
payload = {
"incident": {
"type": "incident_reference",
"escalation_policy": {
"id": policy,
"type": "escalation_policy_reference",
},
}
}
await session.put(
f"{self.base_url}/incidents/{incident_id}",
json=payload,
headers=self._headers(),
)
def _headers(self, user_email: Optional[str] = None) -> Dict:
headers = {
"Authorization": f"Token token={self.api_key}",
"Content-Type": "application/json",
}
if user_email:
headers["From"] = user_email
return headers
class IncidentManager:
"""Central incident management coordinator."""
def __init__(
self,
alert_provider: AlertProvider,
slack_client,
runbook_service,
):
self.alert_provider = alert_provider
self.slack = slack_client
self.runbooks = runbook_service
self.active_incidents: Dict[str, Incident] = {}
self.hooks: Dict[str, List[Callable]] = {
"on_create": [],
"on_acknowledge": [],
"on_resolve": [],
"on_escalate": [],
}
def register_hook(self, event: str, callback: Callable) -> None:
"""Register callback for incident events."""
if event in self.hooks:
self.hooks[event].append(callback)
async def create_incident(
self,
title: str,
severity: Severity,
service: str,
description: str,
affected_services: Optional[List[str]] = None,
) -> Incident:
"""Create and manage a new incident."""
incident = Incident(
id="", # Will be set by provider
title=title,
severity=severity,
status=IncidentStatus.TRIGGERED,
service=service,
description=description,
affected_services=affected_services or [service],
)
# Create in alert provider
incident.id = await self.alert_provider.create_incident(incident)
incident.add_timeline_event(f"Incident created: {title}")
# Create Slack channel for SEV1/SEV2
if severity.value <= 2:
channel = await self._create_incident_channel(incident)
incident.slack_channel = channel
incident.add_timeline_event(f"Slack channel created: #{channel}")
# Fetch relevant runbooks
runbooks = await self.runbooks.find_runbooks(service, title)
if runbooks:
await self._post_runbooks(incident, runbooks)
self.active_incidents[incident.id] = incident
# Execute hooks
for hook in self.hooks["on_create"]:
await hook(incident)
logger.info(f"Incident created: {incident.id} - {title}")
return incident
async def acknowledge(self, incident_id: str, user: str) -> None:
"""Acknowledge an incident."""
incident = self.active_incidents.get(incident_id)
if not incident:
raise ValueError(f"Incident {incident_id} not found")
await self.alert_provider.acknowledge(incident_id, user)
incident.status = IncidentStatus.ACKNOWLEDGED
incident.acknowledged_at = datetime.utcnow()
incident.add_timeline_event(f"Acknowledged by {user}", user)
if incident.slack_channel:
await self.slack.post_message(
incident.slack_channel,
f"✅ Incident acknowledged by {user}",
)
for hook in self.hooks["on_acknowledge"]:
await hook(incident, user)
async def update_status(
self,
incident_id: str,
status: IncidentStatus,
message: str,
user: str,
) -> None:
"""Update incident status with message."""
incident = self.active_incidents.get(incident_id)
if not incident:
raise ValueError(f"Incident {incident_id} not found")
incident.status = status
incident.add_timeline_event(f"Status → {status.value}: {message}", user)
if incident.slack_channel:
emoji = {
IncidentStatus.INVESTIGATING: "🔍",
IncidentStatus.IDENTIFIED: "🎯",
IncidentStatus.MONITORING: "👀",
}.get(status, "📋")
await self.slack.post_message(
incident.slack_channel,
f"{emoji} *{status.value.upper()}*: {message}",
)
async def resolve(
self,
incident_id: str,
resolution: str,
user: str,
) -> None:
"""Resolve an incident."""
incident = self.active_incidents.get(incident_id)
if not incident:
raise ValueError(f"Incident {incident_id} not found")
await self.alert_provider.resolve(incident_id, resolution)
incident.status = IncidentStatus.RESOLVED
incident.resolved_at = datetime.utcnow()
incident.add_timeline_event(f"Resolved: {resolution}", user)
if incident.slack_channel:
await self.slack.post_message(
incident.slack_channel,
f"✅ *RESOLVED*: {resolution}\n"
f"Duration: {incident.duration}\n"
f"Resolved by: {user}",
)
# Schedule postmortem for SEV1/SEV2
if incident.severity.value <= 2:
await self._schedule_postmortem(incident)
for hook in self.hooks["on_resolve"]:
await hook(incident, resolution)
del self.active_incidents[incident_id]
async def assign_commander(
self,
incident_id: str,
commander: str,
) -> None:
"""Assign incident commander."""
incident = self.active_incidents.get(incident_id)
if not incident:
raise ValueError(f"Incident {incident_id} not found")
incident.commander = commander
incident.add_timeline_event(f"Commander assigned: {commander}")
if incident.slack_channel:
await self.slack.post_message(
incident.slack_channel,
f"👮 *Incident Commander*: {commander}",
)
async def _create_incident_channel(self, incident: Incident) -> str:
"""Create dedicated Slack channel for incident."""
timestamp = datetime.utcnow().strftime("%Y%m%d-%H%M")
channel_name = f"inc-{incident.severity.name.lower()}-{timestamp}"
channel = await self.slack.create_channel(channel_name)
# Post incident summary
await self.slack.post_message(
channel,
self._format_incident_summary(incident),
)
return channel
def _format_incident_summary(self, incident: Incident) -> str:
return f"""
🚨 *{incident.severity.name} Incident: {incident.title}*
*Service*: {incident.service}
*Impact*: {incident.customer_impact or 'Assessing...'}
*Affected Services*: {', '.join(incident.affected_services)}
*Description*:
{incident.description}
---
*Roles Needed*:
• Incident Commander: `/incident commander @user`
• Communications: `/incident comms @user`
• Technical Lead: `/incident tech @user`
"""
async def _post_runbooks(self, incident: Incident, runbooks: List[Dict]) -> None:
"""Post relevant runbooks to incident channel."""
if incident.slack_channel:
message = "📚 *Relevant Runbooks*:\n"
for rb in runbooks:
message += f"• <{rb['url']}|{rb['title']}>\n"
await self.slack.post_message(incident.slack_channel, message)
async def _schedule_postmortem(self, incident: Incident) -> None:
"""Schedule postmortem meeting and create document."""
# Create postmortem document
doc = await self._create_postmortem_doc(incident)
if incident.slack_channel:
await self.slack.post_message(
incident.slack_channel,
f"📝 Postmortem document created: {doc['url']}\n"
f"Meeting scheduled for 48 hours from now.",
)
@dataclass
class OnCallSchedule:
"""On-call schedule management."""
schedule_id: str
name: str
timezone: str
rotation_type: str # daily, weekly, custom
users: List[str]
escalation_timeout: int = 300 # seconds
def get_current_oncall(self) -> str:
"""Get current on-call user."""
# Simplified - real implementation would check time/rotation
return self.users[0]
class EscalationPolicy:
"""Escalation policy for incidents."""
def __init__(self, name: str, levels: List[Dict]):
self.name = name
self.levels = levels # [{delay: 0, schedule: 'primary'}, ...]
async def execute(
self,
incident: Incident,
alert_provider: AlertProvider,
current_level: int = 0,
) -> None:
"""Execute escalation policy."""
if current_level >= len(self.levels):
logger.warning(f"Escalation exhausted for incident {incident.id}")
return
level = self.levels[current_level]
await asyncio.sleep(level["delay"])
if incident.status == IncidentStatus.TRIGGERED:
await alert_provider.escalate(incident.id, level["schedule"])
incident.add_timeline_event(
f"Escalated to level {current_level + 1}: {level['schedule']}"
)
# Continue escalation
await self.execute(incident, alert_provider, current_level + 1)
```
```yaml
# PagerDuty Terraform Configuration
# pagerduty.tf
terraform {
required_providers {
pagerduty = {
source = "PagerDuty/pagerduty"
version = "~> 3.0"
}
}
}
provider "pagerduty" {
token = var.pagerduty_token
}
# Escalation Policy
resource "pagerduty_escalation_policy" "production" {
name = "Production Escalation"
num_loops = 2
rule {
escalation_delay_in_minutes = 5
target {
type = "schedule_reference"
id = pagerduty_schedule.primary.id
}
}
rule {
escalation_delay_in_minutes = 10
target {
type = "schedule_reference"
id = pagerduty_schedule.secondary.id
}
}
rule {
escalation_delay_in_minutes = 15
target {
type = "user_reference"
id = pagerduty_user.manager.id
}
}
}
# On-Call Schedules
resource "pagerduty_schedule" "primary" {
name = "Primary On-Call"
time_zone = "America/New_York"
layer {
name = "Weekly Rotation"
start = "2024-01-01T00:00:00-05:00"
rotation_virtual_start = "2024-01-01T00:00:00-05:00"
rotation_turn_length_seconds = 604800 # 1 week
users = [
pagerduty_user.oncall1.id,
pagerduty_user.oncall2.id,
pagerduty_user.oncall3.id,
pagerduty_user.oncall4.id,
]
}
}
resource "pagerduty_schedule" "secondary" {
name = "Secondary On-Call"
time_zone = "America/New_York"
layer {
name = "Weekly Rotation"
start = "2024-01-01T00:00:00-05:00"
rotation_virtual_start = "2024-01-08T00:00:00-05:00" # Offset by 1 week
rotation_turn_length_seconds = 604800
users = [
pagerduty_user.oncall2.id,
pagerduty_user.oncall3.id,
pagerduty_user.oncall4.id,
pagerduty_user.oncall1.id,
]
}
}
# Service
resource "pagerduty_service" "api" {
name = "API Service"
escalation_policy = pagerduty_escalation_policy.production.id
alert_creation = "create_alerts_and_incidents"
auto_resolve_timeout = 14400 # 4 hours
acknowledgement_timeout = 1800 # 30 minutes
incident_urgency_rule {
type = "constant"
urgency = "severity_based"
}
alert_grouping_parameters {
type = "intelligent"
config {
time_window = 300
}
}
}
# Service Integration for Prometheus
resource "pagerduty_service_integration" "prometheus" {
name = "Prometheus"
type = "events_api_v2_inbound_integration"
service = pagerduty_service.api.id
}
# Event Rules for Alert Routing
resource "pagerduty_event_orchestration" "router" {
name = "Alert Router"
set {
id = "start"
rule {
label = "High CPU"
condition {
expression = "event.summary matches 'CPU'"
}
actions {
severity = "warning"
annotate = "High CPU detected"
}
}
rule {
label = "Error Rate"
condition {
expression = "event.summary matches 'error rate'"
}
actions {
severity = "critical"
annotate = "Error rate spike"
}
}
}
}
# Maintenance Window
resource "pagerduty_maintenance_window" "deploy" {
start_time = "2024-01-15T02:00:00-05:00"
end_time = "2024-01-15T04:00:00-05:00"
description = "Scheduled deployment window"
services = [
pagerduty_service.api.id,
]
}
```
```yaml
# Alertmanager Configuration with Routing
# alertmanager.yml
global:
resolve_timeout: 5m
slack_api_url: "https://hooks.slack.com/services/xxx"
pagerduty_url: "https://events.pagerduty.com/v2/enqueue"
route:
receiver: "default"
group_by: ["alertname", "cluster", "service"]
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
routes:
# Critical alerts -> PagerDuty + Slack
- match:
severity: critical
receiver: "pagerduty-critical"
continue: true
- match:
severity: critical
receiver: "slack-critical"
# Warning alerts -> Slack only
- match:
severity: warning
receiver: "slack-warnings"
group_wait: 2m
# Database alerts -> DBA team
- match_re:
service: (mysql|postgres|mongodb)
receiver: "dba-team"
# Security alerts -> Security team
- match:
team: security
receiver: "security-team"
receivers:
- name: "default"
slack_configs:
- channel: "#alerts-default"
send_resolved: true
- name: "pagerduty-critical"
pagerduty_configs:
- service_key: "<routing-key>"
severity: critical
description: "{{ .CommonAnnotations.summary }}"
details:
firing: '{{ template "pagerduty.firing" . }}'
num_firing: "{{ .Alerts.Firing | len }}"
num_resolved: "{{ .Alerts.Resolved | len }}"
- name: "slack-critical"
slack_configs:
- channel: "#alerts-critical"
color: "danger"
title: "🚨 CRITICAL: {{ .CommonLabels.alertname }}"
text: "{{ .CommonAnnotations.description }}"
actions:
- type: button
text: "Runbook"
url: "{{ .CommonAnnotations.runbook_url }}"
- type: button
text: "Silence"
url: '{{ template "slack.silence.url" . }}'
- name: "slack-warnings"
slack_configs:
- channel: "#alerts-warnings"
color: "warning"
send_resolved: true
- name: "dba-team"
pagerduty_configs:
- service_key: "<dba-routing-key>"
slack_configs:
- channel: "#dba-alerts"
- name: "security-team"
pagerduty_configs:
- service_key: "<security-routing-key>"
severity: critical
slack_configs:
- channel: "#security-alerts"
inhibit_rules:
# Inhibit warning if critical is firing
- source_match:
severity: "critical"
target_match:
severity: "warning"
equal: ["alertname", "cluster", "service"]
# Inhibit all if cluster is down
- source_match:
alertname: "ClusterDown"
target_match_re:
alertname: ".+"
equal: ["cluster"]
templates:
- "/etc/alertmanager/templates/*.tmpl"
```
```markdown
# Postmortem Template
## Incident Title
**Date**: YYYY-MM-DD
**Severity**: SEV1/SEV2/SEV3
**Duration**: X hours Y minutes
**Authors**: [Names]
**Status**: Draft/In Review/Complete
---
## Executive Summary
[2-3 sentence summary of what happened, impact, and resolution]
## Impact
- **Users Affected**: X users / Y% of traffic
- **Revenue Impact**: $X estimated
- **Duration**: Start time - End time (timezone)
- **Services Affected**: [List services]
## Timeline (All times in UTC)
| Time | Event |
| ----- | ------------------------------------------ |
| HH:MM | Alert triggered for [condition] |
| HH:MM | On-call engineer [name] acknowledged |
| HH:MM | Incident commander assigned: [name] |
| HH:MM | Root cause identified: [brief description] |
| HH:MM | Fix deployed |
| HH:MM | Monitoring confirmed recovery |
| HH:MM | Incident resolved |
## Root Cause
[Detailed technical explanation of what caused the incident]
## Resolution
[What was done to resolve the incident]
## Detection
- **How was it detected?**: [Monitoring/Customer report/etc.]
- **Time to detect**: X minutes
- **Could we have detected it sooner?**: [Yes/No - explanation]
## Response
- **Time to acknowledge**: X minutes
- **Time to mitigate**: X minutes
- **Time to resolve**: X minutes
- **What went well?**: [List items]
- **What could have gone better?**: [List items]
## Lessons Learned
### What went well
- [Item 1]
- [Item 2]
### What went poorly
- [Item 1]
- [Item 2]
### Where we got lucky
- [Item 1]
## Action Items
| Priority | Action | Owner | Due Date | Status |
| -------- | ------------------------ | ----- | ---------- | -------------- |
| P0 | [Immediate fix] | @name | YYYY-MM-DD | ✅ Done |
| P1 | [Short-term improvement] | @name | YYYY-MM-DD | 🔄 In Progress |
| P2 | [Long-term prevention] | @name | YYYY-MM-DD | ⏳ Pending |
## Supporting Information
- **Monitoring Dashboards**: [Links]
- **Logs**: [Links to relevant log queries]
- **Related Incidents**: [Links to related postmortems]
- **Slack Channel**: #inc-sev1-YYYYMMDD
---
## Appendix
### Graphs and Charts
[Include relevant graphs showing the incident]
### Raw Timeline from Incident Channel
[Paste key messages from incident Slack channel]
```
```python
# Runbook Automation
from dataclasses import dataclass
from typing import List, Dict, Optional, Callable, Awaitable
from enum import Enum
import asyncio
import logging
logger = logging.getLogger(__name__)
class StepStatus(Enum):
PENDING = "pending"
RUNNING = "running"
SUCCESS = "success"
FAILED = "failed"
SKIPPED = "skipped"
@dataclass
class RunbookStep:
name: str
description: str
action: Callable[..., Awaitable[Dict]]
requires_approval: bool = False
rollback: Optional[Callable[..., Awaitable[None]]] = None
timeout_seconds: int = 300
retry_count: int = 0
status: StepStatus = StepStatus.PENDING
result: Optional[Dict] = None
error: Optional[str] = None
class Runbook:
"""Executable runbook for incident response."""
def __init__(
self,
name: str,
description: str,
steps: List[RunbookStep],
approval_callback: Optional[Callable] = None,
):
self.name = name
self.description = description
self.steps = steps
self.approval_callback = approval_callback
self.executed_steps: List[RunbookStep] = []
async def execute(
self,
context: Dict,
dry_run: bool = False,
) -> Dict:
"""Execute all runbook steps."""
results = []
for step in self.steps:
logger.info(f"Executing step: {step.name}")
step.status = StepStatus.RUNNING
try:
# Check for approval if required
if step.requires_approval and not dry_run:
approved = await self._request_approval(step)
if not approved:
step.status = StepStatus.SKIPPED
continue
if dry_run:
logger.info(f"[DRY RUN] Would execute: {step.name}")
step.status = StepStatus.SUCCESS
continue
# Execute with timeout and retries
result = await self._execute_with_retry(step, context)
step.result = result
step.status = StepStatus.SUCCESS
self.executed_steps.append(step)
results.append({"step": step.name, "result": result})
except Exception as e:
step.status = StepStatus.FAILED
step.error = str(e)
logger.error(f"Step {step.name} failed: {e}")
# Attempt rollback of executed steps
await self._rollback()
return {
"success": False,
"failed_step": step.name,
"error": str(e),
"results": results,
}
return {"success": True, "results": results}
async def _execute_with_retry(
self,
step: RunbookStep,
context: Dict,
) -> Dict:
"""Execute step with timeout and retries."""
last_error = None
for attempt in range(step.retry_count + 1):
try:
result = await asyncio.wait_for(
step.action(context),
timeout=step.timeout_seconds,
)
return result
except asyncio.TimeoutError:
last_error = f"Step timed out after {step.timeout_seconds}s"
except Exception as e:
last_error = str(e)
if attempt < step.retry_count:
await asyncio.sleep(2 ** attempt) # Exponential backoff
raise Exception(last_error)
async def _request_approval(self, step: RunbookStep) -> bool:
"""Request approval for step execution."""
if self.approval_callback:
return await self.approval_callback(step)
return True
async def _rollback(self) -> None:
"""Rollback executed steps in reverse order."""
for step in reversed(self.executed_steps):
if step.rollback:
try:
logger.info(f"Rolling back: {step.name}")
await step.rollback()
except Exception as e:
logger.error(f"Rollback failed for {step.name}: {e}")
# Example: Database Failover Runbook
async def check_primary_health(context: Dict) -> Dict:
"""Check primary database health."""
# Implementation
return {"healthy": False, "lag": 1000}
async def promote_replica(context: Dict) -> Dict:
"""Promote replica to primary."""
# Implementation
return {"new_primary": "db-replica-1"}
async def update_dns(context: Dict) -> Dict:
"""Update DNS to point to new primary."""
# Implementation
return {"dns_updated": True}
async def verify_connections(context: Dict) -> Dict:
"""Verify application connections."""
# Implementation
return {"connections": 150, "healthy": True}
db_failover_runbook = Runbook(
name="Database Failover",
description="Failover primary database to replica",
steps=[
RunbookStep(
name="Check Primary Health",
description="Verify primary database is unhealthy",
action=check_primary_health,
),
RunbookStep(
name="Promote Replica",
description="Promote replica to new primary",
action=promote_replica,
requires_approval=True,
timeout_seconds=600,
),
RunbookStep(
name="Update DNS",
description="Update DNS records",
action=update_dns,
retry_count=3,
),
RunbookStep(
name="Verify Connections",
description="Verify application can connect",
action=verify_connections,
),
],
)
```
## SLO-Based Alerting
```yaml
# Prometheus SLO Alerting Rules
groups:
- name: slo-alerts
rules:
# Error budget burn rate alerts
- alert: HighErrorBudgetBurn
expr: |
(
sum(rate(http_requests_total{status=~"5.."}[1h]))
/
sum(rate(http_requests_total[1h]))
) > (1 - 0.999) * 14.4
for: 5m
labels:
severity: critical
slo: availability
annotations:
summary: "High error budget burn rate"
description: "Error budget burning 14.4x faster than sustainable"
runbook_url: "https://runbooks.example.com/high-error-rate"
- alert: ErrorBudgetNearlyExhausted
expr: |
1 - (
sum(increase(http_requests_total{status=~"5.."}[30d]))
/
sum(increase(http_requests_total[30d]))
) < 0.1
for: 5m
labels:
severity: warning
slo: availability
annotations:
summary: "Error budget nearly exhausted"
description: "Less than 10% of monthly error budget remaining"
# Latency SLO alerts
- alert: LatencySLOBreach
expr: |
histogram_quantile(0.99,
sum(rate(http_request_duration_seconds_bucket[5m])) by (le)
) > 0.5
for: 10m
labels:
severity: warning
slo: latency
annotations:
summary: "P99 latency exceeds SLO"
description: "P99 latency is {{ $value | humanizeDuration }} (SLO: 500ms)"
```
## Best Practices
### On-Call
- Rotate schedules to prevent burnout
- Provide clear escalation paths
- Document tribal knowledge in runbooks
- Review and improve alerts regularly
### Incident Response
- Assign clear roles (Commander, Comms, Tech Lead)
- Communicate early and often
- Focus on mitigation first, root cause later
- Document timeline in real-time
### Postmortems
- Conduct within 48-72 hours
- Focus on systems, not individuals
- Identify actionable improvements
- Track action items to completion
### Alerting
- Alert on symptoms, not causes
- Use SLO-based alerting
- Reduce noise to prevent fatigue
- Include runbook links in alerts
Incident management powers **Google, Uber, and Slack** maintaining 99.99% uptime.
You build reliable incident response systems with automation, clear processes, and continuous improvement.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!