Browse Courses

Overview of Microservices

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.


Introduction to Application Architectures

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.


Monolithic Architecture

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” >}}


Challenges of Monolithic Applications

  • Coordination between teams becomes complex due to tightly coupled code.
  • Scaling individual features is not possible; the entire application must be scaled, increasing infrastructure costs.
  • Dependency conflicts arise when different features require different versions of the same module.
  • The release process is slow, as any change requires building, testing, and deploying the whole application.

Microservices Architecture

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” >}}

Criteria of Creating Micro Services

  • When an application is split into micro services, number of questions to be asked:
    1. How to break down the existing code?
    2. What code goes where?
    3. How many services do we need?
    4. How big or small should they be?
    5. How do they communicate with each other?

Key Principles and Best Practices

  • Decompose the application based on business functionalities, not technical layers.
  • Each microservice should perform a single, isolated job.
  • Services must be self-contained and independently deployable, enabling loose coupling.
  • Release cycles for each service are independent, allowing faster and safer deployments.

Communication Between Microservices

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” >}}

Synchronous Communication (API Calls)

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” >}}

  • It is simple to implement and understand, but can lead to tight coupling between services.

Asynchronous Communication (Message Broker)

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.

Service Mesh

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” >}}

  • It provides advanced features like load balancing, retries, and circuit breaking.
  • Service meshes can simplify complex communication patterns and improve overall system reliability.

Comparison of Communication Types

Communication TypeDescription
SynchronousServices call each other’s APIs and wait for responses, leading to tight coupling.
AsynchronousServices send messages to a message broker, allowing them to operate independently and improving resilience.
Service MeshA dedicated layer that manages service communication, providing advanced features like load balancing and retries.

Disadvantages of Microservices

While microservices offer numerous benefits, they also come with challenges:

  1. Complexity: Managing multiple services can be more complex than a monolithic architecture. Specially configuring and maintaining communication can be daunting.
    • For example, one service may be sending a message to another service expecting a response, but if the second service is down, it can block the entire request chain, leading to potential bottlenecks. It becomes more difficult to monitor if multiple instances of the same service are distributed across servers.
  2. Data Consistency: Ensuring data consistency across services can be challenging, especially in distributed systems.
    • For example, if one service updates a record, other services may not immediately reflect that change, leading to potential data discrepancies.
  3. Network Latency: Inter-service communication can introduce latency, impacting performance.
    • Each service call adds network overhead, which can slow down the overall application response time.
    • For example, if a user account service needs to call a payment service, the time taken for the request and response can add significant latency, especially if multiple services are involved in a single user action.
  4. Deployment Overhead: Deploying and managing multiple services requires more sophisticated DevOps practices.
    • Coordinating deployments across services can be complex, requiring robust CI/CD pipelines and monitoring tools.
    • For example, if one service is updated, it may require changes in other dependent services, complicating the deployment process.

Solutions to Microservices Challenges

To address these challenges, organizations can adopt several strategies:

ChallengeSolution
ComplexityImplement API gateways to manage communication and reduce direct service-to-service calls.
Data ConsistencyUse distributed transactions or eventual consistency models to manage data across services.
Network LatencyOptimize service communication through techniques like caching, load balancing, and asynchronous messaging.
Deployment OverheadAdopt containerization and orchestration tools (e.g., Kubernetes) to streamline deployment and scaling processes.

Tools to Manage Microservices

ToolDescription
API GatewayManages traffic between clients and microservices, providing a single entry point and enabling features like authentication, logging, and rate limiting.
Service MeshProvides a dedicated infrastructure layer for managing service-to-service communication, offering features like load balancing, service discovery, and observability.
Container OrchestrationTools like Kubernetes automate the deployment, scaling, and management of containerized applications, simplifying microservices management.

Companies Providing the Tools

ToolDescription
API GatewayCompanies like Kong, NGINX, and Amazon API Gateway provide robust API gateway solutions.
Service MeshCompanies like Istio, Linkerd, HashiCorp Consul, and Consul offer service mesh solutions for managing microservices communication.
Container OrchestrationCompanies like Red Hat OpenShift, VMware Tanzu, and Google Kubernetes Engine (GKE) provide container orchestration platforms to manage microservices.

Code Management Strategies

Managing code for microservices can be approached in different ways:

StrategyDescription
MonorepoAll microservices are stored in a single repository, simplifying dependency management but potentially increasing complexity as the codebase grows.
PolyrepoEach microservice has its own repository, allowing independent versioning and deployment but requiring more coordination for shared changes.

Conclusion

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.


FAQ

Monolithic architecture combines all application components into a single unit, while microservices architecture breaks the application into independent, self-contained services responsible for specific business functionalities.

Scaling individual features is not possible; the entire application must be scaled, leading to higher infrastructure costs and less flexibility.

Loose coupling allows each microservice to be developed, deployed, and scaled independently, reducing dependencies and enabling faster, safer releases having their own independent versions

Services communicate by sending HTTP requests to each other’s API endpoints and waiting for responses.

  1. Independent deployment of services
  2. Easier scaling of individual features
  3. Single technology stack for all components
  4. Faster release cycles for specific functionalities
(3) Microservices allow different technology stacks for each service, unlike monolithic architectures that require a single stack.

A message broker enables asynchronous communication by receiving messages from one service and forwarding them to the appropriate service, decoupling senders and receivers.

StrategyDescription
A. Monorepo1. Each microservice has its own repository, allowing independent versioning and deployment
B. Polyrepo2. All microservices are stored in a single repository, simplifying dependency management
A-2, B-1.

Service mesh provides a dedicated layer for managing service-to-service communication, handling routing, security, and observability without modifying application code.

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.

The application should be broken down based on business functionalities, ensuring each service is responsible for a specific business capability.