Core · 03/05 7 min
Concurrency, retries & idempotency
Race conditions, idempotency keys, backoff with jitter: the 'production' bugs.
Check-then-act races
const seat = await Seat.findById(id);
if (!seat.booked) { seat.booked = true; await seat.save(); } // two requests can both pass the check
Make the check and the write one atomic operation:
const r = await Seat.updateOne({ _id: id, booked: false }, { $set: { booked: true } });
if (r.modifiedCount === 0) return res.status(409).json({ error: "already booked" });
Idempotency keys
Clients retry. A payment endpoint must not charge twice. Store the result under the client's Idempotency-Key; a repeated key returns the stored response instead of re-executing.
Retries
- Only retry transient failures (timeouts, 503, 429), never 400s.
- Exponential backoff:
base * 2^attempt, capped. - Jitter (random spread) stops every client retrying in lock-step.
- Always cap attempts; surface the last error.
Rate limiting
Fixed window is simple but bursty at boundaries; sliding window or token bucket smooths it. Key by user or IP, return 429 with Retry-After.
Practise it now
Next in Core
DSA pattern cheat sheet