To ensure that the system you’re building today is both stable and can scale to meet anticipated demands of customers, without requiring an expensive rebuild, considering the architecture at the core of your system is essential when developing any new services. This article discusses two architectural designs, their features, and key considerations when deciding which is most suitable.
Microservice architecture is defined as “a variant of the service-oriented architecture structural style – in which an application is structured as a collection of small autonomous services, each running in its own process and communicating with lightweight mechanisms, typically an HTTP resource API”. These services are designed around business capabilities and can be deployed independently by fully automated deployment machinery. There is very little centralized management of these services, which may be written in various programming languages and employ various data storage technologies.
Before microservices, the only model used for solution design was monolithic architecture. This means that all the application components and the whole code are part of a single unit. For example, for an online shop application, all of its parts like the user authentication shopping cart, and product catalog sales campaigns notification, have their code written in a single codebase. All the features are developed, deployed, and scaled as one unit.
This means the application must be written in a single language, with one technology stack, and with single runtime. Different teams working on different parts of the application need to coordinate to ensure others' work is not impacted during deployments; for example, if the developers change the code for payment the entire application would need to be built and deployed as a single package. Payment functionality cannot be changed separately.
But as applications grow in size and complexity this leads to different challenges. First of all coordination between teams becomes increasingly difficult as a large amount of code is written. Parts of the application become entangled making feature updates and defect resolution is more time consuming as the correct portion of code responsible for a feature needs to be identified. A needle in a haystack!
Scaling is also an issue where only certain parts of an application need to be scaled to handle the increased load. For example, scaling would be required for shopping functionality on holiday dates; however, with Monolithic architecture, the whole solution would need to be scaled. This results in higher infrastructure costs and less flexibility in scaling applications up and down.
Another issue is for example if a payment functionally required version 1.8 of a third-party module, whilst notification functionality needed the same module but required version 1.7. In a monolithic application, only one version can be selected as a single application is dependent on the same module versioning.
Another major issue with monolithic applications is that the release of such applications takes longer because changes in any features require rebuilding and regression testing of large portions of the application to deploy those changes.
Microservice architecture is an application design approach where a large application “service” is broken down or modularised into multiple smaller applications “microservices”.
This raises several questions which we’ll answer here:
The best practice is to break down the application into components or into microservices based on business features and not technical functionalities. So, the microservices of an online shop will be the search functionality, product display, cart, user account, checkout, and so on. Each microservice is responsible for performing one business feature.
You should always strive to keep one service doing one specific job, and a very important characteristic of each microservice is that they should be self-contained and independent from each other. This is called “loose coupling”.
So, for example, you should have a microservice that is responsible for shopping cart logic and checkout. This means each service can be developed, deployed, and scaled separately without any tight dependencies on any other services even though they are a part of the same application.
With this best practice approach, if you change something in the payment service, you will only build and deploy the payment service and nothing else will be affected. This means the services have their individual visions which are not dependent on others. If I release one service I don’t need to upgrade any other service. The release circle is completely independent.
These services are isolated and self-contained, how do they connect to each other? Because obviously, the payment service will need something from the user account to process the payment or the checkout services will need something from the shopping cart.
A very common way for microservice communication is using API (Application Programming Interfaces) calls. This is like using a telephone where one service can make a call to send a message, another service can receive it, process it, and if necessary make a subsequent call to pass the message on.
This can happen in 3 ways:
These are the different communication options and since the services are all isolated and talk to each other either with API calls or using additional services you can even develop each service with a different programming language. You can have dedicated teams for each service that can choose their own technology stack and work on their services without affecting or being affected by other service teams. This is the most important advantage of microservices architecture compared to the monolith.
These benefits of microservices architecture come with a price. While microservices made developing and deploying applications easier in many aspects, this also introduced some other challenges that weren’t there before. When you break down the application into these multiple pieces, it introduces a lot of complexities and challenges.
One of the main complexities may be configuring the communication part between the services. A microservice may be down, unhealthy, or not responding when another service starts sending requests to its API expecting a fulfilled response, leading to some interesting and unexpected results.
Also with microservices deployed and scaled separately, it may become difficult to keep an overview and identify when a microservice is down and which microservices are down when something in the application is not working correctly.
You need a proper configuration of your application setup and its pieces to make sure your application as a whole function well. But there are various tools for making this all easier, even though the microservices architecture is complex there are a lot of tools, and still, more are being developed regularly to make running microservices applications easier. The most popular are Docker and Kubernetes which are the perfect platform for running large microservices applications.
When deciding which architecture to use for a project, it is important to take the time to understand both the big picture and the detail and weigh the advantages and disadvantages of different approaches in fulfilling the scope and requirements in the most efficient way possible. Doing so will ensure that the most appropriate architecture is chosen, allowing teams to build successful, scalable, future-proof applications. It is also important to consider the costs associated with the development and maintenance of the chosen architecture, as well as the project's projected timeline. Furthermore, the development team's capabilities and available resources should be considered.
Whilst we have touched on just a few aspects in this article, there is much more to consider in the world of system design and we would be delighted to discuss this further with you. Simply contact us directly via email@example.com and get in touch with our amazing team.