The Scalability Cube

I was just watching a YouTube video where they brought up an interesting diagram, which I realized summed up how to scale your service from an system design point of view.



In the diagram, it has three axis:


  • X-axis scaling (Horizontal Duplication)
  • Y-axis scaling (Functional Decomposition)
  • Z-axis scaling (Partitioning)

Horizontal Duplication (X-axis)

Probably the first thing that comes to mind when your thinking about scaling out your application. Horizontal Duplication means that you should build your application in such a way that you can have multiple instances of your application running and handling requests at the same time.

To complete this strategy, a machine called a load balancer will usually sit in front of your cloned systems and forward incoming requests to your instances. 

Stateless Design

Stateless Design is the design principle that information is not stored from the communications between a user and an instance of your application, and this information should not affect future interactions. More specifically, a system should only need information from the request, and some external persistence layer in order to handle the request.

Functional Decomposition (Y-axis)

Functional Decomposition is the trend to split up your system into specialized sub-systems to facilitate a request. While there is not an immediate performance benefit from scaling this service, it has a key benefit of breaking down your solution into smaller components that have an impact on your architecture and your organization.

Benefits of Smaller Sub-Systems

The key benefit of splitting up a larger sub-system is when you relate it back to horizontal duplication and the benefits of load balancing. When we want to load balance an application, it requires us to create new instances of our application and run them in parallel. The cost of doing this is the time to create a new resource, and the resources it requires to run the application.

When we decompose our large system into smaller components, we are starting to reduce the size of the applications that need to live, which would in turn reduce the time it takes for a system to complete it's startup process, as well as the resources it requires to run.

It also allows us to customize a unique strategy for each problem a sub-system is mean to solve. For example a system that we have high amount of requests would need to be in a machine that can handle high network traffic. A system that is meant to do a large amount of caching may require a machine with high amounts of memory. A system that is algorithm intensive may need a machine that has blazing fast computational output.

Benefits for the Organization

Just as applications can become large, so does the organization that needs to support it. As more and more people begin working on the same application, it becomes its own problem of coordinating system requirements, merging your code back in, and coordinating deployments. By separating out your application into different domains, you are creating an isolated environment where a single team is able to manage a specific function of your application. This reduces the amount of dependencies you have on other parts of your organization, which should theoretically improve productivity.

On an information note, smaller sub-systems introduces a large amount of other problems which I'll probably address in a later post. It is important that we should acknowledge that a system will always have some problem we're trying to address, but we're trying to get to a point where we have better problems.

Partitioning (Z-axis)

Then we come to our final scaling strategy, partitioning, which is splitting up the overall problem into the same problem, just split into groups. We have a variety of strategies we can split up big problems, such as splitting up network traffic by region, or a username database by first name. When you split up data by a specific key, it is also known as sharding. This will probably be your last step of scaling a system.

Conclusion

From a system architecture point of view, we really have these three strategies to use from our toolbox. We use Horizontal Duplication when we can solve the problem by throwing more resources at the issue. We use Functional Decomposition when we can make optimizations to the problem itself. And then we can look to Partitioning when the problem set becomes so large the overall system becomes large enough in size.

Comments

Popular posts from this blog

Uncle Bob's Clean Architecture

C4 Model: Describing Software Architecture

Running RabbitMQ with Docker