System Design Basics
Building a scalable system is a difficult job, you need to think of many different edge cases, work on trade offs, and still there are lot of things in a system design that can be improved. I am writing this article to make the system design process a little simpler and giving a structure to your approach. You can use this while working on a design in your current job or if you are preparing for an interview.
Here are couple of sections you can work on in the given sequence while working on a design.
Requirements
The very first thing before working on design you should do is scope your design. Basically, write the system requirements. In my opinion there can be 3 types of requirements —
- Functional- These are the requirements which define the features of your system. For example in case of an instagram design, you can think uploading a photo as a functional requirement.
- Non Functional- These are the pure technical requirements of your system. For example you may want to build a highly consistent system or a system with high availability but low consistency.
- Extended- These are the requirements which your design may not include at present but you should keep these requirements in mind and build your design such that in future it should be able to incorporate these requirements.
API
Now you have listed your requirements, the next step would be to list your interfaces. This will give you a high level picture of what request will be coming in and what should be the response of your API’s that will fulfil your design requirements.
Capacity estimation
After you have decided your API’s, the next thing you can think of is expected traffic to your system. Now, there is no exact formulae to calculate the correct expected traffic but you can do a rough estimate. Following things you can calculate in this section.
- Traffic- This is the expected number of request your system will be receiving. You can calculate this on a per second basis.
- Storage- This is the expected storage volume your system needs to store.
Design Considerations
In this section it will good to talk about your major Design choices. All these topics can be taken up separately in detail, I am writing just a gist here —
- Storage type- If you need to store a data that is not be feasible to store in SQL/NoSQL database then which storage you should choose. There are 3 types of storage that you can choose from, File storage, object storage and block storage.
- Database type- If you need to store some data in a database, then which one you should choose, SQL or NoSQL. If you choose NoSQL then what type of NoSQL database you should go with, Key-Value based, Document based, wide-column database or graph based.
- Microservices- When you choose to go with distributed architecture then you need to divide the responsibility between different micro-services and figure out how you they will communicate with each other.
- Sync/Async flow- Depending upon the requirements you can choose if the request of an API has to be processed synchronously or asynchronously.
- Push/Pull mechanism- To communicate from one service to another you can either call an API(Pull based) or you can push a message to another service via Kafka/SNS/SQS.
- Connection type- Based on the use case and requirements you may also need to choose the type of connection you want to setup between client and server like Http, Long polling or Web-sockets.
- Caching- Fetching the data from persistent database for every request may not fulfil the latency requirements. Many times you may have to add a caching layer between your service and database like Redis, memcache, etc.
These are just a couple of topics and it may happen that you will not need to work on these in every design. There are a lot of other topics/trade-offs that can be discussed, but these will be good to start with.
High Level Design Diagram
Till now you have chosen a lot of things and you must be having a high level picture of the design in your mind. Now you have to print that picture from your mind to a board/paper or you can also use many online tools. I prefer https://draw.io/ to create high level design diagram.
Detailed High level Diagram
Once you have created a basic high level design diagram, now you can dig deeper into the individual components and refine your design. By refining I mean you can do following things —
- Add arrows and numbers representing the direction of data flow.
- Add side components like load balancer based on what components need load balancer.
- Explain about your storage and any complex piece of your design like consistency, availability, latency handling, and etc.
Bottlenecks & Design improvement
Once you have your design ready, you need to look for further improvements. Below are few things that you can look for —
- Extended requirements- Is your design able to support extended requirements. If not then think what you will need to change.
- Latency- What will be the overall latency of your system, is it under your expected requirement? Is there any improvement that can be done to improve your system latency.
- Availability- If you want to make your system highly available then look what can be the fault points of your system and figure out how you can improve it.
- Scalability- Is your system designed such that it is able to scale for high traffic. What you will need to scale for high traffic? What changes you will need in your database? You need to think from all angles.
I hope you find this article helpful, we discussed basic things which can be a good start for system design. There are lot of things that can be covered and you can keep on eye on upcoming articles for that.