Re-designing Monolithic Applications with API-Led
Introduction
It's essential to adapt architectural paradigms that ensure scalability, resilience, and ease of maintenance. In this blog post, we will describe how to re-design a traditional monolithic website by leveraging the three-layered API architecture and the CQRS pattern, addressing the common pitfalls associated with monolithic applications.
Problem Statement
Monolithic applications, though once the norm, come with a lot of challenges:
Lack of Scalability: Scaling horizontally becomes a difficult task as the entire monolith needs to be replicated.
Maintenance Challenges: Complexity grows with the application, making it challenging to manage with multiple team members as everybody is writing on the same code base.
Risk of Downtime: A bug in one part can bring the entire system down, resulting in downtime.
Difficult Testing: Testing becomes difficult due to the interconnected nature of components.
Fault Isolation: A single failure can cascade, affecting the entire system.
Let's see how this monolithic application can be re-designed by using the three layered approach to overcome the downsides we just described before.
Solution
Our journey towards a modern, scalable, and maintainable architecture unfolds in two steps:
Step 1: Three Layers and Load Balancing
First, we'll reshape our architecture by dividing it into three main layers:
Application Layer: This is where the frontend application resides, making it the user-facing part of our system.
Integration Layer: Our APIs find their new home here. We'll also adopt the API-Led approach, as we've described in a previous blog post.
Data Layer: The database lives here, handling data storage and retrieval.
This architectural shift provides several advantages:
Flexibility: Separating the frontend from the backend allows for more adaptable system components.
Scalability: With this separation, it's easier to scale each layer with the related components as needed.
Reusability: Components are better organized for reuse in various parts of your system.
Simplified Maintenance: Managing and updating individual layers is more straightforward, even with multiple team members involved.
Enhancing the Integration Layer
Within the integration layer, we'll enhance it by implementing the API-Led approach. This is an effective method where we create multiple layers of APIs to enhance re-usability, flexibility and having loosely coupled services. To make sure everything gets load balanced over multiple replicas, we'll add a Load Balancer. While there are various types of Load Balancers, like Level 4 (TCP) or Level 7 (HTTP), we won't delve into those details in this blog post.
By adopting these changes, your system will be better equipped to handle the demands of high volumes of users and requests.
Step 2: CQRS and Caching
The second step involves the segregation of the database into a read and write database, a concept also described by Martin Fowler known as the CQRS pattern. In addition to this segregation, we introduce caching mechanisms in the APIs to reduce unnecessary database queries and enhance system performance. For instance GET requests can be perfectly cached as data is not often changed.
The Read Database is a replication of the Write Database in a Master-Slave relationship.
Conclusion
In summary, our transformation journey equips us with the following best practices:
Modern Three-Layered Architecture: Distribute the application, integrations, and the database across three distinct layers.
Load Balancing: Deploy APIs on multiple replicas and multiple layers, using the three layered API-Led approach and employ a Load Balancer for efficient load distribution.
CQRS and Caching: Overcome database bottlenecks by separating read and write operations using the CQRS pattern. Implement caching for read operations to reduce unnecessary database queries.
The evolution from monolithic to a more agile architecture is a vital step in meeting the demands of high volume applications.
Call to Action
Let us know what you would do to optimize a monolithic application in your context. Which important optimisations are still missing?





