Building blocks of a Software System Design

Prateek Nima
5 min readFeb 27, 2023
Photo by Alvaro Reyes on Unsplash

Nowadays, to build a good distributed system, it is necessary to utilize multiple services which combined together help us to deploy software that can be accessed over the network. It is necessary to choose the correct building blocks and this primarily depends on the requirements which are mainly categorized into functional and non-functional requirements. The overall process of combining the building blocks is known as System Design in the world of software development and helps us to design a system that enables us to handle millions of user requests.

The following are the building blocks of a system design:

Domain Name System(DNS):

As per Wikipedia,

The Domain Name System is a hierarchical and distributed naming system for computers, services, and other resources in the Internet or other Internet Protocol networks. It associates various information with domain names assigned to each of the associated entities.

This building block focuses on how to design hierarchical and distributed DNS for the computers connected over the internet.

Databases:

Databases are one of the most important aspects of designing a system. There are basically categories of databases that come into play and that are relational and non-relational databases. Each of them comes with its own benefits and trade-offs. ACID is one of the most important properties, other properties include replication, partitioning, sharding, etc. The major types of non-relational databases include key-value database, document database, graph database, and columnar database.

Load Balancers:

In today’s world, most applications need to handle millions of requests each day. As the website grows there might be exponential growth and this needs to be handled without any lack in the user experience. E.g. As per the search statistics, Google processes 8.5 billion search requests each day. This is possible using load balancers.

Load balancers divides the user workload evenly amongst all the available servers, thereby avoiding overloading and crashing of the servers.

It is the first point of contact before the request is processed by the API or applications thereby enabling to achieve of improved performance along with scalability and availability.

Content Delivery Network(CDN):

Consider a global application that is data intensive e.g. Netflix, or Amazon Prime video. If we retrieve the video for each request only using a single server, the workload on the database would be immense and will also lead to high costs and delayed response to the users.

A Content Delivery Network, also known as a content distribution network, copies data into multiple proxy servers across various locations around the world. When a client(user) request comes in, it fulfills the request using the proxy server itself rather than forwarding the request to the origin server.

This helps the applications to provide high performance and availability.

Have you ever noticed that many of the web series/movies on Amazon prime videos are only accessible to the users of a particular region?

Unique ID Generator:

Whenever we design software it is necessary to distinguish each of the entries added to the database. Usually, in relational databases, this is done utilizing the auto-increment feature but when an application is distributed across multiple nodes we need to come up with a different mechanism to achieve the same. One of the implementations to generate a unique id in distributed systems is using UUID.

Service Monitoring:

Once a system/application has been developed, it is necessary to monitor it continuously to make sure the services are working as expected or if there is any unexpected failure. It acts as a trigger on which the team and stakeholders can understand the impact and take any further actions. This includes monitoring server-side as well as client-side errors.

Caching:

Consider an application highly interactive application such as Twitter, or Instagram. Imagine if a video post goes viral, if we retrieve the video for each request, the workload on the database would be immense and will also lead to high costs. In the worst case, this might also lead to application breakdown.

Caching is a mechanism using which we store the data in a high-performant temporary storage so when a future user request comes in(Viral video in the above example) we can simply return the data from the temporary storage.

The various algorithms for caching include Least Recently Used(LRU), Least Frequently Used(LFU), etc.

Messaging Queue:

When you place an order on an eCommerce website, have you ever noticed that you receive the confirmation email after a few minutes? or consider an example where you purchase an online gift voucher but it gets delivered to your mailbox after a certain period of time.

Messaging Queue helps to add the requests in a queue, generated by producers, while it stays in the queue until the consumer is ready to process it. Basically, it acts as an intermediate component that helps to connect the request-producing and request-consuming entities.

This is also known as the message-queue model.

Pub-Sub Model:

The Pub-Sub model is similar to the message-queue model, the difference is that multiple consumers(called subscribers), can listen to the published messages in the case of a pub-sub model while in the case of the messages-queue model, only a single consumer listens to the published messages.

In the case of the pub-sub model, the number of consumers can even be zero. It is also known as event-driven architecture.

Rate-Limiting:

Rate limiting is a defensive mechanism and is used to limit the number of requests a user can do in a specified time frame. This is one of the mechanisms which acts against attacks such as Denial of Service(DOS).

One of the algorithms for rate-limiting is the token-bucket algorithm.

Search data in distributed systems:

Have you ever imagined when you type a keyword on the google search bar we automatically see the top relevant results? This is only possible using distributed search systems. The primary things to achieve this is first scanning through all the content(known as crawling), then performing indexing and finally, we search the results.

The various techniques for indexing include bitmap index, reverse index, dense index, etc. One of the distributed search engines is Elasticsearch.

Task Schedulers:

The main task of task schedulers is to schedule and execute tasks in distributed systems. They allocate resources dynamically such that there is no delay in the execution and thereby provide asynchronicity.

Distributed logging system:

The logging system helps us to trace the logs and come to know and debug the issue. For e.g. consider you have a high number of microservices dependent on each other, if one of the services fails, all the other services would fail and impact the overall application. It is not possible to go through each line of code in the applications. This makes logging in distributed systems immensely important.

Logging helps to reach the root cause of failure easily and quickly

Elastic search is one example of a highly available logging systems in the market.

In this article, we went through the building blocks that are required while designing a system. If you liked this article, then please share it with your friends and colleagues. If you have any questions please feel free to shoot them in the comments section below.

--

--