← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

Race Condition

Concurrency Intermediate
debt(d9/e5/b5/t7)
d9 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'silent in production until users hit it' (d9). Semgrep patterns can catch some file read-modify-write patterns, but most race conditions are timing-dependent and surface only under load. Intermittent and hard to reproduce.

e5 Effort Remediation debt — work required to fix once spotted

Closest to 'touches multiple files / significant refactor in one component' (e5). Quick_fix suggests swapping to flock(), atomic UPDATE, SELECT FOR UPDATE, or Redis INCR — each fix is localized but identifying every read-modify-write site and adding proper locking typically spans multiple call sites in a component.

b5 Burden Structural debt — long-term weight of choosing wrong

Closest to 'persistent productivity tax' (b5). Applies across web/cli/queue contexts; once concurrency is in play, every shared-state operation must be reasoned about for atomicity, slowing many work streams.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7). The misconception (PHP is single-threaded therefore race-free) directly contradicts the PHP-FPM reality of concurrent processes sharing files/DB/cache. Developers coming from a single-request mental model guess wrong systematically.

About DEBT scoring →

TL;DR

A race condition occurs when the outcome of a program depends on the relative timing of concurrent operations — two threads reading and writing shared state without coordination.

Explanation

Race conditions arise when multiple threads/processes access shared mutable state without synchronisation. Classic example: two threads both read a counter (value: 5), both increment locally, both write (both write 6 instead of 7). The TOCTOU (Time-Of-Check-To-Time-Of-Use) variant: check a condition then act on it, but state changes between check and act. In PHP: race conditions occur in file-based counters (read→increment→write without locks), cache stampede (multiple processes regenerating expired cache simultaneously), and database reads without transactions. Prevention: atomic operations, mutexes/locks, database transactions, optimistic locking.

Common Misconception

Race conditions only happen in multi-threaded languages — PHP-FPM runs many processes concurrently, all sharing files, databases, and caches. Race conditions are very real in PHP.

Why It Matters

Race conditions cause intermittent data corruption that's extremely hard to reproduce and debug — they typically surface under load when multiple requests hit the same code path simultaneously.

Common Mistakes

  • File-based counters without flock() — classic race condition.
  • Cache aside pattern without stampede protection.
  • Check-then-act on database records without SELECT FOR UPDATE.
  • Assuming single-threaded PHP is race-condition-free.

Code Examples

✗ Vulnerable
// Race condition — read/increment/write without lock:
$count = (int)file_get_contents('counter.txt');
$count++;
file_put_contents('counter.txt', $count);
// Two simultaneous requests both read 5, both write 6
✓ Fixed
// File lock prevents race:
$fp = fopen('counter.txt', 'c+');
if (flock($fp, LOCK_EX)) {
    $count = (int)stream_get_contents($fp);
    $count++;
    ftruncate($fp, 0); rewind($fp);
    fwrite($fp, $count);
    flock($fp, LOCK_UN);
}
fclose($fp);

// Better: use atomic DB increment:
$pdo->exec('UPDATE counters SET value = value + 1 WHERE id = 1');

Added 23 Mar 2026
Views 93
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings W 1 ping T 0 pings F 0 pings S 0 pings S 1 ping M 0 pings T 0 pings W 2 pings T 4 pings F 5 pings S 13 pings S 9 pings M 0 pings T 0 pings W 0 pings T 0 pings F 2 pings S 0 pings S 0 pings M 1 ping T 1 ping W 0 pings T 1 ping F 1 ping S 0 pings S 0 pings M 1 ping T 0 pings W
No pings yet today
Bing 1
Scrapy 32 Perplexity 12 Amazonbot 8 Ahrefs 4 Google 4 SEMrush 4 Unknown AI 3 Claude 1 Meta AI 1 PetalBot 1 Bing 1
crawler 69 crawler_json 1 pre-tracking 1
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Medium
⚡ Quick Fix
Use flock() for file operations. Use DB atomic increments (UPDATE SET col = col + 1). Use SELECT FOR UPDATE for read-modify-write DB patterns. Use Redis INCR for counters.
📦 Applies To
web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
file_get_contents.*file_put_contents|read.*increment.*write
Auto-detectable: ✗ No semgrep
⚠ Related Problems
🤖 AI Agent
Confidence: Low False Positives: High ✗ Manual fix Fix: High Context: Function Tests: Update
CWE-362 CWE-367


✓ schema.org compliant