MongoDB
Designing a Coupon and Discount System
Build a promotional engine that handles coupon codes, percentage discounts, flash sales, and anti-abuse mechanisms at scale.
S
srikanthtelkalapally888@gmail.com
Designing a Coupon and Discount System
A promotional system manages discount codes, flash sales, and loyalty rewards without abuse or race conditions.
Coupon Types
Percentage discount: 20% off entire order
Fixed amount: $10 off orders > $50
Free shipping: Waive delivery fee
BOGO: Buy one get one free
Flash sale: 50% off for 2 hours
Loyalty points: 1 point per $1 spent
Data Model
coupons(
code VARCHAR UNIQUE,
type ENUM('percent', 'fixed', 'shipping'),
value DECIMAL,
min_order DECIMAL,
max_uses INT,
used_count INT,
user_limit INT, -- uses per user
valid_from TIMESTAMP,
valid_until TIMESTAMP,
product_ids UUID[] -- restrict to products
)
coupon_usages(coupon_code, user_id, order_id, used_at)
Validation Flow
User applies coupon_code:
1. Does coupon exist and is active?
2. Not expired (valid_from ≤ now ≤ valid_until)?
3. Usage limit not reached (used_count < max_uses)?
4. User hasn't exceeded per-user limit?
5. Minimum order value met?
6. Applicable to cart items?
→ Apply discount
Race Condition Prevention
Flash coupons with 1000 uses available — 50K simultaneous requests.
-- Redis Lua script (atomic)
local current = redis.call('INCR', 'coupon:FLASH50:count')
if current > 1000 then
redis.call('DECR', 'coupon:FLASH50:count')
return 0 -- rejected
end
return 1 -- accepted
Sync Redis counter to DB asynchronously.
Anti-Abuse
- One code per email/device fingerprint
- Rate limit coupon validation attempts
- Flag accounts creating multiple emails
- Velocity checks: >5 coupons in 1 hour = suspicious
Flash Sale Architecture
Scheduler triggers at sale start time
↓
Update product prices in Redis
↓
Invalidate product cache
↓
Push notification to users
Conclusion
Coupon systems require atomic counters (Redis) for race-free usage tracking, validation pipelines for anti-abuse, and scheduled systems for flash sales.