Make sure you understand the basic requirements and ask clarification questions. Start with the most basic assumptions:
- What is the goal of the system?
- Who are the users of the system? What do they need it for? How are they going to use it?
- What are the inputs and outputs of the system?
Try to define all the features that you think of by their importance to the user. Ask clarifying questions, such as:
- Do we want to discuss the end-to-end experience or just the API?
- What clients do we want to support (mobile, web, etc)?
- Do we require authentication? Analytics? Integrating with existing systems?
Take a few minutes to discuss this with your interviewer, and write it down.
It’s important to determine the scale so that you know whether your data can fit on one machine or whether you need to scale the reads. You might ask:
- What is the expected read-to-write ratio?
- How many concurrent requests should we expect?
- What’s the average expected response time?
- What’s the limit of the data we allow users to provide?
- How much storage will we need?
- What is the network bandwidth we expect?
Different answers require very different designs, so getting the scale right is key to success.
Start with covering the end-to-end process, based on the goals you’ve established. This might include detailing different clients, APIs, backend services, offline processes, network architecture, data stores, and how they all come together to meet the requirements. This is also a good point to identify the system’s entry-points, such as:
- User interaction
- External API calls
- Offline processes
Drill down into potential performance bottlenecks, and decisions about the separation of responsibilities. Always start simple, and iterate.
What kind of data do we need to store?
- Message schema
- RDMS tables
- Monitoring events
URL shortener? Makes me think of a hashing function. Oh, you need it to scale? Sharding might help. Concurrency? Redundancy? Generating keys becomes even more complicated. Same goes for designing an analytics system, a news feed, or a Q&A forum, each with its own set of common DS&A.
Don’t forget to account for your scaling requirements, where analyzing runtime and memory complexity really becomes handy.
Draw a block diagram with 5-6 boxes representing the core components of the system that are able to solve the problem end-to-end?
- API Gateway
- Load balancer
- Message queues
- Databases & cache
- Monitoring
- Service discovery & health checks
Dive deeper into 2-3 components:
- Should we partition part of the system because of massive amount of data?
- How do we handle hot data partitions?
- How do we optimize reads?
- Which components need better load balancing or caching?
Almost every decision will involve a trade off.A few common examples might include:
- Is there a single point of failure in the system?
- Do we have enough replicas of data so we are resilient to server failures?
- What type of database would you use and why?
- What caching solutions are out there? Which would you choose and why?
- What frameworks can we use as infrastructure in your ecosystem of choice?
- How do we monitor performace of our system? Do we get alerts when components fail?