BitBootcampBitBootcamp ← all explainers 🔄 Review ⚙ Settings

Drill 10 — The Contaminated Year

Theme: Data Disasters · Format: 20-min drill · Difficulty: advanced

The story

An internal audit finds that a shared feature cache leaked evaluation-period rows into training data — for a year. Every model shipped in that window, every reported metric, every "we improved fraud catch by 12%" claim is now suspect. Three of those models are making production decisions right now.

⏸ Stop here and ask the room: you found it. What are the first three things you do, and who do you tell?

Run it — facilitator script

Timing: 2 min story · 10 min questions · 3 min reveal · 5 min transfer.

Do you turn the models off?

Listen for: A risk-based answer — for each contaminated model, compare it against the realistic fallback (the previous model, a rules engine, human review); contamination usually means overrated, not worthless, so the call is per-model, made against clean re-evaluation numbers, with monitoring tightened in the meantime. Weak signal: A reflexive "kill them all" or "leave them running" — either answer given without asking what would replace the models or what their clean-data performance actually is.

How do you quantify the real damage?

Listen for: Re-evaluate every affected model on clean out-of-time data, recompute each headline metric on that basis, and diff the decisions the contaminated models actually made against what the clean baseline would have decided — that diff is the damage. Weak signal: "Re-run the numbers" without specifying clean, held-out, post-period data — re-running against the same contaminated cache just reproduces the lie with more confidence.

What do you say to leadership — and to the client whose numbers you reported?

Listen for: Incident discipline — declare a severity, notify with the known/unknown/next-steps structure, commit to re-stated metrics by a date; the client conversation is treated as owed, not optional, because the reported 12% was an input to their decisions. Weak signal: "Wait until we know everything before saying anything" — the delay that quietly becomes the coverup.

What does the quiet-fix instinct cost?

Listen for: The insight that discovery is survivable and concealment isn't — a contamination found and disclosed is an engineering incident; a contamination found, hidden, and later discovered is an integrity scandal that voids trust in every number the team has ever reported. Plus the internal cost: engineers watching a quiet fix learn that surfacing problems is punished. Weak signal: Framing the quiet fix as pragmatic — "we fixed it, no harm done" — without pricing the asymmetry between correcting a metric and being caught having known.

The reveal

(Discussion, not a twist.) The honest path: treat it as a full incident — severity, comms, timeline — re-evaluate on clean out-of-time data, and re-state the metrics. Usually the models are less good but not worthless; the coverup, not the contamination, is what destroys trust.

Why this happens — the mechanics

Shared feature caches exist for good reasons: computing features once and reusing them everywhere saves enormous compute and keeps teams consistent. But train/eval separation is a property of the training process, not of the data — the cache has no idea which rows will later serve as someone's evaluation period. The moment a cache is shared across teams and time, every consumer inherits whatever leakage its construction allowed, and one subtle flaw contaminates a year of downstream work without any single team doing anything wrong.

The organizational mechanics are what stretch it to a year. Inflated metrics look like success, and success is not a symptom anyone investigates — the failure mode actively rewards the people inside it. Reported numbers ratchet: once "fraud catch up 12%" has gone into a leadership deck and a client report, it becomes a baseline with constituents, and re-opening it has a political price. Meanwhile the checking cadence is annual (audit) rather than continuous (CI — Continuous Integration, the automated pipeline that tests every change), so the detection latency is built in.

It's invisible for the same reason it's seductive: nothing is broken. Pipelines run, models ship, metrics climb. The only observable symptom — offline numbers persistently rosier than production reality — is routinely absorbed as "drift" or "the market." That's why the fix is structural: contamination checks on every training run, so the gap between train and eval is a machine-enforced invariant rather than an annual archaeology project.

Diagrams

Problem — how the failure unfolds:

timeline
    title A year of contamination
    section Quarter 1
        Cache built : Shared feature cache ships : Eval rows leak in (silent)
    section Quarters 2-3
        Models shipped : Every model trains on the future : Three make production decisions
    section Quarter 4
        Metrics reported : Inflated wins go to leadership : 12% fraud-catch claim to client
    section One year in
        Audit finds the leak : Every shipped model suspect : Every reported metric suspect

Solution — where the guardrails go:

flowchart TD
    A["Shared feature cache feeds<br/>training run"] --> B["Contamination check in CI<br/>on every run"]
    B --> C["Train and eval row overlap<br/>detected"]
    C --> D["Build blocked before<br/>training starts"]
    C -.-> E["Alarm fires: leaked rows<br/>identified same day"]
    D --> F["Re-evaluate on clean out-<br/>of-time data"]
    F --> G["Metrics re-stated,<br/>incident disclosed"]

What good looks like

The lesson

Correctness failures deserve the same incident machinery as outages: declared severity, honest disclosure, remediation, postmortem. And eval hygiene belongs in CI — contamination checks on every training run, not annual audits.

Named concepts: correctness incidents, blameless disclosure, eval-as-CI, out-of-time validation.

Real-world echoes

Corporate versions of this incident essentially never go public under their own names — they surface, if at all, as quietly revised numbers. The closest public analogue is academic: researchers studying machine-learning-based science have documented leakage as a leading cause of results that later had to be walked back across dozens of fields. The corporate silence is the point — you will not get to learn this one from someone else's postmortem.

Transfer

If our headline metric were wrong for a year, how would we find out? What contamination check runs automatically today?

Make it a ticket: add a train/eval row-overlap check to the CI of our most important model's training pipeline, failing the build on overlap — and dry-run the correctness-incident comms template against a hypothetical while nothing is on fire.

Related