Design Online Bidding Services
Designing an online bidding system involves building a scalable, fault-tolerant, and user-friendly system where users can participate in auctions by placing bids on items.
FR
1.Users can sign up as a bidder, seller, or admin by providing necessary details (e.g., username, email, password).
2.Sellers can create auctions with details like title, description, starting price, reserve price, start time, and end time.
3.Users can browse active, upcoming, and completed auctions.
4.Bidders can place bids on active auctions.The system validates that the bid is higher than the current price and complies with increment rules.
5.Notify users about being outbid,auction start end,winning an auction/cancellation
6.: Winners can pay for items via integrated payment gateways
7.Reports and analytics(iew past bids, ongoing auctions, and won auctions.)
8..User can cancel their bid until certain time ,if it is cancelled current bid should go to next higher bidder
NFR
1.System should be highly scalable to support a growing number of users and auctions with low latency.
2.System should be highly available for auction
Estimates
User Base:
Total users: 100M
Active users: 10M
Concurrent users: 10% of active users (1M).
Auctions:
Active auctions at any given time: 1M
Bids per auction: ~50 on average.
Peak bids per auction: 200.
Average auction duration: 7 days.
Storage
Storage for users=100M*1KB=100GB
Auction metadata=1M*2KB/auction=2GB
For notification Storage
10M*50bid/action*0.5KB/bid= 100GB*5*5/10=250GB
Read QPS
1M concurrent users query bid history or auction status every 10 seconds.
Read QPS=1M/10=100k QPS
API’s
1.POST /api/users/register
request
{
"username": "john_doe",
"email": "john.doe@example.com",
"password": "securepassword123"
}
response
{
"userId": 12345,
"message": "User registered successfully"
}
2.POST /api/users/login
request
{
"email": "john.doe@example.com",
"password": "securepassword123"
}
response
{
"token": "eyJhbGciOiJIUzI1...",
"userId": 12345,
"message": "Login successful"
}
3.GET /api/users/{userId}
to view user profile
{
"userId": 12345,
"username": "john_doe",
"email": "john.doe@example.com",
"registeredAuctions": [1001, 1002],
"wonAuctions": [2001]
}
4.POST /api/auctions
to create auction
request
{
"title": "iPhone 15 Pro Max",
"item _id":aedf4
"description": "Brand new sealed box",
"startingPrice": 1000,
"endTime": "2024-12-01T23:59:59Z"
"threshold price":12000
"start time": "2024-12-01T23:59:59Z"
"item_url":some url
}
response
{
"auctionId": 56789,
"message": "Auction created successfully"
}
5.GET /api/auctions/{auctionId}
View auction details
{
"auctionId": 56789,
"title": "iPhone 15 Pro Max",
"description": "Brand new sealed box",
"currentPrice": 1500,
"highestBidder": "john_doe",
"startTime": "2024-11-25T10:00:00Z",
"endTime": "2024-12-01T23:59:59Z",
"bids": [
{
"bidder": "alice",
"amount": 1200,
"timestamp": "2024-11-25T10:05:00Z"
},
{
"bidder": "john_doe",
"amount": 1500,
"timestamp": "2024-11-25T10:15:00Z"
}
]
}
6.GET /api/auctions/active
List all active auctions
[
{
"auctionId": 56789,
"title": "iPhone 15 Pro Max",
"currentPrice": 1500,
"endTime": "2024-12-01T23:59:59Z"
},
{
"auctionId": 56800,
"title": "MacBook Pro 2023",
"currentPrice": 2000,
"endTime": "2024-11-30T20:00:00Z"
}
]
7.POST /api/auctions/{auctionId}/bids
For placing bid
request
{
"userId": 12345,
"bidAmount": 1600
}
response
{
"bidId": 78901,
"message": "Bid placed successfully",
"currentPrice": 1600
}
8.GET /api/users/{userId}/bids
View user bids
[
{
"auctionId": 56789,
"title": "iPhone 15 Pro Max",
"bidAmount": 1600,
"bidTime": "2024-11-25T10:20:00Z",
"status": "Highest"
},
{
"auctionId": 56800,
"title": "MacBook Pro 2023",
"bidAmount": 2000,
"bidTime": "2024-11-25T10:25:00Z",
"status": "Outbid"
}
]
9.GET /api/users/{userId}/notifications
[
{
"message": "You are the highest bidder for auction 56789!",
"timestamp": "2024-11-25T10:20:00Z"
},
{
"message": "You have been outbid for auction 56800.",
"timestamp": "2024-11-25T10:25:00Z"
}
]
10.POST /api/admin/auctions/{auctionId}/end
End auction by admin
request
{
"adminId": 1
}
response {
"message": "Auction ended successfully",
"winner": "john_doe",
"winningBid": 1600
}
11.GET /api/admin/statistics
Fetch auction statistics
{
"totalUsers": 1000000,
"activeAuctions": 100000,
"completedAuctions": 500000,
"totalBids": 25000000
}
Databases
Users table
CREATE TABLE Users (
userId INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(255) UNIQUE NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
passwordHash VARCHAR(255) NOT NULL,
createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
2.Auction Table
CREATE TABLE Auctions (
auctionId INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(255) NOT NULL,
description TEXT,
startingPrice DECIMAL(10, 2) NOT NULL,
currentPrice DECIMAL(10, 2) DEFAULT NULL,
highestBidderId INT DEFAULT NULL,
startTime TIMESTAMP NOT NULL,
endTime TIMESTAMP NOT NULL,
isActive BOOLEAN DEFAULT TRUE,
createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (highestBidderId) REFERENCES Users(userId)
);
3.Bids Table
CREATE TABLE Bids (
bidId INT PRIMARY KEY AUTO_INCREMENT,
auctionId INT NOT NULL,
bidderId INT NOT NULL,
bidAmount DECIMAL(10, 2) NOT NULL,
bidTime TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (auctionId) REFERENCES Auctions(auctionId),
FOREIGN KEY (bidderId) REFERENCES Users(userId)
);
4.Notification table
CREATE TABLE Notifications (
notificationId INT PRIMARY KEY AUTO_INCREMENT,
userId INT NOT NULL,
message TEXT NOT NULL,
isRead BOOLEAN DEFAULT FALSE,
createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (userId) REFERENCES Users(userId)
);
5.Admins Table
CREATE TABLE Admins (
adminId INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(255) UNIQUE NOT NULL,
passwordHash VARCHAR(255) NOT NULL,
createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
6.For active auctions
using redis cache
Key: active_auction:<auctionId>
Value:
{
"title": "iPhone 15 Pro Max",
"currentPrice": 1500,
"highestBidder": "john_doe",
"endTime": "2024-12-01T23:59:59Z"
}
How to ensure no two users win the same item.?
Use Redis to acquire a lock on the auction ID before processing a bid.
The lock is released once the operation is completed.
Implementation:
Use Redis commands like SET key value NX PX timeout to create a lock.
Code Example
lock_key = f"auction:{auction_id}"
if redis.set(lock_key, user_id, nx=True, px=3000): # Acquire lock for 3 seconds
try:
# Process bid
finally:
redis.delete(lock_key) # Release lock
else:
# Handle lock contention
Pros:
Simple to implement with low overhead.
Cons:
Requires careful tuning of lock expiration time.
Use the Redis SET command with the NX (only set if not exists) and PX (set expiration in milliseconds) options:
SET auction_lock:{auction_id} {lock_value} NX PX {expiration_time_ms}
HLD