Nova Uptime
Guidesincident-responseescalationon-call

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.

SN
Sumit Nova Uptime
28. Februar 2026 · 8 min read
Share:

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):

  1. Domain-Einstellungen → Alerting
  2. Severity setzen: Critical
  3. 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 Free

Verwandte Artikel