Individuelle E-Mail-Alerts und Eskalationen: fortgeschrittenes Incident-Routing
Gestalte Eskalations-Workflows, die zur richtigen Zeit die richtige Person erreichen. Leitfaden zu Alert-Routing, On-Call-Integration und.
Das Eskalationsproblem#
Es ist 3 Uhr nachts. Deine Website geht down. Jemand muss sofort reagieren.
Ohne Eskalation:
- Alert geht in den On-Call-Slack-Kanal
- Niemand sieht es (alle schlafen, Slack-Benachrichtigungen aus)
- 45 Minuten später wecken Kundenbeschwerden jemanden
- MTTR: 45 Minuten
Mit smarter Eskalation:
- Alert geht an Slack (niedrige Priorität)
- Keine Bestätigung innerhalb von 2 Minuten → SMS an die primäre On-Call-Person
- Keine Reaktion innerhalb von 5 Minuten → Anruf an On-Call-Backup
- MTTR: 5 Minuten
Dieser Leitfaden zeigt dir, wie du intelligente Eskalations-Workflows aufbaust.
Incident-Severity verstehen#
Klassifiziere Incidents zuerst nach Severity:
Tier 1: Critical (sofort eskalieren)#
- Produktiv-Website down (umsatzrelevant)
- Payment-Gateway-Ausfall
- API liefert 5xx-Fehler
- Datenbank-Replikation down
Aktionen:
- Slack #critical-incidents (wird permanent überwacht)
- SMS an primäre On-Call-Person
- Anruf, falls keine SMS-Reaktion erfolgt
- Automatische Jira-Ticket-Erstellung
- Update auf der Statusseite
Tier 2: Warning (während der Geschäftszeiten eskalieren)#
- Verschlechterte Response-Zeiten
- Nicht-kritische Service-Fehler
- Probleme mit der E-Mail-Deliverability
- Langsame Datenbank-Queries
Aktionen:
- Slack #alerts (wird während der Geschäftszeiten geprüft)
- Jira-Ticket-Erstellung
- E-Mail-Digest am Tagesende
Tier 3: Info (nur loggen)#
- Domain läuft in 30 Tagen ab
- SSL läuft in 90 Tagen ab
- Wöchentlicher Trend-Report
- Nicht-kritischer Metrik-Schwellwert
Aktionen:
- Wöchentlicher E-Mail-Digest
- Dashboard-Benachrichtigung (kein Pager)
So baust du deine Eskalationsrichtlinie auf#
Schritt 1: On-Call-Rotationen definieren#
Lege eine Rotation fest, die zeigt, wer wann On-Call ist:
Montag-Freitag 9-17 Uhr: Alice (primary), Bob (backup)
Montag-Freitag 17-9 Uhr: Charlie (primary), Diana (backup)
Samstag-Sonntag 24 Std: Eve (primary), Frank (backup)
Feiertage: George (ganztägig On-Call)
Schritt 2: Eskalationszeiten festlegen#
T+0: Alert geht an Slack
T+2min: Keine Bestätigung → SMS an Primary
T+5min: Keine Reaktion → Anruf Primary
T+10min: Keine Reaktion → SMS an Backup
T+15min: Immer noch keine Reaktion → ganzes Team eskalieren
Schritt 3: Eskalationslogik umsetzen#
In Nova Uptime (falls unterstützt):
- Domain-Einstellungen → Alerting
- Severity setzen: Critical
- Eskalation konfigurieren:
- Schritt 1: Slack #critical-incidents
- Schritt 2 (2 Min): SMS an On-Call
- Schritt 3 (5 Min): Telefonanruf
- Schritt 4 (10 Min): gesamtes Team
Per Webhook + eigenem System:
async function handleCriticalIncident({ domain, detectedAt }) {
const oncall = await getOnCallEngineer(new Date());
// Step 1: Immediate Slack alert
const slackMessage = await postToSlack({
channel: '#critical-incidents',
text: `🚨 CRITICAL: ${domain} is down`,
blocks: [
{
type: 'section',
text: {
type: 'mrkdwn',
text: `@${oncall.slackHandle}: ${domain} is down. Acknowledge with reaction.`
}
}
]
});
// Step 2: Wait 2 minutes for acknowledgment
const acknowledged = await waitForAcknowledgment(slackMessage, 2 * 60 * 1000);
if (!acknowledged) {
// Step 2: Send SMS
await sendSMS({
to: oncall.phone,
message: `CRITICAL: ${domain} down. Reply OK to acknowledge.`
});
}
// Step 3: Wait 5 minutes total
const smsAcknowledged = await waitForSMS(oncall.phone, 5 * 60 * 1000);
if (!smsAcknowledged) {
// Step 3: Phone call
await makePhoneCall({
to: oncall.phone,
message: `Critical incident. Website ${domain} is down. Press 1 to acknowledge.`
});
}
// ... Continue escalation chain
}
Fortgeschritten: smartes Alert-Routing#
Pattern 1: Routing nach Tageszeit#
Unterschiedliche Personen sind zu unterschiedlichen Zeiten On-Call.
async function getOnCallEngineer(timestamp) {
const hour = new Date(timestamp).getHours();
const dayOfWeek = new Date(timestamp).getDay();
// Business hours (9 AM - 5 PM weekdays)
if (dayOfWeek >= 1 && dayOfWeek <= 5 && hour >= 9 && hour < 17) {
return {
name: 'Alice',
slackHandle: 'alice',
phone: '+1-555-0100',
email: 'alice@company.com'
};
}
// After hours (weekdays)
if (dayOfWeek >= 1 && dayOfWeek <= 5 && (hour < 9 || hour >= 17)) {
return {
name: 'Charlie',
slackHandle: 'charlie',
phone: '+1-555-0102',
email: 'charlie@company.com'
};
}
// Weekend
if (dayOfWeek === 0 || dayOfWeek === 6) {
return {
name: 'Eve',
slackHandle: 'eve',
phone: '+1-555-0104',
email: 'eve@company.com'
};
}
}
Pattern 2: Routing nach Domain#
Unterschiedliche Teams sind für unterschiedliche Domains zuständig.
async function getTeamForDomain(domain) {
// Engineering team owns api.*, backend.*
if (domain.startsWith('api.') || domain.startsWith('backend.')) {
return 'engineering';
}
// Infrastructure team owns server, monitoring, infra
if (domain.includes('server') || domain.includes('monitor')) {
return 'infrastructure';
}
// Support team owns customer-facing domains
if (domain.startsWith('support.') || domain.startsWith('customer.')) {
return 'support';
}
// Default: DevOps
return 'devops';
}
async function handleIncident({ domain, severity }) {
const team = await getTeamForDomain(domain);
const oncall = await getOnCallEngineer(team, new Date());
if (severity === 'critical') {
await escalate(oncall);
}
}
Pattern 3: Routing nach Incident-Typ#
Unterschiedliche Expertise für unterschiedliche Ausfälle.
async function getExpertForIncident(domain, incidentType) {
if (incidentType === 'database_down') {
// Page database expert
return await getOnCallExpert('database');
} else if (incidentType === 'api_errors') {
// Page API lead
return await getOnCallExpert('backend');
} else if (incidentType === 'email_delivery_failing') {
// Page email ops
return await getOnCallExpert('email');
} else if (incidentType === 'ssl_expired') {
// Page security
return await getOnCallExpert('security');
}
// Default: on-call engineer
return await getOnCallEngineer(new Date());
}
Pattern 4: Bedingte Eskalation#
Unterschiedliche Eskalationspfade je nach Eigenschaften des Incidents.
async function escalateIncident({ domain, severity, duration }) {
const oncall = await getOnCallEngineer(new Date());
if (severity === 'critical' && duration > 5 * 60 * 1000) {
// Critical for >5 minutes: Aggressive escalation
await Promise.all([
postSlack({ channel: '#critical-incidents', text: 'CRITICAL ESCALATION' }),
sendSMS(oncall.phone),
makePhoneCall(oncall.phone),
pageBackup(oncall.backup)
]);
} else if (severity === 'critical') {
// Critical but recent: Gentle escalation
await Promise.all([
postSlack({ channel: '#critical-incidents' }),
sendSMS(oncall.phone)
]);
} else if (severity === 'warning') {
// Just log
await postSlack({ channel: '#alerts' });
}
}
Integration mit PagerDuty#
Für ausgeklügeltes On-Call-Management bietet sich die Integration mit PagerDuty an:
const PagerDutyClient = require('pagerduty');
async function pageOnCallVia PagerDuty(domain, severity) {
const client = new PagerDutyClient({
token: process.env.PAGERDUTY_TOKEN
});
// Create incident
const incident = await client.incidents.create({
type: 'incident_reference',
incident: {
type: 'incident',
title: `${domain} is down`,
body: {
type: 'incident_body',
description: `Website ${domain} is down. Response: Down. Severity: ${severity}`
},
urgency: severity === 'critical' ? 'high' : 'low',
service: {
id: process.env.PAGERDUTY_SERVICE_ID,
type: 'service_reference'
}
}
});
console.log(`Created PagerDuty incident: ${incident.id}`);
}
Bestätigung und Übergabe#
Bestätigungs-Patterns#
Die On-Call-Person muss den Incident bestätigen:
// Via Slack reaction
async function waitForSlackAcknowledgment(messageId, maxWait) {
const startTime = Date.now();
while (Date.now() - startTime < maxWait) {
// Poll for reactions
const reactions = await getSlackMessageReactions(messageId);
if (reactions.includes('white_check_mark')) {
return true; // Acknowledged
}
await sleep(10 * 1000); // Check every 10 seconds
}
return false; // Not acknowledged within max wait
}
// Via SMS
async function waitForSmsAcknowledgment(phone, maxWait) {
const startTime = Date.now();
while (Date.now() - startTime < maxWait) {
// Poll SMS responses
const responses = await getSmsResponses(phone);
if (responses.some(m => m.text.toUpperCase().includes('OK'))) {
return true; // Acknowledged
}
await sleep(5 * 1000); // Check every 5 seconds
}
return false; // Not acknowledged
}
Übergabe zwischen Teams#
Wenn eine On-Call-Person an eine andere übergeben muss:
async function handoffIncident(incident, fromEngineer, toEngineer) {
// Update incident
incident.assignedTo = toEngineer;
incident.handoffAt = new Date();
await incident.save();
// Notify both
await sendMessage({
to: fromEngineer.slack,
text: `Handing off ${incident.domain} to ${toEngineer.name}`
});
await sendMessage({
to: toEngineer.slack,
text: `Taking over incident: ${incident.domain}. See: ${incident.dashboard}`
});
// Update status page
await updateStatusPage({
message: `Working with ${toEngineer.name}'s team on investigation`
});
}
Wirksamkeit der Eskalation messen#
Tracke Eskalations-Metriken:
async function analyzeEscalationMetrics() {
const incidents = await Incident.find({
createdAfter: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) // Last 30 days
});
const metrics = {
totalIncidents: incidents.length,
avgTimeToAcknowledgment: calculateAvg(
incidents.map(i => i.acknowledgedAt - i.alertedAt)
),
avgTimeToEscalation: calculateAvg(
incidents.map(i => i.escalatedAt - i.alertedAt)
),
escalationRate: incidents.filter(i => i.escalatedAt).length / incidents.length,
avgMTTR: calculateAvg(
incidents.map(i => i.resolvedAt - i.alertedAt)
)
};
console.log('Escalation Metrics (Last 30 days):');
console.log(`Total Incidents: ${metrics.totalIncidents}`);
console.log(`Avg Time to Acknowledgment: ${metrics.avgTimeToAcknowledgment / 60}m`);
console.log(`Escalation Rate: ${(metrics.escalationRate * 100).toFixed(1)}%`);
console.log(`Avg MTTR: ${metrics.avgMTTR / 60}m`);
}
Häufige Eskalationsfehler#
Fehler 1: Alert-Müdigkeit führt zum Ignorieren#
Problem: Zu viele Alerts → das Team reagiert nicht mehr → echte Probleme werden übersehen
Lösung: Setze strikte Schwellwerte. Eskaliere nur bei wirklich kritischen Themen.
Fehler 2: Zu aggressiv eskalieren#
Problem: Bei jedem Incident wird das ganze Team eskaliert → Burnout → Leute kündigen
Lösung: Eskaliere schrittweise. Gib der primären Person 5 Minuten, bevor du das Backup eskalierst.
Fehler 3: Zu langsam eskalieren#
Problem: Ein kritischer Incident bleibt 30 Minuten unbemerkt → massiver Schaden
Lösung: Bei kritischen Incidents innerhalb von 2-5 Minuten eskalieren.
Fehler 4: Kein Übergabe-Prozess#
Problem: Die primäre On-Call-Person wusste nichts von der Übergabe → Chaos
Lösung: Übergaben explizit per Slack/E-Mail kommunizieren.
Zusammenfassung: Checkliste zum Eskalations-Setup#
- ✅ Severity-Stufen für Incidents definieren (Critical/Warning/Info)
- ✅ On-Call-Rotationsplan erstellen
- ✅ Eskalationszeiten festlegen (2 Min → 5 Min → 10 Min → alle)
- ✅ Eskalationskanäle einrichten (Slack → SMS → Telefon → gesamtes Team)
- ✅ Routing nach Tageszeit konfigurieren
- ✅ Routing nach Domain bzw. Team-Verantwortung
- ✅ Routing nach Incident-Typ (Datenbank vs. API vs. E-Mail)
- ✅ PagerDuty integrieren (falls relevant)
- ✅ Bestätigungsmechanismen einrichten (Slack-Reaktion, SMS-Antwort)
- ✅ Übergabe-Prozesse definieren
- ✅ Eskalations-Metriken tracken
- ✅ Monatliches Review der Eskalations-Wirksamkeit
Heute starten#
Fang einfach an: nur Slack + SMS. Erweitere die Komplexität (PagerDuty, bedingtes Routing), wenn dein Incident-Volumen wächst.
Dokumentiere deine Eskalationsrichtlinie im Team-Wiki. Teile sie mit allen Team-Mitgliedern. Teste sie quartalsweise, um sicherzustellen, dass alles noch funktioniert.
Deine Eskalationsrichtlinie ist der Unterschied zwischen "Incident in 5 Minuten gelöst" und "Ausfall dauerte 3 Stunden". Investiere darin, das richtig hinzubekommen.
Monitor Your Website Before It Goes Down
Get uptime monitoring, SSL tracking, domain expiry alerts, and email health checks. Free plan — no credit card required.
Start Monitoring FreeVerwandte Artikel
Webhooks und Integrationen für Uptime-Monitoring: Eigene Workflows bauen
Verbinde Uptime-Monitoring per Webhooks mit deinen Systemen. Kompletter Guide zu Incident-Automatisierung, Custom-Benachrichtigungen und Workflow-Integration.
Fallstudie: Wie Uptime-Monitoring 500.000 $ an entgangenem Umsatz rettete
Praxisbeispiel, wie proaktives Uptime-Monitoring katastrophale Geschäftsauswirkungen verhindert hat. Lerne aus der Incident-Response-Story eines.
Uptime-Monitoring mit Slack integrieren: Anleitung für Echtzeit-Alerts
Richte in 10 Minuten Slack-Alerts für Website-Downtime ein. Leite Incidents nach #alerts und reduziere die Reaktionszeit von 30 Minuten auf 60 Sekunden.