A bug where two operations run at almost the same instant and interfere, producing a result impossible if they'd run one after the other.
Why it exists
Software serves many people at once, so two requests can touch the same row in the same instant. The ordinary pattern of read a value, decide based on it, then write it back is safe on its own, but when two requests overlap, both can read the old value before either writes, and each acts as if it were alone. Race condition is the name for that overlap, and the concept matters because the last pack in stock, a wallet balance, or a booked seat can be handed to two people at once when nothing guards the gap between the read and the write.
How it actually works
One Kacchi pack left. Two customers press Buy within the same 50 milliseconds. Each request reads stock ("1 available"), checks it's above zero, charges, and subtracts one. But request B reads "1" before request A has written its update. Both checks pass. Both get charged. Stock is now -1.
Nothing in either request was wrong; the bug lives in the tiny gap between reading a value and updating it, a gap that only matters when two requests land inside it at once. This is why races are nasty: a single tester can never trigger one, so they appear only under real concurrent load, usually in production at peak.
Press both buyers fast. Can the store sell the same last pack twice?
1pack left
No sales yet. Press a buyer.
Without guarding the gap between the read and the write, two overlapping requests both act on the old value.
Subtopics
A senior PM walks you through it
A junior PM, stuck
Ops reported that the last Kacchi pack in the Friday flash sale sold to two different customers, and the products table now shows stock at -1. When I asked how one pack became two orders, the dev said "classic race condition" and pasted fourteen log lines with millisecond timestamps. I can see two customers and a lot of near-identical lines, but I cannot follow how both of them got the same pack.
The dev is right, and the proof is in those milliseconds, which is why he pasted them instead of explaining. This is the checkout service logging two orders that landed on the same pack inside the same fifth of a second. The trick to reading it is to stop reading top to bottom and instead braid the two customers apart, because the bug is not in either order, it is in how they overlap. Here are the lines as he sent them, two users, one item, about three hundred milliseconds. Take the steps with me and watch the stock number.
Checkout service log, two overlapping orders, Friday flash sale 12:47
2026-03-06T12:47:03.101ZINFOcheckout POST /api/orders received user=u_88452 item=p_1042
2026-03-06T12:47:03.108ZINFOcheckout POST /api/orders received user=u_88617 item=p_1042
2026-03-06T12:47:03.413ZINFOcheckout order created o_5515 user=u_88617 total=649
Click a step to see the lines it points at.
Mistakes I've seen
Treating -1 as a data-entry error and just resetting stock to 0. The number is correct evidence of an oversell, and clearing it hides that a real customer is owed either a pack or a refund.
Trying to reproduce it by clicking Buy fast yourself. One person can never land two requests in the same millisecond, so it will always pass in your hands and look unreal in the bug report.
Asking to "add a check that stock is above zero." That check already runs and already passes for both orders, the log shows it, so the fix is closing the read-to-write gap, not adding another read.
Speccing "first 100 get the discount" without naming what happens at the boundary. Item 100 and item 101 arriving together is exactly this log with a coupon instead of a pack, so decide who wins before engineering has to ask.
Filing it as "checkout oversold" with no timestamps. "12:47:03, u_88452 and u_88617 both read stock=1 for p_1042 seven ms apart" points at these lines, while a one-line summary makes the engineer hunt for the overlap you already found.
Reply in the thread with: "Followed both orders. u_88452 and u_88617 hit p_1042 seven ms apart, both read stock=1, both passed the check, and both wrote, so we created o_5514 and o_5515 for one pack and stock landed at -1. One of them is owed a refund and checkout needs an atomic decrement so the second read cannot see a stale 1." You braided two overlapping requests apart and named the gap the bug lives in.
Where a PM meets this
Finance flags 40 double charges from flash-sale night: "race condition in checkout," fixed with idempotency and an atomic stock decrement.
When you spec "only the first 100 get the discount," engineering asks hard questions about user 100, because that boundary is exactly where races live.
Hear it in a meeting
"It's a race between the payment callback and the order-update job."