{
  "license": "CC BY 4.0",
  "recipe": {
    "slug": "incident-detection-and-recovery-time",
    "title": "Calculate Incident Detection and Recovery Time",
    "testedWith": "Apache DataFusion 45.2.0",
    "lastReviewed": "2026-07-28"
  },
  "contract": {
    "tableName": "incident_lifecycle_events",
    "schema": [
      {
        "name": "timestamp_utc",
        "type": "Timestamp",
        "description": "Lifecycle event time in UTC."
      },
      {
        "name": "incident_id",
        "type": "Utf8",
        "description": "Stable incident identifier."
      },
      {
        "name": "service",
        "type": "Utf8",
        "description": "Primary affected service."
      },
      {
        "name": "event_name",
        "type": "Utf8",
        "description": "impact_started, detected, or resolved."
      },
      {
        "name": "severity",
        "type": "Utf8",
        "description": "Reviewed incident severity."
      },
      {
        "name": "environment",
        "type": "Utf8",
        "description": "Deployment environment."
      }
    ]
  },
  "query": "WITH incident_times AS (\n  SELECT\n    incident_id,\n    service,\n    MIN(CASE WHEN event_name = 'impact_started' THEN timestamp_utc END)\n      AS impact_started_at,\n    MIN(CASE WHEN event_name = 'detected' THEN timestamp_utc END)\n      AS detected_at,\n    MAX(CASE WHEN event_name = 'resolved' THEN timestamp_utc END)\n      AS resolved_at\n  FROM incident_lifecycle_events\n  WHERE timestamp_utc >= now() - INTERVAL '90 days'\n    AND environment = 'production'\n  GROUP BY incident_id, service\n)\nSELECT\n  service,\n  COUNT(*) AS incidents,\n  AVG(date_part('epoch', detected_at - impact_started_at) / 60.0)\n    AS average_detection_minutes,\n  AVG(date_part('epoch', resolved_at - detected_at) / 60.0)\n    AS average_recovery_minutes\nFROM incident_times\nWHERE impact_started_at IS NOT NULL\n  AND detected_at IS NOT NULL\n  AND resolved_at IS NOT NULL\nGROUP BY service\nORDER BY average_recovery_minutes DESC, service;",
  "fixtureKind": "reproducible",
  "inputRows": [
    {
      "timestamp_utc": "2026-07-28T15:00:00.000Z",
      "incident_id": "inc-api-1",
      "service": "checkout-api",
      "event_name": "impact_started",
      "severity": "high",
      "environment": "production"
    },
    {
      "timestamp_utc": "2026-07-28T15:05:00.000Z",
      "incident_id": "inc-api-1",
      "service": "checkout-api",
      "event_name": "detected",
      "severity": "high",
      "environment": "production"
    },
    {
      "timestamp_utc": "2026-07-28T15:30:00.000Z",
      "incident_id": "inc-api-1",
      "service": "checkout-api",
      "event_name": "resolved",
      "severity": "high",
      "environment": "production"
    },
    {
      "timestamp_utc": "2026-07-28T16:20:00.000Z",
      "incident_id": "inc-api-2",
      "service": "checkout-api",
      "event_name": "impact_started",
      "severity": "high",
      "environment": "production"
    },
    {
      "timestamp_utc": "2026-07-28T16:30:00.000Z",
      "incident_id": "inc-api-2",
      "service": "checkout-api",
      "event_name": "detected",
      "severity": "high",
      "environment": "production"
    },
    {
      "timestamp_utc": "2026-07-28T17:10:00.000Z",
      "incident_id": "inc-api-2",
      "service": "checkout-api",
      "event_name": "resolved",
      "severity": "high",
      "environment": "production"
    },
    {
      "timestamp_utc": "2026-07-28T16:30:00.000Z",
      "incident_id": "inc-worker-1",
      "service": "billing-worker",
      "event_name": "impact_started",
      "severity": "high",
      "environment": "production"
    },
    {
      "timestamp_utc": "2026-07-28T16:45:00.000Z",
      "incident_id": "inc-worker-1",
      "service": "billing-worker",
      "event_name": "detected",
      "severity": "high",
      "environment": "production"
    },
    {
      "timestamp_utc": "2026-07-28T17:45:00.000Z",
      "incident_id": "inc-worker-1",
      "service": "billing-worker",
      "event_name": "resolved",
      "severity": "high",
      "environment": "production"
    }
  ],
  "illustrativeInputRows": [
    {
      "timestamp_utc": "2026-07-28T15:00:00.000Z",
      "incident_id": "inc-api-1",
      "service": "checkout-api",
      "event_name": "impact_started",
      "severity": "high",
      "environment": "production"
    },
    {
      "timestamp_utc": "2026-07-28T15:05:00.000Z",
      "incident_id": "inc-api-1",
      "service": "checkout-api",
      "event_name": "detected",
      "severity": "high",
      "environment": "production"
    },
    {
      "timestamp_utc": "2026-07-28T15:30:00.000Z",
      "incident_id": "inc-api-1",
      "service": "checkout-api",
      "event_name": "resolved",
      "severity": "high",
      "environment": "production"
    },
    {
      "timestamp_utc": "2026-07-28T16:20:00.000Z",
      "incident_id": "inc-api-2",
      "service": "checkout-api",
      "event_name": "impact_started",
      "severity": "high",
      "environment": "production"
    },
    {
      "timestamp_utc": "2026-07-28T16:30:00.000Z",
      "incident_id": "inc-api-2",
      "service": "checkout-api",
      "event_name": "detected",
      "severity": "high",
      "environment": "production"
    },
    {
      "timestamp_utc": "2026-07-28T17:10:00.000Z",
      "incident_id": "inc-api-2",
      "service": "checkout-api",
      "event_name": "resolved",
      "severity": "high",
      "environment": "production"
    },
    {
      "timestamp_utc": "2026-07-28T16:30:00.000Z",
      "incident_id": "inc-worker-1",
      "service": "billing-worker",
      "event_name": "impact_started",
      "severity": "high",
      "environment": "production"
    },
    {
      "timestamp_utc": "2026-07-28T16:45:00.000Z",
      "incident_id": "inc-worker-1",
      "service": "billing-worker",
      "event_name": "detected",
      "severity": "high",
      "environment": "production"
    },
    {
      "timestamp_utc": "2026-07-28T17:45:00.000Z",
      "incident_id": "inc-worker-1",
      "service": "billing-worker",
      "event_name": "resolved",
      "severity": "high",
      "environment": "production"
    }
  ],
  "expectedOutput": {
    "columns": [
      "service",
      "incidents",
      "average_detection_minutes",
      "average_recovery_minutes"
    ],
    "rows": [
      {
        "service": "billing-worker",
        "incidents": 1,
        "average_detection_minutes": 15,
        "average_recovery_minutes": 60
      },
      {
        "service": "checkout-api",
        "incidents": 2,
        "average_detection_minutes": 7.5,
        "average_recovery_minutes": 32.5
      }
    ]
  },
  "notes": [
    "The included synthetic input rows generate the expected output when timestamps are shifted into the documented query window.",
    "Run this fixture in the public browser SQL playground; the selected query executes locally with DuckDB-Wasm.",
    "Adapt time windows, thresholds, identities, and business definitions before operational use."
  ]
}