| Scale | Users | Products | Carts Active | Orders Placed | System Changes |
|---|---|---|---|---|---|
| Small | 100 | 1,000 | 50 | 20 | Single server, simple DB, no caching |
| Medium | 10,000 | 10,000 | 5,000 | 2,000 | DB read replicas, caching for products, load balancer |
| Large | 1,000,000 | 100,000 | 100,000 | 50,000 | Sharded DB, distributed cache, multiple app servers, async order processing |
| Very Large | 100,000,000 | 1,000,000 | 10,000,000 | 5,000,000 | Microservices, event-driven order system, CDN for product data, global DB shards |
Product, Cart, Order classes in LLD - Scalability & System Analysis
Start learning this pattern below
Jump into concepts and practice - no test required
At small scale, the database is the first bottleneck. It handles product lookups, cart updates, and order writes. As users grow, the DB CPU and I/O get overwhelmed by many read and write requests.
- Read Replicas: Use read-only copies of the database to handle product and cart read queries, reducing load on the main DB.
- Caching: Cache product details and cart sessions in memory (e.g., Redis) to reduce DB hits.
- Horizontal Scaling: Add more application servers behind a load balancer to handle increased user requests.
- Sharding: Split the database by user ID or order ID to distribute writes and reads across multiple DB instances.
- Async Processing: Use message queues to process orders asynchronously, reducing latency and DB write spikes.
- CDN: Serve static product images and data from a CDN to reduce bandwidth and server load.
- At 1M users, assuming 5% active carts = 50,000 carts active concurrently.
- Each cart update generates ~2 DB writes per minute -> 100,000 writes/min = ~1,666 writes/sec.
- Orders placed at 50,000/day -> ~0.6 orders/sec, but spikes during sales.
- Product catalog reads at 1M users -> ~10,000 QPS for product info.
- Bandwidth for product images served via CDN reduces load on origin servers.
Start by explaining the main components: Product, Cart, Order. Discuss how each scales with users and data. Identify the database as the first bottleneck. Then propose solutions in order: caching, read replicas, horizontal scaling, sharding, async processing. Use numbers to justify your choices.
Your database handles 1000 QPS. Traffic grows 10x to 10,000 QPS. What do you do first?
Answer: Add read replicas and implement caching for product and cart data to reduce load on the main database before considering sharding or more complex solutions.
Practice
Solution
Step 1: Understand the role of Product class
The Product class stores item details such as ID, name, and price.Step 2: Compare with other classes
The Cart class holds selected products and quantities, and Order class records purchased items and status, not product details.Final Answer:
Product class -> Option AQuick Check:
Product details = Product class [OK]
- Confusing Cart with Product class
- Thinking Order stores product details
- Assuming User class stores product info
Solution
Step 1: Identify the class responsible for holding selected products
The Cart class holds selected products and their quantities before purchase.Step 2: Check method naming conventions
Adding a product to a cart is typically done by calling a method on the Cart object, like addProduct(product, quantity).Final Answer:
cart.addProduct(product, quantity) -> Option CQuick Check:
Adding product to cart = cart.addProduct() [OK]
- Calling addToCart on Product class
- Using Order class to add products before purchase
- Confusing method names like createOrder in Cart
product1 = Product(id=1, name='Pen', price=2)
product2 = Product(id=2, name='Notebook', price=5)
cart = Cart()
cart.addProduct(product1, 3)
cart.addProduct(product2, 2)
order = Order(cart)
order.checkout()
Solution
Step 1: Calculate total cost from cart products and quantities
Pen price = 2, quantity = 3 -> 2 * 3 = 6
Notebook price = 5, quantity = 2 -> 5 * 2 = 10
Total = 6 + 10 = 16Step 2: Check if any additional charges or taxes apply
No extra charges mentioned, so total cost should be 16.Final Answer:
16 -> Option AQuick Check:
2*3 + 5*2 = 16 [OK]
- Adding quantities instead of multiplying by price
- Mixing product prices and quantities incorrectly
- Ignoring one product's cost
class Order:
def __init__(self, cart):
self.cart = cart
self.total = 0
def calculate_total(self):
for product, qty in self.cart.items():
self.total += product.price * qty
return self.total
Solution
Step 1: Analyze total calculation logic
The method adds product price times quantity to self.total in a loop.Step 2: Check for accumulation errors
Since self.total is not reset before calculation, repeated calls will add to previous total, causing incorrect sums.Final Answer:
Not resetting self.total before calculation -> Option DQuick Check:
Reset total before sum to avoid accumulation [OK]
- Assuming cart.items() is invalid without context
- Thinking multiplication is wrong when it is correct
- Confusing return with print for output
Solution
Step 1: Understand separation of concerns
Cart should hold selected products and quantities before purchase. Order should record purchased items and status separately.Step 2: Evaluate design options for scalability and clarity
Make Cart hold Product objects with quantities; Order copies Cart items and tracks status separately keeps Cart holding Product objects with quantities, and Order copies these items to keep a snapshot and track status, which is clean and scalable.Final Answer:
Make Cart hold Product objects with quantities; Order copies Cart items and tracks status separately -> Option BQuick Check:
Separate Cart and Order responsibilities for scalability [OK]
- Making Order inherit Cart causing tight coupling
- Storing only product IDs in Cart losing details
- Putting quantity in Product class mixing concerns
