Skip to main content

Command Palette

Search for a command to run...

Understanding Microservices: A Starter Guide

Updated
•5 min read•View as Markdown

In modern software development, microservices architecture has become one of the most popular approaches for building large-scale applications. Instead of creating one large, tightly coupled application, microservices break the system down into small, independent services that work together to form a complete product.

Think of it like this: an application is divided into small independent modules such as user signup, product catalog, payment gateway, and shopping cart. Each of these modules is developed, deployed, and scaled independently, yet collectively they form a single, cohesive application.


Why Microservices?

To understand the benefits of microservices, let’s first compare it with the monolithic architecture.

Monolithic Architecture

  • In a monolithic system, the entire application is developed and deployed as one single unit.

  • All modules (e.g., login, cart, payment, product catalog) are tightly coupled and deployed together.

  • Scaling happens at the level of the whole application.

For example, consider an e-commerce app. If traffic increases suddenly, you might scale up (vertical scaling) by increasing the RAM/CPU of your server (e.g., from 2 GB to 6 GB). But vertical scaling has limits. Eventually, you’ll switch to horizontal scaling deploying multiple copies of the same monolithic application behind a load balancer.

Here’s the problem:
If only the product catalog module experiences heavy load, you still end up scaling the entire application including signup, payment, and cart even if they don’t need it. This is inefficient and costly.

Microservices Architecture

Microservices solve this issue by allowing independent deployment and scaling.

  • Each feature (e.g., signup, product catalog, payment gateway) is developed as a separate service.

  • If load increases only on the catalog service, you scale just that service, not the entire application.

  • This enables zero-downtime deployments, faster updates, and more efficient scaling.

In simple terms: microservices give you fine-grained control over your application.


Key Advantages of Microservices

  1. Independent Deployability
    Each service can be deployed independently without affecting the rest of the application. This reduces downtime and accelerates development cycles.

  2. Scalability
    Services can be scaled vertically or horizontally based on demand. For example, if only the payment gateway faces high load, you scale just that service.

  3. Fault Isolation
    Since each service is self-contained, a failure in one service (e.g., payment) doesn’t necessarily crash the entire system. Other services can continue to function normally.

  4. Technology Flexibility
    Teams have the freedom to build their services using different programming languages, frameworks, or databases, as long as they communicate via APIs.

  5. Smaller, Focused Teams
    Teams can own individual services, improving productivity and enabling parallel development.


Challenges with Microservices

While microservices bring clear advantages, they also introduce new complexities:

  1. Infrastructure Complexity
    Managing multiple environments, deployments, configurations, and monitoring becomes more complex compared to a single monolithic application.

  2. Latency
    Services often need to communicate with each other over the network. These service-to-service calls can add latency, especially when one service calls another, which calls another, and so on (known as “service hopping”).

  3. Risk of Failure Cascades
    If one critical service fails (e.g., payment), dependent services (e.g., order) may also fail, causing a chain reaction. Proper fault-tolerance mechanisms (circuit breakers, retries, fallbacks) are necessary.

  4. Data Management
    Each microservice usually manages its own database. While this reduces coupling, it makes maintaining data consistency across services more challenging.

  5. Operational Overhead
    Continuous monitoring, logging, debugging, and orchestration (using tools like Kubernetes, Docker, or service meshes) require advanced DevOps practices.


Let’s architect a simple microservice for e-commerce

  1. First, we need to identify our frontend applications and microservices.

    1. Frontend: We have two applications one customer-facing UI and one admin-facing UI.

    2. Microservices: We have the following services Auth Service, Notification Service, Order Service, and Product Catalog Service.

  2. Another important point to understand is that the frontend or client will not communicate directly with the individual microservices. Doing so would create unnecessary overhead for the frontend, which would need to manage multiple service addresses. It would also introduce issues if any service goes down, and it is not a secure approach. To address this, we introduce an API Gateway, which manages all communication between the frontend and the backend.

    An API Gateway in a microservices architecture serves as the single entry point for all client requests. It acts as a reverse proxy, routing requests to the appropriate backend microservices, aggregating responses from multiple services into a single optimized response for the client, and handling cross-cutting concerns such as authentication, authorization, rate limiting, and security.

    1. Each service will have its own database. This is very important to remember, because if multiple services share the same database, they are no longer true microservices but instead form a distributed monolith.

      1. It is also possible that each service may need to communicate with third-party services. For example, the Product Catalog Service might use S3 or another object store to store product images, the Order Service might integrate with Stripe for payment processing, and the Notification Service might use an SMS or email provider to deliver messages.

        1. Now, how will these microservices communicate with each other internally? The first approach is direct synchronous communication, which can be achieved using REST APIs or gRPC. In this way, each service can directly call and interact with another service.

          1. Now, let’s say the Order Service has a dependency on the Product Catalog Service. For example, when a new order is placed, the Order Service needs to call the Product Catalog Service (via an API call or gRPC) to update product quantities. But if the Product Catalog Service is down, the update will fail.

            To handle this, we introduce asynchronous communication using a queue or message broker (e.g., Kafka).In this setup, the Order Service will publish a message to a specific topic (e.g., product-updates ). The message broker will store the event safely. Once the Product Catalog Service becomes available again, it will subscribe to that topic and process the pending messages, completing the inventory update.

            1. The final component that I see missing is caching. It’s better not to call every service repeatedly when the data hasn’t changed. For example, if the admin UI requests a list of the first 10 users, instead of always querying the service, the API Gateway should first check the cache.

              • If the response is available in the cache, it returns the cached data.

              • If not, it calls the service, retrieves the data, and then updates the cache.