Reproducing race conditions
Makes timing-sensitive failures repeatable by controlling the moments where requests, transactions or asynchronous results overlap.
concurrency-timing-reproduction
Team members using this skill
When is it useful?
Use it when a reported duplicate, deadlock or stale overwrite disappears during ordinary debugging.
What does it help you do?
- Uses barriers instead of guessed sleeps to expose races.
- Controls completion order to reveal stale-state overwrites.
- Recreates conflicting locks and expired worker leases.
Try asking this
Reproduce two requests both claiming the last available seat. Pause both requests immediately after their availability check, then release them together. Record the winning write and the rejected competing request.
Detailed documentation
Read the skill’s original instructions, examples and checks in their authored language.
Show less
Concurrency & Timing Reproduction
When to Use
Use when a bug occurs "only sometimes," under rapid double-clicks, parallel webhook deliveries, concurrent worker jobs, async stream cancellations, or database transaction contention.
Replace Random sleep() Guessing with Deterministic Interleaving
A race condition happens when Operation $A$ and Operation $B$ overlap in a critical window $[t_1, t_2]$. Using random setTimeout delays makes tests slow and flaky. Instead, widen or control the critical window deterministically:
1. Check-Then-Act (TOCTOU) & Double-Submission Races
Scenario: Two concurrent requests pass the if (!exists) or if (balance >= amount) check before either writes its update.
- Deterministic Barrier Technique:
- Launch Request $A$ and Request $B$ concurrently (
Promise.all([reqA(), reqB()])). - Where supported by test hooks or mock/spy wrappers around the I/O step between the read check and the write commit, pause both fibers at a shared Latch / Barrier until both have completed the read check, then release both to execute the write simultaneously.
- Assert that the invariant (e.g., duplicate record created, negative balance, lost update, or unhandled unique-constraint
500crash) is triggered 100% of the time.
- Launch Request $A$ and Request $B$ concurrently (
2. Async Completion Ordering & Stale-State Overwrites
Scenario: Operation $A$ starts before Operation $B$, but $A$ finishes after $B$ and overwrites newer state with stale data.
- Controlled Deferred Resolution:
- Intercept the underlying network/storage promise for call $A$ and call $B$ using controllable
Deferredpromises:const callA = createDeferred(); const callB = createDeferred(); // Trigger A, then trigger B // Resolve B first: callB.resolve(freshData); // Resolve A second: callA.resolve(staleData); - This reproduces out-of-order async bugs in
< 10mswith 100% determinism.
- Intercept the underlying network/storage promise for call $A$ and call $B$ using controllable
3. Database Lock Contention, Deadlocks & Queue Leases
- Deadlock Reproduction ($A \to B$ vs. $B \to A$): Open two concurrent transactions; Transaction 1 locks Row $X$, Transaction 2 locks Row $Y$, then Transaction 1 requests Row $Y$ while Transaction 2 requests Row $X$.
- Queue Stalled-Lock Expiry: Configure a short lease/visibility timeout in the test (e.g.,
100ms) while a worker job is held on a250msbarrier, proving a second worker picks up the in-flight job concurrently.
4. Bounded Stress Harness for Native / Multi-Threaded Races
When fine-grained promise interception is impossible (e.g., OS filesystem races, multi-process SQLite SQLITE_BUSY, Rust thread races):
- Use tools like
loom(for Rust atomics/mutexes) or a bounded parallel worker burst (N = 20–50concurrent operations over a tight loop with a hard timeout), recording the exact failure ratio (k / Nruns).
Included files 1
SKILL.md
