Drill — Audit the Toil
Wavelength's Checkout Reliability team — the team that owns checkout-api throughout this course's capstone — just finished a rotation week, and the team lead wants a real toil number for the quarterly capacity review, not a vibe. You've been handed the raw on-call log: fourteen entries, every page, ticket, and meeting logged with a timestamp and minutes spent. Your job, in order: (1) classify every single entry as toil, engineering project work, or overhead, using the exact six-gate test and three-bucket model from Reducing Toil — not a gut call; (2) turn the correctly classified entries into a real toil percentage and check it against Google's 50% ceiling from toil & automation; (3) name the single highest-leverage automation investment the data actually supports. This page assumes you already know the six gates and the toil/overhead/engineering three-bucket split — it drills applying them under a full week of realistic, occasionally misleading data, the same way a real capacity review would hand it to you.
Imagine a school nurse logs every single visit for a week — headaches, a skinned knee, a temperature check before every gym class, and one long afternoon spent with a kid having a genuinely rare allergic reaction nobody on staff had ever seen before. If the principal just adds up "time not actually teaching" and calls the whole pile "wasted," the rare-reaction afternoon gets blamed exactly as hard as the routine temperature checks — even though a cheap forehead thermometer handed to every gym teacher could make the temperature checks disappear completely, and nothing could or should have made the rare afternoon disappear. The real job isn't complaining that the office was busy. It's sorting which visits a cheap tool could have prevented from the one visit that genuinely needed a trained person's judgment — and then buying the tool for the biggest pile, not the loudest one.
The scenario: Checkout Reliability's on-call week
☺ Like you're 10: One team, one pager, one week — every page, ticket, and meeting they touched, logged with exactly how many minutes it took.
The Checkout Reliability team owns checkout-api and its background worker payment-worker — the service that reconciles asynchronous webhooks from the external payment processor against checkout-api's order records — plus on-call coverage for a legacy internal admin panel and the customer-success escalation queue when a ticket needs an engineer, not just a support agent. This is the same checkout-api the course's capstone builds end to end; nothing about its SLO or architecture changes here. Below is the full raw log for the week of Monday 2026-08-10 through Sunday 2026-08-16, exactly as it was pulled from PagerDuty, the ticket queue, and the on-call engineer's own notes — nothing pre-filtered, nothing pre-labeled.
| # | Time | Trigger | Area | What happened | Min |
|---|---|---|---|---|---|
| 1 | Mon 08-10, 03:14 | Page | payment-worker | Pod OOM-killed again. On-call confirmed the process was down and restarted it by hand. Same memory leak that's sat unassigned in the backlog for two sprints. | 12 |
| 2 | Mon 08-10, 09:40 | Ticket | admin-panel | TLS cert for the legacy internal admin panel expires in 48h. Requested a new one from the CA, uploaded it to the load balancer console by hand, updated three config references. | 35 |
| 3 | Tue 08-11, 11:02 | Slack request | checkout-api | Platform team stood up the ap-south-2 region. On-call hand-ran the same seven kubectl/gcloud commands used to wire DNS and base config for every new region. | 40 |
| 4 | Tue 08-11, 14:20 | Ticket | customer-success | Enterprise customer (Meridian Foods) locked out of MFA. Reset their device by hand through the internal admin tool — no self-service reset exists yet. | 15 |
| 5 | Wed 08-12, 02:47 | Page | payment-worker | Same hung-pod pattern as Monday. Restarted it by hand again. | 10 |
| 6 | Wed 08-12, 09:10–14:05 | Page → investigation | checkout-api | A support ticket about a customer double-charged on a stacked coupon code turned into a real root-cause hunt — nobody had seen that coupon-stacking path fail before. Traced it to a race in the discount-application step, wrote a validation fix and a regression test, shipped by end of day. | 300 |
| 7 | Wed 08-12, 16:00 | Ticket | customer-success | Second MFA reset this week (Halcyon Retail), same manual admin-tool flow. | 12 |
| 8 | Thu 08-13, 09:00 | Meeting | — | Weekly reliability status meeting, plus updating the on-call handoff spreadsheet for Friday's handoff. | 45 |
| 9 | Thu 08-13, 13:30 | Ticket | checkout-api / billing | New enterprise customer (Bellwood Analytics) signed. Hand-provisioned their dedicated Postgres schema, IAM role, and billing webhook across three separate consoles — the same nine-step checklist run for every onboarding. | 55 |
| 10 | Fri 08-14, 04:03 | Page | payment-worker | Third hung-pod restart this week, same leak. | 14 |
| 11 | Fri 08-14, 11:45 | Ticket | customer-success | Third MFA reset this week (Orinda Health). | 10 |
| 12 | Fri 08-14, 15:10 | Ticket | checkout-api | Read the diff and approved a production deploy touching the payment-retry path before it merged. | 20 |
| 13 | Sat 08-15, 08:20 | Ticket | checkout-api / billing | Second new-customer provisioning this week (Fenwick Logistics), same nine-step checklist. | 50 |
| 14 | Sun 08-16, 19:32 | Page, auto-cleared | session cache (cache-infra) | Burn-rate alert fired on the shared session cache and cleared itself within four minutes — Redis failover completed automatically. On-call glanced at the dashboard to confirm and took no action. | 5 |
Total logged time across all fourteen entries: 623 minutes, a little over ten hours, inside a nominal 40-hour week. Resist the urge to eyeball a verdict from this table alone — Step 1 below is the whole point of this drill, and at least three entries here are built specifically to fail a gate you might not think to check.
Step 1 — classify every entry
☺ Like you're 10: One prior question sorts out the paperwork, then six yes/no questions sort everything else into toil or not.
Run each entry through Reducing Toil's exact test: first, the prior question — is this about operating the production service, or not? — which sorts administrative work into overhead before the six gates ever apply. Then, for anything that survives that question, all six gates (manual, repetitive, automatable, tactical, no enduring value, O(n) with growth) must hold, or it isn't toil.
Before reading further, go back to the table above and write, for each of the fourteen entries, one of three verdicts — Toil, Engineering, or Overhead — plus the single gate or question that decided it. Entries 6, 8, 12, and 14 are the ones most likely to trip you up if you're pattern-matching on "felt like firefighting" instead of running the actual test.
Here's the worked verdict for every entry:
| # | Verdict | Deciding gate / question |
|---|---|---|
| 1, 5, 10 | Toil | All six hold: hands-on restart, recurs three times this week alone, a process supervisor or liveness probe could do it, purely reactive to a page, the pod ends up exactly where it was before it hung, and restart volume scales with worker fleet size. This is the identical scenario Reducing Toil's own worked-example table already adjudicated. |
| 2 | Toil | All six hold, including O(n): the number of internal certificates needing manual rotation grows with the number of internal services, and this is purely calendar-driven with no judgment call — the classic profile for full ACME-style automation. |
| 3 | Toil | All six hold — the exact scenario Reducing Toil's own toon scene already ran gate by gate: manual, repetitive per region launch, scriptable with no judgment call, reactive to the launch event, restores nothing beyond baseline setup, scales with region count. |
| 4, 7, 11 | Toil | All six hold: manual admin-tool clicks, recurs across customers, automatable behind an identity-verified self-service flow with no genuine judgment call, reactive to each request, restores the account to normal with nothing improved, and scales directly with customer count. |
| 6 | Not toil — engineering project work | Fails repetitive ("nobody had seen that coupon-stacking path fail before") and fails no enduring value (the validation fix and regression test prevent this exact failure from recurring). The biggest single line on the sheet is not the biggest toil source — it's the opposite of toil, on purpose. |
| 8 | Not toil — overhead | Fails the prior question before the six gates even apply: a status meeting and a handoff spreadsheet aren't operating the production service at all. |
| 9, 13 | Toil | All six hold: manual across three consoles, recurs per onboarding, automatable into an infrastructure-as-code template, reactive to each signup, restores nothing beyond that one customer's baseline setup, and scales directly with enterprise customer count — the same scenario toil & automation's own worked example already walks. |
| 12 | Not toil | Fails automatable: reading a diff on a change to the payment-retry path for real risk is exactly the judgment call a script can't safely replace, even though the approval happens on every release. |
| 14 | Not toil | Fails manual: nobody executed a remediation step — Redis failover ran itself and the engineer only confirmed it on a dashboard. This line isn't a toil source at all; it's a rung-5 automation already working exactly as designed. See the automation ladder in toil & automation. |
Entries 6, 8, 12, and 14 are deliberately the ones a rushed classification gets wrong, and they're also the four largest or most attention-grabbing lines on the sheet after the toil entries themselves. Frequency and duration tell you almost nothing about whether something is toil — entry 6 is the longest single entry on the whole log (300 minutes) and still isn't toil, while entry 14 barely registers (5 minutes) and is arguably the best outcome on the entire sheet, because it's toil that's already been eliminated.
Step 2 — quantify the toil percentage
☺ Like you're 10: Add up only the entries that actually passed all six gates, divide by everything logged, and compare that one real number to the 50% line.
Summing the correctly classified entries: Toil = 36 + 35 + 40 + 37 + 105 = 253 minutes (payment-worker restarts 36, cert rotation 35, region DNS onboarding 40, three MFA resets 37, two customer provisionings 105). Everything else — the investigation, the meeting, the deploy approval, the self-healed cache blip — sums to 370 minutes and isn't toil under the formal test.
Toil (correctly classified) = 253 min
Not toil (engineering + overhead +
judgment call + already-automated) = 370 min
──────────────────────────────────────────────
Total logged this week = 623 min
Toil % of total logged time = 253 ÷ 623 = 0.4061 = 40.6% ← under the 50% ceilingThe easiest wrong answer here isn't a bad gate call — it's skipping the gates entirely and treating "everything that wasn't a meeting" as toil: 578 ÷ 623 = 92.8%, more than double the real number. That naive figure would tell the capacity review the team is catastrophically over the 50% cap and needs emergency headcount, when the actual, correctly classified number — 40.6% — says something much more specific and much more actionable: the team is under the ceiling this week, and the fix isn't more people, it's automating a handful of named, recurring tasks. Getting the denominator right here is the exact same discipline the SLO & error-budget drill demands of a health-check filter — skip the correction and the number still looks plausible, which is what makes it dangerous.
40.6% is under the ceiling — but a single week isn't the quarter-averaged number Google's policy is actually built on, and the composition matters more than the headline figure. Split the 253 toil minutes by what drives their volume:
| Toil source | This week | Scales with |
|---|---|---|
| Customer provisioning (9, 13) + MFA resets (4, 7, 11) | 142 min | Enterprise customer count — Checkout Reliability's own quarterly business review projects ~25% growth in enterprise signups per quarter. |
| Payment-worker restarts (1, 5, 10) | 36 min | Nothing but the unfixed memory leak — fixed cost until someone root-causes it, not customer growth. |
| Cert rotation (2) | 35 min | Calendar and internal service count — grows slowly, largely fixed for this projection. |
| Region DNS onboarding (3) | 40 min | Region launches, which happen a few times a year, not weekly — this week's entry is a lumpy one-off, not a typical week's cost, and shouldn't be projected forward linearly. |
Hold the fixed and lumpy toil (71 + 40 = 111 min) and the 370 non-toil minutes constant, and grow only the customer-count-coupled slice (142 min) at the stated 25% per quarter:
| Quarter | Customer-coupled toil | Total toil / wk | Total logged / wk | Toil % |
|---|---|---|---|---|
| Now | 142 | 253 | 623 | 40.6% |
| +1 quarter | 177.5 | 288.5 | 658.5 | 43.8% |
| +2 quarters | 221.9 | 332.9 | 702.9 | 47.4% |
| +3 quarters | 277.3 | 388.3 | 758.3 | 51.2% |
This is a deliberately simplified model — it holds the fixed, lumpy, and non-toil load flat and grows only the two customer-count-coupled sources — but the direction is the real takeaway regardless of exactly which quarter it lands in: left alone, this team's toil ratio crosses the 50% ceiling in roughly three quarters, driven entirely by enterprise-customer growth the team doesn't control, with zero change in the defect count, headcount, or engineering discipline. That's the case for acting on Step 3 now, before the number crosses, not after.
Step 3 — the single highest-leverage automation
☺ Like you're 10: Pick the toil source that's both the biggest slice right now and the one that keeps growing on its own — not just the one that paged the most times.
It's tempting to pick payment-worker — it fired three separate pages this week, more than any other single toil source. Resist that instinct: raw page count isn't leverage.
- By raw minutes this week, customer provisioning (105 min) is already the single largest toil line on the sheet — larger than payment-worker's three restarts combined (36 min) and larger than cert rotation (35 min).
- By the O(n) growth property specifically, provisioning is one of only two toil sources coupled to Checkout Reliability's fastest-growing input — enterprise signups — and it's the larger of those two (105 of the 142 customer-coupled minutes, versus 37 for MFA resets).
- By automation-ladder position, provisioning currently sits at rung 1 — fully manual, nine steps across three consoles, from toil & automation's own automation ladder. Climbing even to rung 3 removes most of the manual-execution risk; climbing to rung 4 or 5 removes the toil entirely.
- Payment-worker, by contrast, is capped: its toil doesn't grow with the business, and — critically — the correct fix isn't automating the restart at all. It's root-causing the memory leak through a proper blameless postmortem, which eliminates the toil source completely rather than just moving it up a rung. Automating a restart around an unfixed leak is treating the symptom.
Recommendation: automate customer provisioning. Replace the nine-step, three-console manual checklist with a parameterized Terraform module triggered automatically the moment a contract is signed — climbing straight from rung 1 to rung 4, with a clear path to rung 5 once the team trusts it unattended:
# modules/customer-onboarding/main.tf
variable "customer_id" { type = string }
variable "tier" { type = string } # "standard" | "enterprise"
resource "aws_db_instance" "customer_schema" {
identifier = "cust-${var.customer_id}"
engine = "postgres"
instance_class = var.tier == "enterprise" ? "db.r6g.large" : "db.t4g.medium"
allocated_storage = 20
db_name = "customer_${var.customer_id}"
}
resource "aws_iam_role" "customer_role" {
name = "customer-${var.customer_id}-role"
assume_role_policy = data.aws_iam_policy_document.trust.json
}
resource "null_resource" "billing_webhook" {
provisioner "local-exec" {
command = "curl -X POST https://billing.internal/api/webhooks -d '{\"customer_id\":\"${var.customer_id}\"}'"
}
}# .github/workflows/onboard-customer.yml — fired by the CRM's "contract signed" webhook
on:
repository_dispatch:
types: [contract-signed]
jobs:
provision:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: |
terraform init
terraform apply -auto-approve \
-var="customer_id=${{ github.event.client_payload.customer_id }}" \
-var="tier=${{ github.event.client_payload.tier }}"
working-directory: modules/customer-onboarding
- run: curl -X POST "$SLACK_WEBHOOK" -d '{"text":"Provisioned '"${{ github.event.client_payload.customer_id }}"'"}'That's rung 4 on day one — the system detects the trigger and runs unattended, with a Slack post so a human still notices. It removes the full 105 minutes this week cost, and because it's coupled to the same growth driving the projection in Step 2, it removes a proportionally larger number every quarter after — the automation pays for itself faster the longer it's deferred, which is exactly the ROI case toil & automation's section on building the case for automation investment describes. Secondary recommendation, not this drill's top pick but worth flagging separately: get payment-worker's memory leak onto the next sprint's postmortem action-item list — see reliability economics for how to frame that cost trade-off next to the provisioning automation for the same review.
Pull five real entries from your own team's actual on-call log or ticket queue this month. Run each one through the same test: the prior overhead question, then all six gates. Write one verdict per entry citing the specific gate or question that decided it — not just "toil" or "not toil." That one-line habit, defended against a specific property rather than a feeling, is precisely what a real capacity review — and the SREF exam's Module 3 — is scoring.
Benny the Beaver: Ran all fourteen through the six gates. Provisioning and the MFA resets are clean sweeps — toil on every property.
Foxy: What about Wednesday's double-charge investigation? Three hundred minutes is the biggest line on the whole sheet — feels like the worst offender to me.
Benny the Beaver: Fails repetitive on the first read. Nobody had ever seen that coupon-stacking path fail before, and the fix means it can't recur the same way again. That's engineering, not toil — the biggest line isn't the answer.
Sol the Sloth: I almost counted the meeting too, first pass. Corrected total: 253 of 623 minutes. Forty point six percent. Under the ceiling — for this week.
Timmy the Turtle: "For this week" is carrying a lot of weight in that sentence. What happens once the customer-coupled slice compounds?
Professor Owl: Sol already ran it — three quarters out, unattended, it crosses fifty. So the audit already answered its own question: automate provisioning before the number does the crossing for you, not after.
1. Which single entry in the week's log is the largest by raw minutes, and why does the six-gate test say it's not toil despite being the biggest line on the sheet? 2. What's the one prior question that filters overhead out before the six gates even apply, and which log entry does it catch? 3. What's the correctly classified toil percentage for this week, and what wrong percentage would you get by only excluding the meeting and calling everything else toil? 4. Between payment-worker's restarts and customer provisioning, which is the single highest-leverage automation target, and what property makes it so — even though payment-worker paged three times this week and provisioning only twice?
Check your answers
- The double-charge investigation (300 minutes, entry 6) is the largest single line. It fails repetitive — the coupon-stacking bug had never been seen before — and fails no enduring value, since the shipped fix prevents the exact failure from recurring. Both disqualify it from toil; it's engineering project work.
- The prior question is: is this work about operating the production service, or not? It catches entry 8 — the weekly status meeting and handoff-spreadsheet update — sorting it into overhead before the six-gate test ever runs, since it isn't operational work on the service at all.
- Correct: 253 ÷ 623 = 40.6%. Naive, excluding only the meeting: 578 ÷ 623 = 92.8% — more than double the real figure, because it wrongly keeps the engineering investigation, the judgment-call deploy approval, and the already-self-healed cache blip counted as toil.
- Customer provisioning. Even though payment-worker fired more often this week, provisioning is both the single largest toil line by minutes (105 of 253) and the one whose volume is directly coupled to enterprise-customer growth — the O(n)-with-growth property — projected at roughly 25% per quarter. Its cost compounds every quarter left unautomated, while payment-worker's toil is capped by a single fixable bug and doesn't grow with the business at all; the correct fix there is a postmortem, not an automation investment.