A dry run only counts if staging matches.
The dry run went well, then production differed in ways the rehearsal couldn't see. A permission the test user had, a flag only on in staging, seed data cleaner than any customer. Check that staging matches before you trust what it taught you.

A dry run counts only after the TWIMCO Staging Parity Checklist passes: data shape, permissions, feature flags, integrations, and seed fixtures, each with an owner and a pass or fail. A green staging environment that differs on any of those rows is a different product. Do not treat its rehearsal as evidence about production.
Staging can be a polite fiction
The dry run went well. The script finished. People clapped, or at least nobody filed an incident. Then production differed in a way the rehearsal could not see: a permission the test user had, a flag that was on only in staging, a stub where a partner API should have been, a seed row that was cleaner than any real customer. The dry run did not fail. It answered a question nobody was asking.
Parity is the decision that the rehearsal environment is close enough, on the rows that can change the result, to teach you something about the environment you will actually run. It is not a claim that staging is a perfect copy. Perfect copies are expensive and often illegal to hold. Parity is a named list, an owner per row, and a pass or fail you are willing to say out loud before the clock starts.
This note is the TWIMCO Staging Parity Checklist. It is not a cutover runbook, not a dual-write plan, and not a tabletop of timed injects. Those are about the night you switch. This checklist is about whether the rehearsal beforehand is allowed to count. If it is not allowed to count, you may still run it. You may not call it evidence.
Spin:Market is software and hardware in one operation, with control that has to survive contact with a real floor. A dry run there, or in any product with permissions and integrations, is only as honest as the environment under it. Building that environment is web application work when the gaps are product gaps, not a mood about “being more careful.” If you are still framing what the product is supposed to do, the live custom product build brief is a separate instrument. It does not replace this checklist, and this checklist is not a published interactive tool. Copy the rows.
Do the checklist against a specific release candidate and a specific production target. “Staging” as a permanent place drifts. The checklist is for a pair: this build, that production, on this date. When either side moves, the prior pass expires.
Five rows you do not get to skip
Each row on the TWIMCO Staging Parity Checklist has the same shape: the thing being compared, how you will tell it matches, the owner who may mark pass or fail, the evidence, and what a fail blocks. A row without an owner is a wish.
Data shape. Do the records you will touch have the same fields, the same requiredness, and the same awkward nulls you will meet in production? Volume need not match. Shape does. A staging database full of short, complete rows will hide the bug that lives in the long, partial ones. Name the entities in this release, not “the data.” For each, say what “same shape” means: schema, a sample of real anonymized rows, or a contract you already trust. If you cannot use production-like rows, write what you used instead, and do not pretend it was the same.
Permissions. The dry-run identities must match the roles that will act, including the role that is not allowed to act. A superuser rehearsal proves that a superuser can finish. It does not prove the operator can. List the roles in the script. Fail the row if any of them is broader in staging than in production, or narrower in a way that blocks a step production would allow. Both directions lie.
Feature flags. Write the flag state for this release in both places. A flag on in staging and off in production means you rehearsed a different product. A flag off in staging and on in production means you did not rehearse the product you will ship. “We will turn it on later” is a fail until the dry run is repeated or the scope of the dry run is explicitly reduced to the flags you actually matched.
Integrations. For each system the release calls, say whether staging calls the real dependency, a faithful sandbox, or a stub. Stubs are allowed. Hidden stubs are not. A stub passes this row only if the checklist says what the stub cannot teach you, and the dry run’s claim is narrowed to exclude that lesson. Payment, identity, messaging, and device or hardware edges are the usual liars. Name the ones this release uses.
Seed fixtures. The rows, files, or device states the script assumes must be listed. Who loads them, how they are reset, and which of them could not exist in production. A fixture that skips a validation production enforces fails the row. A fixture that includes an exception you care about is a pass only if production can contain that same exception shape.
You may add rows. You may not delete these five by calling them obvious. Obvious rows are the ones that silently differ.
How the work moves
Rows that decide whether the dry run counts
- Data shape
Fields, requiredness, and awkward nulls for the entities this release touches.
- Permissions
The roles in the script, no broader and no narrower than production.
- Feature flags
The same flag state in both places, or the claim gets smaller.
- Integrations
Real, faithful sandbox, or a named stub with a narrowed lesson.
- Seed fixtures
What the script assumes, who loads it, and what production could not contain.
A dry run against a different product is a rehearsal of the wrong system.
Pass, fail, and the person on the row
Mark each row pass or fail. Do not mark “partial” and continue as if that were a pass. Partial means you have not decided what the dry run is allowed to prove. Split the row or fail it.
The owner is the role who can actually inspect the row, not the person who wants the dry run to proceed. Engineering owns data shape and flags when those live in code and config. The operator’s lead owns permissions when production access is theirs to grant. The integration owner owns the sandbox-versus-stub call. If two people must agree, the row stays fail until both have signed, and the checklist names both.
A fail blocks the claim, not necessarily the exercise. You can run a rehearsal against a known gap if the invitation says what this run will not prove. You cannot, the next morning, describe it as a successful dry run of the release. The sentence you are allowed to say should be written at the bottom of the checklist before you start: “This run may speak about X. It may not speak about Y.”
Expiry matters. A pass on Monday does not survive a flag change on Tuesday, a permissions ticket, or a migration. Put a date on the checklist and the build identifier. If you cannot name the build, you do not have a pass. You have a memory of a good afternoon.
Disagreement between the person running the script and the owner of a row resolves toward fail until the evidence is rechecked. Optimism is how parity rot gets into the readout. The checklist is short on purpose so that rechecking is cheaper than arguing.
Store the filled checklist with the release notes. When an incident later looks like something staging would have caught, you should be able to see whether the row was passed, failed, or narrowed. If the row did not exist, add it for the next release. That is how the checklist becomes yours rather than a generic prompt.
What a counted dry run is allowed to prove
Even a passed checklist does not prove production will behave. It proves you did not ignore the five usual lies. Say that plainly so nobody promotes the rehearsal into a guarantee.
A counted dry run can support claims like: this script completes for these roles, against this data shape, with these flags, talking to these named dependencies, from these fixtures. It cannot support claims about load, about rare data you did not seed, about a dependency you stubbed, or about a flag you did not match. Load is a different test. Rare data is either in the fixture list or outside the claim.
Watch for these composites. They are patterns from delivery, not client metrics.
The test user is an admin. Every step worked. The real role cannot see the control the script used. The permissions row was never filled because “we are all admins in staging.”
The happy fixture is the only fixture. The script never met a partial record, a stale foreign key, or a device in the state the floor actually leaves behind. Data shape passed on a migration diff and failed the moment a real row arrived. Schema parity is necessary and not sufficient if the script’s claim includes “we tried realistic records.”
The partner sandbox is a stub that always says yes. The integration row said “sandbox” because that sounded better. The first real no, or the first real timeout, is in production. If the sandbox cannot say no, call it a stub and narrow the claim.
The flag of interest was flipped for the demo and flipped back afterward, and the checklist still said pass. Flag state is part of the build you rehearsed. If you change it, you have a new pair, and the old pass is void.
None of these is a measured rate. They are reasons the row exists. If you recognize one, fail the row and rewrite the sentence the dry run is allowed to say. That is a successful use of the checklist, not an embarrassment to hide so the schedule stays pretty.
Sequence of work
From a filled checklist to a claim you may say
- Name the pair
This build, that production, this date. A prior pass does not carry over.
- Mark the rows
Pass or fail, with an owner who can inspect, not a partial that acts like a pass.
- Narrow the sentence
Write what this run may prove and what a stub or a gap keeps offstage.
- Run or refuse
A fail blocks the claim. It does not have to block a clearly labeled exercise.
- File it
Keep the checklist with the release so a later incident can see the row.
Put this into practice
- Name the release candidate and the production target. Date the TWIMCO Staging Parity Checklist.
- Fill the five rows: data shape, permissions, feature flags, integrations, seed fixtures. Add rows you have been burned by. Do not drop the five.
- Assign an owner who can inspect the row. Mark pass or fail. Write the sentence this run may say, and the sentence it may not.
- If a row fails, either fix it and recheck or narrow the claim before anyone calls the run evidence.
- When the gaps are product gaps, in roles, flags, or the way a web application talks to the systems around it, take the checklist into scoping. Spin:Market is the reminder that a rehearsal only helps when it is aimed at the operation you actually run.
A finished script is not a passed checklist. The checklist is what makes the script about the right system.
We build alongside the people doing the work.
Bring us the problem you’re thinking about.