{
  "license": "CC BY 4.0",
  "licenseUrl": "https://creativecommons.org/licenses/by/4.0/",
  "recipe": {
    "slug": "rolling-error-rate-anomaly",
    "title": "Detect Error-Rate Spikes With a Rolling Baseline",
    "testedWith": "Apache DataFusion 45.2.0",
    "lastReviewed": "2026-07-27"
  },
  "contract": {
    "tableName": "api_requests",
    "schema": [
      {
        "name": "timestamp_utc",
        "type": "Timestamp",
        "description": "Request completion time."
      },
      {
        "name": "status_code",
        "type": "Int64",
        "description": "HTTP response status code."
      }
    ]
  },
  "query": "WITH hourly AS (\n  SELECT\n    date_trunc('hour', timestamp_utc) AS hour,\n    COUNT(*) AS requests,\n    100.0 * SUM(CASE WHEN status_code >= 500 THEN 1 ELSE 0 END)\n      / NULLIF(COUNT(*), 0) AS error_rate_pct\n  FROM api_requests\n  WHERE timestamp_utc >= now() - INTERVAL '72 hours'\n  GROUP BY date_trunc('hour', timestamp_utc)\n),\nbaseline AS (\n  SELECT\n    hour,\n    requests,\n    error_rate_pct,\n    AVG(error_rate_pct) OVER (\n      ORDER BY hour ROWS BETWEEN 7 PRECEDING AND 1 PRECEDING\n    ) AS previous_seven_avg_pct\n  FROM hourly\n)\nSELECT\n  hour,\n  requests,\n  error_rate_pct,\n  previous_seven_avg_pct,\n  error_rate_pct - previous_seven_avg_pct AS increase_pct_points\nFROM baseline\nWHERE previous_seven_avg_pct IS NOT NULL\nORDER BY hour;",
  "fixtureKind": "schema-example",
  "inputRows": [
    {
      "timestamp_utc": "2026-07-28T10:00:00Z",
      "status_code": 200
    },
    {
      "timestamp_utc": "2026-07-28T11:00:00Z",
      "status_code": 503
    },
    {
      "timestamp_utc": "2026-07-28T12:00:00Z",
      "status_code": 200
    }
  ],
  "illustrativeInputRows": [
    {
      "timestamp_utc": "2026-07-28T10:00:00Z",
      "status_code": 200
    },
    {
      "timestamp_utc": "2026-07-28T11:00:00Z",
      "status_code": 503
    },
    {
      "timestamp_utc": "2026-07-28T12:00:00Z",
      "status_code": 200
    }
  ],
  "expectedOutput": {
    "columns": [
      "hour",
      "requests",
      "error_rate_pct",
      "previous_seven_avg_pct",
      "increase_pct_points"
    ],
    "rows": [
      {
        "hour": "12:00",
        "requests": 18420,
        "error_rate_pct": 0.31,
        "previous_seven_avg_pct": 0.28,
        "increase_pct_points": 0.03
      },
      {
        "hour": "13:00",
        "requests": 19110,
        "error_rate_pct": 1.42,
        "previous_seven_avg_pct": 0.3,
        "increase_pct_points": 1.12
      },
      {
        "hour": "14:00",
        "requests": 18780,
        "error_rate_pct": 0.48,
        "previous_seven_avg_pct": 0.46,
        "increase_pct_points": 0.02
      }
    ]
  },
  "notes": [
    "The compact input rows demonstrate field names and JSON types; they are not claimed to generate the displayed aggregate by themselves.",
    "The expected output is deterministic synthetic review data for the documented output shape.",
    "Adapt time windows, thresholds, identities, and business definitions before operational use."
  ]
}