Video

What Is a Race Condition? Lost Updates Explained with Rails

Two customers withdraw from the same account at the same moment. The balance starts at $1,000, one takes $200, the other takes $300 — and the account ends up at $700 instead of $500. One withdrawal just vanished.

That's a lost update, and it's the clearest example of a race condition there is. This video follows those exact two requests from the bug all the way to the fix, using one Ruby on Rails banking example the whole way through.

You'll see why it happens: reading the balance and writing it back are two separate operations, and another request can slip in between them. Both requests read $1,000 before either one saves, so the second write overwrites the first. The arithmetic was never wrong — the coordination was.

Then the fix. Active Record's with_lock runs the update inside a transaction while holding a row-level lock, so Request B waits for Request A to finish and then reads the updated $800 instead of the stale $1,000. Both withdrawals land. Final balance $500.

It ends honestly. Locks cost something: requests wait, contention hurts throughput, and badly scoped transactions can deadlock. Row-level locking is also not the only answer — atomic database updates, isolation levels and optimistic locking all have a place. Pick the strategy that fits the operation.

CHAPTERS
0:00 — Two requests, one wrong balance
0:10 — How the update gets lost
0:25 — What a race condition actually is
0:40 — The execution order, step by step
1:00 — Fixing it with with_lock in Rails
1:25 — What locking costs you
1:45 — The takeaway

— #Astmation — #software #systems, #automation, and #AI-powered #applications. Build. Automate. Evolve. https://astmation.com/


Watch on YouTube

Back to videos