This document explores the evolution from monolithic to microservices architectures, highlighting their differences, challenges, and best practices for building, scaling, and communicating between services.
This document provides a detailed comparison between monolithic and microservices architectures, explaining the motivations for adopting microservices, their benefits, best practices, and the various methods for service communication and code management in modern application development.
Modern software applications can be built using different architectural styles. Two of the most prominent are monolithic and microservices architectures. Understanding their differences is essential for designing scalable and maintainable systems.
A monolithic application is developed as a single, unified unit. All components—such as user authentication, shopping cart, product catalog, and notifications—are part of one codebase, deployed and scaled together. This approach requires a single technology stack and runtime, making coordination between teams challenging as the application grows.
{{< kroki _type=“mermaid”_name=“diagrams/course/10/01m/001/01-monolithic.mmd” >}}
Microservices architecture addresses the limitations of monolithic systems by decomposing the application into multiple smaller, independent services. Each microservice is responsible for a specific business functionality, such as products, shopping cart, user accounts, or checkout.
{{< kroki _type=“mermaid”_name=“diagrams/course/10/01m/001/02-microservices.mmd” >}}
Note
A single monolithic application is split into smaller (micro) applications known as,microservices
How to create services and breakdown the existing code?The code is split by first creating services based upon
business functionalitiesinstead oftechnical needs
How big or small a service be?One service must only perform one job and nothing else. What is known as
1 service for 1 specific job. A principle ofSeparation of Concern.
How to ensure that services follow microservice architecture?Each service must be
Self-Containedand Independent of each other. That is each one should bedeveloped, deployed and scaledseparately without anydependencyon any other services, despite being a part of the same application. A principle known asloose coupling
Microservices often need to interact to fulfil business requirements. There are several common communication patterns. Three primary methods are synchronous HTTP/API calls, asynchronous messaging via a message broker, and service mesh.
{{< kroki _type=“mermaid”_name=“diagrams/course/10/01m/001/03-internal-microservices-communication.mmd” >}}
Each service exposes an API endpoint on which it accepts requests. Other services communicate by sending HTTP requests and waiting for responses. For example, the user account service may call the payment service’s API to process a transaction. Each service wait for a response before doing anything else, this is known as Synchronous Communication
{{< kroki _type=“mermaid”_name=“diagrams/course/10/01m/001/04-synchronous-communication.mmd” >}}
How tight coupling affects ?If one service is down, it can block the entire request chain, leading to potential bottlenecks.
Services send messages to an intermediary, such as RabbitMQ. The broker forwards messages to the appropriate service, enabling decoupled and resilient communication.
{{< kroki _type=“mermaid”_name=“diagrams/course/10/01m/001/05-asynchronous-communication.mmd” >}}
This approach allows services to operate independently, as they do not wait for immediate responses.
It improves resilience, as services can continue processing messages even if other services are temporarily unavailable.
This kind of messaging follows a common distribution pattern Publish/subscribe and Point-to-Point messaging.
A service mesh introduces a dedicated layer to manage service-to-service communication, handling routing, security, and observability without requiring changes to application code. This approach is increasingly popular in Kubernetes environments.
{{< kroki _type=“mermaid”_name=“diagrams/course/10/01m/001/06-mesh-communication.mmd” >}}
Note
Since microservices are independent, they can be written in different programming languages such as Java, JavaScript, or Python, and use different data stores such as MongoDB, PostgreSQL, or Redis, allowing teams to choose the best tools for each service.
| Communication Type | Description |
|---|---|
| Synchronous | Services call each other’s APIs and wait for responses, leading to tight coupling. |
| Asynchronous | Services send messages to a message broker, allowing them to operate independently and improving resilience. |
| Service Mesh | A dedicated layer that manages service communication, providing advanced features like load balancing and retries. |
While microservices offer numerous benefits, they also come with challenges:
To address these challenges, organizations can adopt several strategies:
| Challenge | Solution |
|---|---|
| Complexity | Implement API gateways to manage communication and reduce direct service-to-service calls. |
| Data Consistency | Use distributed transactions or eventual consistency models to manage data across services. |
| Network Latency | Optimize service communication through techniques like caching, load balancing, and asynchronous messaging. |
| Deployment Overhead | Adopt containerization and orchestration tools (e.g., Kubernetes) to streamline deployment and scaling processes. |
| Tool | Description |
|---|---|
| API Gateway | Manages traffic between clients and microservices, providing a single entry point and enabling features like authentication, logging, and rate limiting. |
| Service Mesh | Provides a dedicated infrastructure layer for managing service-to-service communication, offering features like load balancing, service discovery, and observability. |
| Container Orchestration | Tools like Kubernetes automate the deployment, scaling, and management of containerized applications, simplifying microservices management. |
| Tool | Description |
|---|---|
| API Gateway | Companies like Kong, NGINX, and Amazon API Gateway provide robust API gateway solutions. |
| Service Mesh | Companies like Istio, Linkerd, HashiCorp Consul, and Consul offer service mesh solutions for managing microservices communication. |
| Container Orchestration | Companies like Red Hat OpenShift, VMware Tanzu, and Google Kubernetes Engine (GKE) provide container orchestration platforms to manage microservices. |
Managing code for microservices can be approached in different ways:
| Strategy | Description |
|---|---|
| Monorepo | All microservices are stored in a single repository, simplifying dependency management but potentially increasing complexity as the codebase grows. |
| Polyrepo | Each microservice has its own repository, allowing independent versioning and deployment but requiring more coordination for shared changes. |
Transitioning from monolithic to microservices architecture enables greater flexibility, scalability, and maintainability. By following best practices for service decomposition, communication, and code management, organizations can build robust, modern applications that adapt to changing business needs.
(3) Microservices allow different technology stacks for each service, unlike monolithic architectures that require a single stack.
| Strategy | Description |
|---|---|
| A. Monorepo | 1. Each microservice has its own repository, allowing independent versioning and deployment |
| B. Polyrepo | 2. All microservices are stored in a single repository, simplifying dependency management |
A-2, B-1.
Microservices architecture enables independent release cycles for each service, reducing the risk of system-wide failures.
True. Each microservice can be released independently, minimizing the impact of changes and failures.