So, before I start telling you about the problems we faced and how we solved them, I would like you folks to get familiar with the ‘Loki’ of coding world. Loki! sounds strange in a coding blog right? Many company’s unknowingly or knowingly are still using this mischievous style of coding which I tell you might be the cause of their downfall, so if you still holding on to those old memories (pun intended) be very scared coz’ professor Doom is very near.

Photo by Iker Urteaga on Unsplash

The topic which I’m trying to describe here is Monolithic Architecture (a large single upright block of stone, especially one shaped into or serving as a pillar or monument or the foundation stone. Any changes in the foundation is going to produce devastating results which will be too costly to handle). This is a legacy style of coding architecture which constraints the developers and chains them down from their imagination. In the below few lines I’ll explain how this acts as a roadblock to a quality style of software development.

I came across this term recently when I saw this legacy system in work for one of our client. It contained a UI (User Interface) which connects to a back-end and do the read/write on the database to get the work done. Seems to be a simple CRUD based model to me.

A CRUD model in itself is an efficient and workable way of software development, considering the size of your project is small and does not require multiple call to the backend or database. As the number of domains continue to grow with the project demands, it created a lot of fuss among the developers as all the projects shared the same Repository. The simultaneous changes made in code by different developers were a pain to handle and monitor by the respective teams during the development phase.

The three major issues that are associated with this Monolith which I discovered while working on the project are:

i. Scalability: This is one of the serious problems which restrict the developers from writing efficient and necessary codes. Even a small change in the code can result in chaos as it has to be synced with all the other teams working on the Repository.

ii. Maintainability: With the number of projects increasing, maintaining the code in a single repository was a much bigger task than development itself. Not only you are supposed to develop an efficient working code you also have to take care of the bugs and errors introduced by others.

iii. Deployment/Delivery: This whole fiasco makes the deployment process a walk on thrones. For the deployment, you need to coordinate with all the teams working on the repo, sync all your code and then you can proceed with deployment. This might take longer than usual time which effects the delivery of the project.

The magic potion for the dying code (Initial Solution):

On thorough analysis of the code we found that all the domains in the project were identical and were working on the same principle. So, we finally decided to experiment with one of the domains and tried separating it from the parent Repository to its own repo. As we expected the changes worked perfectly, now all the domains were separated with different repo’s and they shared the same database, thus we achieved the solution for the three major problems associated with current Monolith described above.

As of now our domains are no longer co-dependent, the only common thing they share are the UI (User Interface) and the database. So, from now on any and every request through the UI goes to the respective domain and does the required transactions on the database to get the work done.

The Blunder (problems with the new code):

Now after doing all the changes and separating the codebase in the nuclear modules, as the number of domains were increasing the overhead on the database increased and it slowed down a lot which was an adverse effect after the separation. As all the domain was querying the database flooding it with reads/writes which became a major problem to handle. For complex query it was hard to optimise the read and write of data from database.

One more problem which stood in front of us was the lack of communication between the domains. In simpler words if one domains require to access the functionality/capability (inform change in domain) of some other domain it’ll be restricted.As the domains are separated and deployed as different systems. Other domains can not poll the database infinite times to get to know about the change in other domain. As it will further slow down the single database.

Now the situation in hand was much worse than what it was earlier. The domains still require communicating with others which again introduces the Monolith, the thing we were trying to avoid for so long.

The Saviour (The Ultimate Solution)

Then I came to know about concepts of CQRS & Event Driven architecture.

CQRS stands for (Command Query Responsibility Segregation). The change that CQRS introduces is to split conceptual model into separate models for updating(write) and display(read), which it refers to as Command and Query. All the write is done by the command and read happens by query. Both the logically separated command and query sits inside a domain and have one small database in common or can be implemented to have different database for command and query. Benefit of implementation of CQRS is you can optimize the read side of the system separately from the write side and teams can scale it separately. So, basically each domain will have its own database which is a small set of data required for the domain and thus separated from the big giant database. It encounters the problem of multiple domain which were reading/writing into a common database. Still we have dependency between the system which need to solve, that can be done using Event Driven Architecture.

Event Driven Architecture is when a system sends event messages to notify other systems of a change in its domain. A key element of event message is that the system doesn’t really care much about the response. Often it doesn’t expect any answer at all, other domains interested in the Event Picks it up and do the processing. The communication happens over Event bus(Queues) like (Kafka/ActiveMQ).

These two terminologies solved all the problem that existed. Now domain do not have to share a single database and have their own database with separated read and write, thus increasing the performance of the system. And all the communication between the domains can be done through Events. Now, each domain publishes the event on event bus which can be listened by other domains or the domains which are interested in the event . It gives domains a capability to be built independently and to be scaled and deployed separately . As of now no service depends on other service and all the domain communicate through events.Which finally resolved the problem we had with the monolith design.

Words of Caution

As CQRS has a lot of pros for a complex system it also comes with a lot of cons. It introduces a lot of complexity in the system. Not every system fits in the mold of CQRS . Thus one should be cautious about using it . Like for a simple domain model in which you want to read/write data from the database and there is only one domain. One do not want to play around with the complexity of CQRS and Event Driven Architecture.