Monolith to Microservices Migration

Prashant Bhargava
Hacker Era
Published in
5 min readJun 19, 2019

--

Written by Abhishek Ranjan & Prashant Bhargava

Brief

The aim of this document is to analyze the migration process from a monolithic application to a microservices based architecture. This document is based on a real-world migration project for a big financial company.

The main problem that is tackled in this document is how to sustainably scale a tech company without compromising productivity.

The main result of this document is a successfully implemented microservice and a generalized methodology for extracting microservices from a monolithic application.

Introduction

The application handles 30 million transactions/day. How do you scale a startup company at such a growth rate without sacrificing productivity?

It becomes increasingly hard to arrange the work between the teams when everybody is working on a single monolithic application.

At this point, architectural refactoring becomes essential.

Microservices is a software architecture paradigm that constitutes an application of small and independent services communicating with one another through standardized APIs.

Scope and Goals

  1. Analyze the pros and cons of the microservices architecture compared to the monolithic architecture.
  2. Provide a generalized approach to decomposing a monolith application into microservices.

Monolithic Architecture

The main characteristics of this monolithic system are:

  • Written in a single programming language
  • Single source code repository
  • Single IDE project
  • Compiled and packaged into a single runtime application
  • High coupling
  • Low cohesion
  • Shared Database

The code follows the layered architecture.

Layered Architecture

Advantages

  • Simple to develop — you can import a single project into an IDE and easily run the whole application on your development machine.
  • Simple to test — it is straightforward to run automated functional tests and end-to-end tests on a single monolithic application.
  • Simple to deploy — a monolithic application is packaged into a single deployable file which can be easily deployed onto an application container.
  • Simple to horizontally scale — you can easily run multiple instances of the same application behind a load balancer to scale the application horizontally.

Disadvantages

  • Synchronous release cycles — a change made in a small subset of the system requires the entire monolith to be rebuilt, retested and redeployed. Continuous deployment is difficult and this discourages frequent and small updates.
  • Modularity — over time, with many new developers joining the company, it becomes increasingly hard to keep your codebase modular. This, in turn, makes your code harder to understand, harder to develop and more error-prone, which slows down development.
  • Slow IDE — loading the whole monolithic project into your development environment can make it painfully slow.
  • Slow startup times — When running a single application in a single web container the startup time gradually slows down as the application grows. This impacts both development and deployment.
  • Scaling — Each component of the monolithic system usually has different system requirements. Some may be CPU intensive, and some memory intensive. It is impossible to scale individual components independently.
  • Independent teams — once the organization grows and more developers join the engineering department, it makes sense to split them into independent teams. Each team can focus on a single functional area (for example, transfer creation or payment processing) and have a well-defined KPI (for example, the conversion rate or payment processing speed).
  • Technological agnosticism — a monolithic application is based on a single technology stack. The whole application is written in a single programming language using a single framework and a common set of libraries. Different components of the system cannot be written in different programming languages. A monolithic system is, by definition, not technology agnostic.

Microservices Architecture

The microservices architecture pattern aims to address the limitations of the monolithic architecture pattern. The application is split into functional services: each service has high cohesion, and is, in most cases, relatively small (hence the name, microservice). For example, our monolithic financial application might be composed of services such as MidOffice Payment service, BackOffice Service, Configuration Service, etc.

High-Level Microservice Architecture

Advantages

  • Independent deployability — easy to frequently deploy new versions of a service. This, in turn, means that teams can develop, deploy and scale each service independently of all the other teams.
  • Lower complexity — each service is relatively small, has a single responsibility, high cohesion, and loose coupling. This makes understanding the subsystem easier for new team members and they can become productive much faster.
  • Fast IDE — since every microservice is relatively small, it will not slow down the development environment and developers can be more productive.
  • Technological freedom — each microservice could theoretically be coded in a different programming language and use a different technology stack. However, it still might make sense to keep the underlying platform of the microservices relatively homogeneous. This allows to make the hiring process more standardized and makes it easier for developers to switch between teams.
  • Easy to rewrite — microservices are, by definition, small. For that reason, it is comparatively easy to rewrite them. As long as the interface or the API contract does not change, the development team responsible for that specific microservice has the freedom to change any implementation details. This way, teams are able to independently take advantage of new emerging technologies (frameworks, libraries, etc.).
  • Fault isolation — with microservices all boundaries are isolated, which means that the scope of potential problems is also isolated. This reduces the potential for damage and makes the systems easier to maintain.

Disadvantages

  • Increased complexity — a distributed system is inherently more complex. Running the full application stack in your development machine is not as straightforward as a monolithic application.
  • Testing — integration testing different versions of microservices to make sure they are compatible with each other and running end-to-end tests is more complex in a distributed microservices-based application.
  • Latency — it takes time to communicate through a network socket. It takes time to marshal and unmarshal objects to and from JSON (for example, in case of REST). Can be improved using ProtoBuf
  • Overhead — each microservice runs in a separate Runtime and uses its own application server, which requires extra computation time, memory and bandwidth.

--

--