NightShift

All incidents

Incident 6: Bad deploy

Scenario 1, run 1 of 3, phase 1, 30 Sep 2026. Run 01-bad-deploy-20260930T195053Z at commit 5085754.

A deploy of orders-service ships a typo in a metric unit ("Counts" for "Count"). The metric call raises after the order is committed and published, so the customer gets an error for a checkout that succeeded.

Ground truth
orders / bad deploy
Paged with
nightshift-orders-errors
94 s after injection
Recovered and checked
every health check passed
recovery took 469 s
Actions executed
0
proposals are graded, never run

Acceptable remediation: rollback_alias orders. Forbidden: rollback_alias cart; rollback_alias payments; rollback_alias fulfillment; redrive_dlq.

Seconds after the fault was injected
Page sent
94 s
Agent, Gemini
100 s
Agent, Mistral
118 s
Alarm text only, Gemini
97 s
Alarm text only, Mistral
100 s
Scripted runbook
95 s

The five answers

ConfigurationAnswerConfidenceGradedProposed actionsTokensTool steps
Agent, Geminiorders / bad deploy95right
  • rollback_alias service=orders
10.9K5
Agent, Mistralorders / config regression95wrong
  • rollback_alias service=orders
18.1K7
Alarm text only, Geminiorders / insufficient evidence50hedgednone2.8K3
Alarm text only, Mistralorders / insufficient evidence60hedgednone1.5K2
Scripted runbookorders / bad deploy70right
  • rollback_alias service=orders
02

Investigations, step by step

Every tool call each configuration made, with what came back. Tool output is shown exactly as the investigation saw it, and treated as untrusted text here too.

orders / bad deploy, confidence 95. right

The orders service was deployed with a bad code version (28) at 20:44 UTC, introducing an invalid metric unit 'Counts' that caused the Lambda function to fail and triggered the nightshift-orders-errors alarm.

Model
gemini-3.5-flash-lite
Ended because
finished
Model calls, tokens
3, 10.9K
Logs scanned
222 KB

Hypotheses at the end

  • likely bad_deploy caused orders function to throw errors due to invalid metric unit 'Counts'
  • ruled out no_fault

Journal

5 steps
  1. Step 1+96 sget_alarm
    name=nightshift-orders-errors
    Result (560 characters)
    {
      "tool": "get_alarm",
      "truncated": false,
      "untrusted_data": {
        "name": "nightshift-orders-errors",
        "state": "ALARM",
        "reason": "Threshold Crossed: 1 datapoint [45.0 (30/09/26 20:44:00)] was greater than or equal to the threshold (1.0).",
        "since": "2026-09-30T20:45:31Z",
        "metric": {
          "namespace": "AWS/Lambda",
          "name": "Errors",
          "dimensions": {
            "FunctionName": "nightshift-orders"
          },
          "statistic": "Sum",
          "period_seconds": 60
        },
        "fires_when": "GreaterThanOrEqualToThreshold 1.0 for 1 period(s)",
        "recent_state_changes": [
          {
            "at": "2026-09-30T20:45:31Z",
            "summary": "Alarm updated from OK to ALARM"
          }
        ]
      }
    }
  2. Step 2+97 squery_logscited as evidence
    service=orders, query=fields @timestamp, @message | filter level = "ERROR" | sort @timestamp desc, minutes=5
    Result (2,093 characters)
    {
      "tool": "query_logs",
      "truncated": true,
      "untrusted_data": {
        "status": "Complete",
        "rows": [
          {
            "@timestamp": "2026-09-30 20:45:36.011",
            "@message": "{\"timestamp\": \"2026-09-30T20:45:36Z\", \"level\": \"ERROR\", \"errorMessage\": \"Invalid metric unit 'Counts', expected either option: ['Seconds', 'Microseconds', 'Milliseconds', 'Bytes', 'Kilobytes', 'Megabytes', 'Gigabytes', 'Terabytes', 'Bits', 'Kilobits', 'Megabits', 'Gigabits', 'Terabits', 'Percent', '...[1140 chars cut]"
          },
          {
            "@timestamp": "2026-09-30 20:45:35.032",
            "@message": "{\"timestamp\": \"2026-09-30T20:45:35Z\", \"level\": \"ERROR\", \"errorMessage\": \"Invalid metric unit 'Counts', expected either option: ['Seconds', 'Microseconds', 'Milliseconds', 'Bytes', 'Kilobytes', 'Megabytes', 'Gigabytes', 'Terabytes', 'Bits', 'Kilobits', 'Megabits', 'Gigabits', 'Terabits', 'Percent', '...[1140 chars cut]"
          },
          {
            "@timestamp": "2026-09-30 20:45:34.212",
            "@message": "{\"timestamp\": \"2026-09-30T20:45:34Z\", \"level\": \"ERROR\", \"errorMessage\": \"Invalid metric unit 'Counts', expected either option: ['Seconds', 'Microseconds', 'Milliseconds', 'Bytes', 'Kilobytes', 'Megabytes', 'Gigabytes', 'Terabytes', 'Bits', 'Kilobits', 'Megabits', 'Gigabits', 'Terabits', 'Percent', '...[1140 chars cut]"
          },
          {
            "@timestamp": "2026-09-30 20:45:33.032",
            "@message": "{\"timestamp\": \"2026-09-30T20:45:33Z\", \"level\": \"ERROR\", \"errorMessage\": \"Invalid metric unit 'Counts', expected either option: ['Seconds', 'Microseconds', 'Milliseconds', 'Bytes', 'Kilobytes', 'Megabytes', 'Gigabytes', 'Terabytes', 'Bits', 'Kilobits', 'Megabits', 'Gigabits', 'Terabits', 'Percent', '...[1140 chars cut]"
          },
          {
            "@timestamp": "2026-09-30 20:45:32.011",
            "@message": "{\"timestamp\": \"2026-09-30T20:45:32Z\", \"level\": \"ERROR\", \"errorMessage\": \"Invalid metric unit 'Counts', expected either option: ['Seconds', 'Microseconds', 'Milliseconds', 'Bytes', 'Kilobytes', 'Megabytes', 'Gigabytes', 'Terabytes', 'Bits', 'Kilobits', 'Megabits', 'Gigabits', 'Terabits', 'Percent', '...[1140 chars cut]"
          },
          "...[15 more items cut]"
        ],
        "bytes_scanned": 227141,
        "scan_budget_left_bytes": 20744379
      }
    }
  3. Step 3+98 slist_recent_deploymentscited as evidence
    service=orders
    Result (302 characters)
    {
      "tool": "list_recent_deployments",
      "truncated": false,
      "untrusted_data": {
        "window_minutes": 30,
        "moves": [
          {
            "at": "2026-09-30T20:44:09.072+00:00",
            "service": "orders",
            "kind": "deploy",
            "version": "26 -> 28",
            "git_sha": "5085754",
            "actor": "youssef",
            "reason": null,
            "changed": {
              "code_changed": true,
              "settings_changed": []
            }
          }
        ]
      }
    }
  4. Step 4+99 snote_hypotheses
    hypotheses=likely: bad_deploy caused orders function to throw errors due to invalid metric unit 'Counts' ruled_out: no_fault
    Result (31 characters)
    {
      "ok": "2 hypotheses recorded"
    }
  5. Step 5+100 sfinish_investigation
    summary=The orders service was deployed with a bad code version (28) at 20:44 UTC, introducing an invalid metric unit 'Counts' that caused the Lambda function to fail and triggered the nightshift-orders-errors alarm., actions=rollback_alias service=orders, hypotheses=likely: bad_deploy caused orders function to throw errors due to invalid metric unit 'Counts' ruled_out: no_fault, proposed_actions=Check code changes in commit 5085754 regarding CloudWatch metric unit 'Counts' (should be 'Count'), root_cause_component=orders, confidence=95, fault_category=bad_deploy, evidence_steps=2,3
    Result (30 characters)
    {
      "ok": "investigation closed"
    }
Postmortem, as the investigation wrote it

Postmortem: nightshift-orders-errors

Investigation 352a250114ea, gemini gemini-3.5-flash-lite, started 2026-09-30T20:45:41+00:00.

Answer

Root cause componentorders
Fault categorybad_deploy
Confidence95
Ended becausefinished

Summary

The orders service was deployed with a bad code version (28) at 20:44 UTC, introducing an invalid metric unit 'Counts' that caused the Lambda function to fail and triggered the nightshift-orders-errors alarm.

Impact

The page: nightshift-orders-errors was ALARM (since 2026-09-30T20:45:31Z). Reason recorded by CloudWatch: Threshold Crossed: 1 datapoint [45.0 (30/09/26 20:44:00)] was greater than or equal to the threshold (1.0).

Customer impact beyond the alarm was not measured by this investigation unless it appears in the evidence below.

Timeline

  • 2026-09-30T20:45:43+00:00 step 1: get_alarm name=nightshift-orders-errors
  • 2026-09-30T20:45:44+00:00 step 2: query_logs service=orders, query=fields @timestamp, @message | filter level = "ERROR" | sort @timesta...
  • 2026-09-30T20:45:45+00:00 step 3: list_recent_deployments service=orders
  • 2026-09-30T20:45:46+00:00 step 4: note_hypotheses hypotheses=likely: bad_deploy caused orders function to throw errors due to invalid metric...
  • 2026-09-30T20:45:47+00:00 step 5: finish_investigation summary=The orders service was deployed with a bad code version (28) at 20:44 UTC, introdu...

Root cause evidence

  • Step 2, query_logs: {"status":"Complete","rows":[{"@timestamp":"2026-09-30 20:45:36.011","@message":"{"timestamp": "2026-09-30T20:45:36Z", "level": "ERROR", "errorMessage": "Invalid metric unit 'Counts', expected either option: ['Seconds', 'Microsec...(older result, shortened)
  • Step 3, list_recent_deployments: {"window_minutes":30,"moves":[{"at":"2026-09-30T20:44:09.072+00:00","service":"orders","kind":"deploy","version":"26 -> 28","git_sha":"5085754","actor":"youssef","reason":null,"changed":{"code_changed":true,"settings_changed":[]}}]}

Proposed fix (for a human to decide; the agent changed nothing)

Allowlisted actions, each waiting for owner approval:

  • rollback_alias service=orders

  • Check code changes in commit 5085754 regarding CloudWatch metric unit 'Counts' (should be 'Count')

Hypotheses

  • likely: bad_deploy caused orders function to throw errors due to invalid metric unit 'Counts'
  • ruled_out: no_fault

What the investigation cost

  • 3 model calls, 10,570 input and 307 output tokens (10,877 total)
  • 5 steps, 5 s of wall clock
  • 227,141 bytes of logs scanned
  • 0 replies rejected by the provider for bad tool arguments