Steps to solve system design problems
1. Requirements Clarifications
Ask questions about the exact scope of the problem. You need to clarify ambiguities as soon as possible. For instance, designing a Twitter-like service:
- Will users of our service be able to post tweets and follow other people?
- Should we also design to create and display the user’s timeline?
- Are we focusing on the backend only, or are we developing the front-end too?
- Will users be able to search tweets?
Answers to the above questions will determine how the end design will look.
2. System Interface Definition
Define what APIs are expected from the system. This will not only establish the exact contract expected from the system, but will also ensure we haven’t gotten any requirements wrong. Using the above example:
postTweet(user_id, tweet_data, tweet_location, user_location, timestamp)generateTimeline(user_id, current_time, user_location)markTweetFavorite(user_id, tweet_id, timestamp)3. Back-of-the-Envelope Estimation
It’s a good idea to estimate the scale of the system you’re designing — this helps later when you want to focus on scaling, partitioning, load balancing, and caching. Using the Twitter example, you can ask:
- What scale is expected from the system (e.g., number of new tweets, number of tweet views, number of timeline generations per second, etc.)?
- How much storage will we need? We’ll have different numbers if users can have photos and videos in their tweets.
- What network bandwidth usage are we expecting? This will be crucial for deciding how we’ll manage traffic and balance load between servers.
4. Defining the Data Model
Defining the data model early clarifies how data will flow among different components of the system. You should be able to identify various entities of the system, how they interact with each other, and different aspects of data management, like storage, transportation, encryption, etc. Some entities for the Twitter-like service:
- User: UserID, Name, Email, DoB, CreationDate, LastLogin, etc.
- Tweet: TweetID, Content, TweetLocation, NumberOfLikes, TimeStamp, etc.
- UserFollowing: UserID1, UserID2
- FavoriteTweets: UserID, TweetID, TimeStamp
Which DBMS should we use — will NoSQL like Cassandra best fit our needs, or should we use a MySQL-like solution? What kind of block storage should we use to store photos and videos?
5. High-Level Design
Draw a block diagram with 5-6 boxes representing the core components of our system. We should identify enough components needed to solve the actual problem end-to-end. For Twitter, at a high level, we’ll need multiple application servers to serve all the read/write requests with load balancers in front of them for traffic distribution. If we’re assuming a lot more read traffic (compared to write), we can decide to have separate servers for handling these scenarios. On the backend, we need an efficient database that can store all the tweets and support a huge number of reads. We’ll also need a distributed file storage system for storing photos and videos.
6. Detailed Design
Dig deeper into two or three components — the interviewer’s feedback should always guide us on what parts of the system need further discussion. We should be able to present different approaches, their pros and cons, and explain why we’d prefer one approach over another.
- Since we’ll be storing a massive amount of data, how should we partition our data to distribute it across multiple databases? Should we try to store all the data of a user on the same database? What issue could that cause?
- How will we handle hot users who tweet a lot or follow lots of people?
- Since users’ timelines will contain the most recent (and relevant) tweets, should we try to store our data in such a way that’s optimized for scanning the latest tweets?
- How much, and at which layer, should we introduce cache to speed things up?
- What components need better load balancing?
7. Identifying and Resolving Bottlenecks
Try to discuss as many bottlenecks as possible and different approaches to mitigate them:
- Is there any single point of failure in our system? What are we doing to mitigate it?
- Do we have enough replicas of the data so that if we lose a few servers we can still serve our users?
- Similarly, do we have enough copies of different services running such that a few failures won’t cause a total system shutdown?
- How are we monitoring the performance of our service? Do we get alerts whenever critical components fail or their performance degrades?
(Page 12 of Grokking the System Design Interview)