Customer
Item
Order
Orders per Day: 20,000 (on average)
Items per Order: 3-5 items (on average)
Items viewed before Ordering: 10-15 items (on average)
Inventory size: currently 100,000 items, and we add 1,000 new items/day
User base: currently 50,000 active users, and we add 500 new users/day
At the current rate, our user will reach 50000+(500*365)=232,500 active users in 1 year, meaning almost 5 times the current number of users. Therefore we can expect all numbers of orders / items to grow rapidly (i.e. by a factor of 10x in the next 3 years).
Orders per second = 20000/(24*60*60) = 0.2 queries per second to the Order API (possibly 2 QPS in the next 3 years)
Items ordered per second = 5*0.2 = 1 write per second to the Items DB (possibly 10 writes per second in the next 3 years)
Items viewed per second = 15*0.2 = ~7 reads per second to the Items DB (possibly 70 reads per second in the next 3 years)
At the current rate, our inventory will reach 100,000+(365*1000)=465,000 in 1 year, meaning almost 5 times the current number of items. And approximately 1,000,000 items in 3 years.
If we assume that 1 item needs approximately 1 KB of data storage (itemID=4 bytes, name=50 bytes, description=250 bytes, supplier address=50 bytes, supplier contact details=50 bytes, stockAmount=4 bytes), then 1 KB * 1,000,000 items = 1 GB database size for the items
We will use REST endpoints to communicate with our system:
GET /inventory/{itemIDs} - used to get the available inventory for some items
Inputs:
JSON Output:
Considerations:
POST /order - used to fulfil a customer order
Inputs:
JSON Output:
Considerations:
POST /reorder_stock - used to send an order to the supplier for one item
Inputs:
JSON Output: None
POST /replenish_stock - used when the delivery from a supplier has arrived and the stock can be increased
Inputs:
JSON Output: None
POST /signup_alert
Inputs:
JSON Output: None
In general, use an API Gateway to authenticate all API requests and enforce rate limiting. As users should only be able to make Orders or Sign Up to Alerts only for their own userID, etc.
Note that we are purposely avoiding having a POST /set_inventory API, as we don't want to publicly expose an endpoint that modifies the available stock of an item as this is prone to incorrectly modifying our item stock. Instead, the system should privately modify the stock amounts by fulfilling an order (POST /order or POST /replenish_stock)
Given that we require strong consistency of the Items database, as well as ACID properties (i.e. Atomicity - an order should either succeed or fail completely) then we will opt for a SQL database solution like PostgresSQL.
User:
Item:
Supplier:
Orders:
An item has exactly one supplier.
An order can have multiple items. An order belongs to exactly one user, but a user can have multiple orders.
Explain how the request flows from end to end in your high level design. Also you could draw a sequence diagram using the diagramming tool to enhance your explanation...
Dig deeper into 2-3 components and explain in detail how they work. For example, how well does each component scale? Any relevant algorithm or data structure you like to use for a component? Also you could draw a diagram using the diagramming tool to enhance your design...
Explain any trade offs you have made and why you made certain tech choices...
Try to discuss as many failure scenarios/bottlenecks as possible.
What are some future improvements you would make? How would you mitigate the failure scenario(s) you described above?