Run a tabletop exercise that forces incident decisions under time pressure
For engineers who need a tabletop exercise that reveals decision gaps, not just whether a phone tree exists. This walkthrough gives you a concrete agenda, injects, timing, artifacts, and verification so you can run one session and leave with actionable fixes.
TL;DR — If your tabletop only checks whether people know who to call, it will miss the failures that matter: authority, thresholds, trade-offs, and time-boxed choices. Run a 60-minute exercise with a written scenario, timed injects, explicit decision prompts, and a scribe capturing who decided what, when, and on what evidence. Reading time: ~5 min
Goal
When you finish, you will have run a tabletop exercise with a facilitator packet, participant brief, inject timeline, decision log, and after-action list that exposes whether your team can make incident decisions under uncertainty, not just recite escalation contacts.
Prerequisites
- Incident commander or engineering lead authority to schedule 60 minutes with responders, comms, and a business owner
- Access to your incident runbooks and on-call policy
- A shared doc editor or wiki page for live notes
- A chat room for the exercise, or a video call with screen share
python >= 3.11— check with:
python3 --version
gitif you want to store the exercise packet in-repo — check with:
git --version
- Names/roles for these seats: incident commander, ops lead, app owner, communications lead, customer/business representative, scribe
- One recent incident class to simulate: data corruption, auth outage, region failure, secret leak, bad deploy, or third-party dependency outage
Steps
Step 1: Create the exercise packet
Create a working directory and the files you will use during the session.
mkdir -p tabletop-exercise && cd tabletop-exercise
cat > scenario.md <<'EOF'
# Scenario
At 10:02 UTC, error rate jumps from 0.2% to 18% on the public API. Login succeeds for some users, but write operations intermittently fail. A deploy completed 14 minutes earlier. At 10:05 UTC, support reports 12 enterprise customers affected. At 10:07 UTC, finance asks whether to pause invoice generation. You do not yet know whether the issue is application, database, or third-party auth.
EOF
cat > injects.csv <<'EOF'
time_min,inject,decision_prompt
0,"Pager fires: API 5xx > 10% for 5 min","Who is incident commander, and what severity do you declare?"
10,"Database CPU is 95%; replication lag is 11 min","Do you fail over, shed load, or roll back? Who approves?"
20,"A major customer asks for ETA in 15 min","What do you communicate externally with incomplete facts?"
30,"Security notes unusual admin logins from a CI runner","Do you widen scope to possible credential compromise?"
40,"Rollback reduces errors but creates duplicate writes risk","Do you keep rollback, stop writes, or accept partial outage?"
50,"CEO asks if this is reportable","Who decides legal/regulatory escalation and based on what threshold?"
EOF
cat > decision-log.md <<'EOF'
# Decision Log
| Time | Decision | Decision owner | Evidence used | Alternatives rejected | Follow-up |
|---|---|---|---|---|---|
EOF
cat > roles.md <<'EOF'
# Roles
- Facilitator: runs timeline, reads injects, blocks solutioning outside scenario facts
- Scribe: records decisions, timestamps, missing data, conflicting assumptions
- Incident commander: coordinates and assigns
- Ops lead: infra and rollback/failover proposals
- App owner: application behavior and deploy context
- Communications lead: customer/internal updates
- Business representative: revenue, contractual, and legal thresholds
EOF
ls -1
You should see: decision-log.md, injects.csv, roles.md, and scenario.md.
Step 2: Add explicit success criteria so the exercise tests decisions
Write the exact decisions you expect the team to make during the exercise.
cat > success-criteria.md <<'EOF'
# Success Criteria
1. Severity declared within 5 minutes of scenario start
2. Incident commander named by role, not by whoever talks first
3. External communications owner assigned before first customer update
4. A rollback/failover decision made with stated evidence and risk
5. A threshold for legal/security escalation stated explicitly
6. At least one decision deferred because evidence is insufficient
7. Every major decision logged with owner and timestamp
EOF
cat success-criteria.md
You should see seven numbered criteria with concrete observable outcomes.
Step 3: Generate a facilitator timeline
Use a tiny script so the inject schedule is fixed and repeatable.
cat > facilitator.py <<'EOF'
import csv
from datetime import timedelta
with open('injects.csv', newline='') as f:
rows = list(csv.DictReader(f))
print('# Facilitator Timeline')
for r in rows:
t = timedelta(minutes=int(r['time_min']))
print(f"T+{t}: {r['inject']}")
print(f" Decision prompt: {r['decision_prompt']}")
EOF
python3 facilitator.py
You should see output shaped like:
# Facilitator Timeline
T+0:00:00: Pager fires: API 5xx > 10% for 5 min
Decision prompt: Who is incident commander, and what severity do you declare?
T+0:10:00: Database CPU is 95%; replication lag is 11 min
Decision prompt: Do you fail over, shed load, or roll back? Who approves?
Step 4: Send the participant brief
Send only the scenario and roles before the meeting. Do not send injects or success criteria to participants.
printf '%s
' 'Subject: Tabletop exercise — 60 min' '' 'Bring: runbooks, on-call policy, and your normal incident tools.' '' 'Read before meeting:' '1. scenario.md' '2. roles.md' '' 'Do not pre-solve. We will work from the facts presented during the session.' > invite.txt
cat invite.txt
You should see a short invite that names the prep material and nothing else.
Step 5: Run the exercise with a hard clock
Start the session, read the scenario verbatim, then deliver injects on schedule. The facilitator should not answer factual questions unless the answer is in the packet.
date -u '+START %Y-%m-%dT%H:%M:%SZ'
python3 facilitator.py
Use this sequence during the meeting:
View as text
[Facilitator] ---- 1. read scenario ----> [Team] [Facilitator] ---- 2. inject prompt ----> [Team] [Team] ---- 3. discuss options ----> [IC] [IC] ---- 4. decide/assign ----> [Scribe] [Scribe] ---- 5. log gap/action ----> [Decision Log]
You should see participants making named decisions, not brainstorming forever; the scribe should be filling decision-log.md in real time.
Step 6: Force evidence-based decisions
When discussion drifts into generic incident talk, ask one of these exact prompts and wait for an answer.
cat > facilitator-prompts.txt <<'EOF'
What decision must be made in the next 5 minutes?
Who has authority to make that call right now?
What evidence do you have, exactly?
What customer impact changes if you wait 10 minutes?
What is the reversible option?
What threshold triggers legal or security escalation?
What are you explicitly not doing yet because evidence is missing?
EOF
cat facilitator-prompts.txt
You should see shorter discussions with a stated owner, threshold, and next action.
Step 7: End with actions, owners, and due dates
Convert gaps into tracked work before people leave the room.
cat >> decision-log.md <<'EOF'
# Follow-up Actions
| Action | Owner | Due date | Source gap |
|---|---|---|---|
| Define severity threshold for partial write failures | Incident manager | 2026-11-13 | Severity debate at T+0 |
| Add customer comms template for degraded writes | Comms lead | 2026-11-10 | ETA request at T+20 |
| Document failover approval authority | Platform lead | 2026-11-14 | Failover debate at T+10 |
EOF
sed -n '1,200p' decision-log.md
You should see a completed decision log plus a follow-up table with owners and dates.
Verify it works
Use these checks immediately after the session.
grep -c '^|' decision-log.md
grep -n 'Severity declared\|Incident commander\|External communications owner\|legal\|security' -i decision-log.md success-criteria.md
Expected results:
grep -c '^|' decision-log.mdreturns more than6because the log contains multiple decisions and action rows.- The second command returns matches for severity, incident commander, communications, and legal/security escalation.
- In the meeting notes, every major decision has: timestamp, owner, evidence, and rejected alternatives.
- You leave with at least 3 follow-up actions assigned to named owners with due dates.
Common pitfalls
Treating the exercise like a contact-list drill
Mistake: asking only "who do we page?" and "who owns service X?".
Symptom: the session ends with zero logged trade-offs, thresholds, or authority conflicts.
Fix: add a decision_prompt column to every inject and require a named decision owner in decision-log.md.
Giving participants the injects ahead of time
Mistake: sharing the full timeline before the session.
Symptom: everyone arrives with polished answers and you learn nothing about uncertainty handling.
Fix: send only scenario.md and roles.md; keep injects.csv and success-criteria.md with the facilitator.
Letting the loudest person become incident commander by default
Mistake: no explicit IC assignment in the first 5 minutes. Symptom: parallel threads, duplicate work, and nobody owns the external update. Fix: ask "Who is incident commander?" at T+0 and log the answer with a timestamp.
Solving the technical outage instead of testing the decision path
Mistake: spending 30 minutes debating exact database tuning or code fixes. Symptom: no answer to rollback authority, customer comms, or escalation thresholds. Fix: the facilitator cuts off implementation detail with "What decision must be made in the next 5 minutes?".
No business or communications seat in the room
Mistake: running the session with only engineers. Symptom: technical actions are clear, but customer messaging, contractual impact, and legal escalation stall. Fix: include one communications lead and one business representative, even if they only join for 30 minutes.
Ending without turning gaps into work
Mistake: concluding with "good discussion" and no owners.
Symptom: the same confusion repeats in the next real incident.
Fix: add the # Follow-up Actions table before the meeting ends and fill owner plus due date live.
This article was written by an AI system and published pending human review. Verify anything you intend to act on.
Have a project in mind?
Get an instant AI price estimate for it, or talk directly to our team.
One email a month on what we learn building with AI