From monolith to microservices: accelerated bank releases 15 times

It happens that a company uses an outdated monolithic IT system, which makes it difficult to quickly release updates and solve its business problems. As a rule, sooner or later the product owner begins to design a new, more flexible architectural solution.



We recently wrote about how IT architects work , and now we will tell you the details about one of our cases and show the scheme of the system. In this project, we helped to replace a "box" banking application with a microservice RBS, while establishing a quick release of releases - on average, once a week.







: , , -. NDA โ€“ , , , -.



ยซยป



Among medium and small companies, ready-made IT solutions are in demand, which can be customized and released with their own logo. Cons - the functions of applications "out of the box" are limited, and updates often have to be made for a long time and exclusively through the vendor.



One of our clients used just such "box" system of remote banking services (RBS). The online bank was a monolithic application with a fairly small set of functions.



In order not to be inferior to competitors, the bank had to constantly introduce improvements and new features. However, even to simply move the buttons in the application, you had to contact the vendor. Updates were released on average once a quarter.



Thus, it was difficult to develop the product due to a number of restrictions:



  1. , ยซยป .
  2. - ยซยป -.
  3. , .
  4. , . .
  5. , .
  6. - , , , .


As a result, the bank made a decision to gradually abandon the "box" and develop its own remote banking system, with a microservice architecture, in order to speed up the development of functions and provide convenience and security for users.



Where did we start



The creation of an online bank began with the design of the top-level architecture, hiring developers and connecting our dedicated team. At the same time, the architecture had to be laid with a margin of safety, counting on future expansion.



At the start, our Backend development team was engaged in the implementation of certain basic functions: for example, money transfers. However, we had quite a lot of experience working with online banks, one of our projects by this time entered the industry rating of Markswebb, so we offered the bank assistance in architectural design - and received the green light.



Architecture



Together with the product owner, we decided to use Spring Cloud, which provides all the necessary functions to implement a microservice architecture: this is Service discovery - Eureka, Api Gateway - Zuul, Config server, and much more. OpenShift was chosen as the container system for Docker images, because the bank's infrastructure was sharpened for this tool.



We also analyzed what features of the old "box" can complicate the work of users. One of the main drawbacks was that the system worked synchronously via the data bus, and every user action caused an access to the bus. Due to heavy loads, the bus often failed, and the entire application stopped working. In addition, as in many old banking products, legacy has accumulated - "legacy" in the form of the old and heavy CORE ABS, which would be difficult and expensive to rewrite.



We have proposed a number of improvements:



  • Versioning


Previously, the "box" supported only one version, but in the new online bank we have proposed a new architecture that will allow us to support several different versions at the same time and replace them if necessary.



The versioning scheme is as follows: if the minor version in the service has changed, then the service is automatically rebuilt and deployed, replacing the outdated version. If we put the major version, then a new copy of the service with the new version is deployed. Thus, the development of new functions with a change in the service API does not affect the mobile application, while the testing time is reduced. Such a system made it possible to provide support for even outdated versions of the mobile application if the user does not have the opportunity to update.



  • Asynchrony


We have implemented a library that can be used in services that require asynchronous work. The library implements the execution of asynchronous tasks, is suitable for use on any number of copies of services, and they do not interfere with each other. Synchronization between different copies is done using the Kafka message queue.



This solution helped to improve the stability of the application. The mobile application is now independent of the bus, we duplicate the data necessary for the user in our services and update them in the background when there is access to the bank bus. All user actions are queued for execution, as soon as they are ready, PUSH notifications about the results are received.



  • Caching


To speed up the application and reduce the load on internal banking resources, data caching using Redis is organized. KeyDB serves as a cache, which shows good results and is compatible with many systems using Redis. Data is cached not after a user request, but when user data changes, which allows access to them independently of the internal banking systems.



What has changed in the system



As noted above, in the old online bank, the backend was implemented in a monolithic architecture, the application was deployed on a separate machine. As the load increased, new servers had to be deployed. When the server crashed, the mobile application did not work for some users.











The new solution uses a microservice architecture, which allows you to deploy as many copies of services as required for a particular functionality. We've added KeyDB-based data caching to not only increase the speed of retrieving information, but also reduce the load on the database.







Let's look at an example of getting data on user accounts in the new architecture. The user's request from the mobile application goes through the balancer to the Gateway, which understands which of the services to send the request to. Next, we get to the account service API. The service first checks if there is actual user data in the Cache. If successful, it returns the data, otherwise it sends a request to the Middle account service.



Updating data in the service can occur in various cases. For example, upon direct request from the user, the service creates a data update task that runs asynchronously, and the data received from the ESB is updated. The service also receives messages from the message queue and responds to them. For example, a service receives a message about a user logging into an application and immediately updates account data, receives data on account transactions from other services, and updates its data. Thus, the user always sees up-to-date data on his accounts.



Among the most important changes are the following:



  • Scaling flexibility


To increase the fault tolerance of the system, services are distributed across different servers. This allows you to keep the system in working order in the event of a fall of one of them. For a timely response to non-standard situations, we introduced a monitoring system, which helped, if necessary, to scale up services on time. We connected DevOps to configure CI / CD from scratch on client servers, built deployment and support processes for the future application on multiple servers.



  • Acceleration of releases due to versioning


Previously, when updating the mobile version, some users already applied the new version, while others did not, but the number of the latter was minimal. When developing a new RBS, we implemented versioning and the ability to release releases without the risk that the application will stop working for a large part of customers. Now, when implementing individual functionality in new versions, we do not break old versions, which means there is no need to regress. This helped accelerate the release frequency by at least 15 times - now releases are released on average once a week. Backend and Mobile teams can simultaneously and independently work on new functionality.



Summing up



In this example, we talked about designing a microservice architecture for a bank, which replaced the "boxed" monolithic solution. A distributed team worked on this project, which included both in-house developers and outsourcers.

When developing an online bank, we tried to implement the same scope of functions in the new application as in a boxed one, and gradually develop it.



In order to prevent customer churn, it was necessary to establish a trouble-free operation of the application, without failures and downtime, and regular release of releases and updates. This was done thanks to improvements in architecture. In particular, after reducing the load on the database, we achieved constant availability of the application, and due to versioning, we reduced the testing time, ensured the possibility of independent work on functionality and release of releases once a week.



The architecture of the application is based on the further growth of the product and development tools used by the banking in-house team so that the product owner can independently make any improvements to the RBS. The terms of active development of the alpha version were about a year, after another 3 months the beta version was released for all users.

We hope that the described scheme of work can be useful when creating other fintech products.



Thank you for attention!



All Articles