Web › Module 6 › Lesson 2
Limit Overrun & Multi-endpoint Races
Parallel requests that overspend limits, and races across multiple endpoints
Opening
The counter that could not count
Single-endpoint races hit one URL hard in parallel. Multi-endpoint races align windows across related URLs (add to cart → pay → confirm) so shared state is inconsistent mid-flow.
1. Limit overrun races
If the server does “read remaining uses → if > 0 grant → decrement,” two parallel requests can both see remaining=1. Database unique constraints or atomic UPDATE … WHERE remaining > 0 RETURNING are safer than check-then-act in app code.
Unsafe pattern (pseudo)remaining = db.get(user.coupon_uses) if remaining > 0: apply_discount() db.set(user.coupon_uses, remaining - 1) # race window here
remaining = db.get(user.coupon_uses)
if remaining > 0:
apply_discount()
db.set(user.coupon_uses, remaining - 1) # race window here2. Multi-endpoint races
Align timing so request A finishes a check while request B mutates related state. Example: change email while a password-reset token for the old email is still valid. Connection warming (sending harmless requests first) can reduce jitter so the race window is easier to hit in labs.
3. Session locks & partial construction
Per-session locks
Some apps lock one session but allow a second session/cookie to race the same account.
Partial construction
Objects created in step 1 may be usable before step 2 finishes (incomplete user with admin role briefly).
Time-sensitive attacks
OTP codes, password resets, and short-lived tokens amplify race impact.
Defense checklist
Prefer DB constraints, idempotency keys, serializable transactions, and server-side queues for critical actions.
Knowledge Check
A strong fix for one-time coupon races is:
Multiple choice