Design a system which can handle a compaign where we are suppose to sell coupons for 6M burgers within 10 min.
Let's look into FR
FR
1.Users can claim a burger coupon via a website, app, or SMS.
2.Each coupon has a unique code for tracking.
3.Coupons can be redeemed at participating restaurants.
4.Coupons should be distributed within 10 minutes without delays.
5.Users should receive a confirmation message (SMS, email, app notification) upon successful claim.
6.Alert users if coupons run out.
7.Dashboard to monitor live coupon claims per second.
8.Each user should receive exactly one coupon (idempotency and deduplication).
NFR
1.The system should be highly scalable to handle millions of concurrent users.
2.System should be highly available
3.Eventual consistency is acceptable for displaying remaining coupon count, but strong consistency for coupon assignment.
4.Race conditions should be avoided when multiple users claim the last few coupons.
5.Coupon claim should be processed within < 100ms.
Estimates
Number of sensors=10M
Data collection rate= every 10 seconds = 6 reading per minute
each reading size=200 bytes
Write QPS= 10M/10=1M/sec
Storage
Each coupon entry contains:
Coupon ID (UUID, 16 bytes)
User ID (Email/Phone, 50 bytes)
Timestamp (8 bytes)
Status (1 byte)
Metadata (Campaign ID, Source, etc., ~25 bytes)
Total per Coupon Entry = ~100 bytes
Write QPS= 10M/10=1M/sec
Size=200bytes*1M=200MB*10^5 = 20 TB per day
Delta compression can be used to store the data
API’s
1.POST /api/v1/auth/login
request {
"email": "user@example.com",
"password": "securepassword"
}
response {
"token": "jwt-token",
"expires_in": 3600
}
2.GET /api/v1/coupons/availability
{
"available_coupons": 1250000
}
3.POST /api/v1/coupons/claim
request {
"user_id": "abc123",
"campaign_id": "burger_festival_2025"
}
response {
"message": "Coupon successfully claimed!",
"coupon_code": "BURGER-XYZ-123",
"expires_at": "2025-06-30T23:59:59Z"
}
4.GET /api/v1/coupons/validate/{coupon_code}
request {
"coupon_code": "BURGER-XYZ-123",
"status": "valid",
"expires_at": "2025-06-30T23:59:59Z"
}
response {
"error": "Coupon is invalid or expired."
}
5.GET /api/v1/users/{user_id}/coupons
Show users the coupons they have claimed.
[
{
"coupon_code": "BURGER-XYZ-123",
"claimed_at": "2025-02-06T12:30:45Z",
"expires_at": "2025-06-30T23:59:59Z"
}
]
6.GET /api/v1/admin/coupons/stats
{
"total_claimed": 4500000,
"remaining": 1500000
}
Databases
1️⃣ Coupons Table (Cassandra/DynamoDB)
🔹 Stores all issued coupons with user assignments.
🔹 Partition by campaign for efficient lookups.
CREATE TABLE coupons (
campaign_id TEXT, -- Unique Campaign ID
coupon_code TEXT, -- Unique Coupon Code
user_id TEXT, -- User who claimed the coupon (NULL if not claimed)
status TEXT, -- ('available', 'claimed', 'redeemed', 'expired')
claimed_at TIMESTAMP, -- Timestamp when the coupon was claimed
expires_at TIMESTAMP, -- Expiry date of the coupon
PRIMARY KEY ((campaign_id), coupon_code)
);
2️⃣ Users Table (Optional, PostgreSQL/MySQL)
🔹 Stores user information if authentication is required.
CREATE TABLE users (
user_id TEXT PRIMARY KEY,
email TEXT UNIQUE,
phone TEXT UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Claimed Coupons Table (For Quick Lookups)
🔹 Stores only claimed coupons for quick retrieval.
🔹 Useful for querying a user’s claimed coupons.
CREATE TABLE claimed_coupons (
user_id TEXT,
coupon_code TEXT,
campaign_id TEXT,
claimed_at TIMESTAMP,
PRIMARY KEY ((user_id), claimed_at)
) WITH CLUSTERING ORDER BY (claimed_at DESC);
🔹 Why This Schema?
✅ Partitioned by user_id → Fast retrieval of all claimed coupons by a user.
✅ Sorted by claim time → Allows easy retrieval of latest claims.
4️⃣ Campaigns Table
🔹 Stores metadata about each coupon campaign.
CREATE TABLE campaigns (
campaign_id TEXT PRIMARY KEY,
name TEXT,
total_coupons INT,
available_coupons INT, -- Cached in Redis for real-time tracking
start_time TIMESTAMP,
end_time TIMESTAMP
);
🔹 Why This Schema?
✅ Tracks available coupons (can sync with Redis).
✅ Enables admin to monitor the campaign progress.
5️⃣ Coupon Redemption Table
🔹 Tracks when coupons are used
CREATE TABLE coupon_redemptions (
coupon_code TEXT PRIMARY KEY,
user_id TEXT,
redeemed_at TIMESTAMP
);
Since the data set is huge we can use delta compression technique to store data
What is delta compression technique?
Delta compression is a data storage and transmission technique where only the differences (deltas) between successive versions of data are stored, rather than the full copies. This reduces storage size and improves efficiency in update-heavy systems.
🛠️ How Delta Compression Works?
Base Version: Store the initial full version of the data.
Change Detection: Identify the differences (deltas) between a new version and the previous version.
Store Deltas: Instead of saving the entire new version, store only the changes.
Reconstructing Data: When required, apply the deltas sequentially to reconstruct the latest version.
🔹 Advantages of Delta Compression
✅ Reduced Storage Costs – Stores only changes, not full copies.
✅ Faster Data Transmission – Smaller updates lead to lower bandwidth usage.
✅ Efficient Versioning – Ideal for time-series data & logs.
✅ Optimized Backups – Less storage overhead for incremental backups.
Each row stores the entire temperature value.
This consumes more storage over time.
Instead of storing full values, we store only changes relative to the previous value.
When retrieving data, we reconstruct values as:
25.5 + 0.1 = 25.6
25.6 + 0.1 = 25.7
25.7 + 0.2 = 25.9
25.9 + 0.1 = 26.0
Why have we used Cassandra or Dynamo Db. Can you explain