Prompt: Design a coupon service for an e-commerce platform: create coupons (percentage/fixed, with usage limits and expiry), validate and redeem them at checkout, and prevent abuse (a “one per user” or “first 1000 uses” coupon must be honored exactly). Attempt cold for 45 minutes first.
Tests: redemption limits under concurrency (the oversell problem again), validation on a hot path, abuse prevention. Reuses ticketing / e-commerce reservation patterns.
Millions of validations/day (every checkout checks a coupon), far fewer redemptions. A viral coupon → a spike of concurrent redemptions on one coupon → contention (a hot key).
Split the two operations:
UPDATE coupons SET used = used + 1 WHERE id = ? AND used < total_limit (and check/insert a per-user
redemption row). The DB serializes it; if 0 rows affected, the coupon is exhausted. This is the same
reserve/decrement under concurrency pattern as inventory oversell.flowchart LR
Checkout --> Validate{Valid & eligible?}
Validate -- yes --> Redeem[Atomic consume:<br/>used < limit AND per-user check]
Redeem -- success --> Apply[Apply discount]
Redeem -- exhausted --> Reject
used = 1000 and fails. Never read-then-write without atomicity. For extreme contention
on one hot coupon, shard the counter (1000 = 10 buckets of 100) and decrement a random bucket, reconciling
totals. (Hot Keys)(coupon_id, user_id) in a redemptions table — the DB rejects
a second redemption atomically. Also gives idempotency (a retried redeem for the same user/coupon/order
doesn’t double-consume).| Decision | Chosen | Why | | — | — | — | | Validate vs redeem | Split: cached validate, atomic redeem | Fast hot-path reads; correctness at consume | | Limit enforcement | Atomic conditional increment | Honors limits exactly under concurrency | | Per-user limit | Unique constraint on (coupon,user) | DB enforces atomically; gives idempotency | | Hot coupon | Sharded counter | Spread contention on a viral code |
Recognizing this is the oversell problem in disguise → atomic conditional consume, per-user uniqueness constraint, idempotency keyed on (coupon,user,order), the validate/redeem consistency split, and hot-coupon counter sharding + abuse controls. A weak answer reads the count then increments separately — races let a coupon exceed its limit.