AlgoMaster Logo

What Microservices Actually Are

10 min readUpdated November 11, 2026
Listen to this chapter
Unlock Audio

Microservices have become one of the most widely discussed architectural approaches in modern backend engineering. Companies like Netflix, Amazon, and Uber have used microservices to build and operate large-scale applications.

But there's a common misunderstanding. Many developers think microservices simply mean breaking a large application into smaller applications that communicate over APIs. That's part of the idea, but it doesn't capture what makes microservices useful.

Microservices are fundamentally about organizing a system into independently owned, deployable, and loosely coupled services, each responsible for a specific business capability.

To understand what that means, let's start with a familiar example.

1. Understanding Microservices Through an Example

Imagine you're building an e-commerce application. The application needs to support several features:

  • Users can browse products.
  • Customers can add products to their shopping carts.
  • Customers can place orders.
  • Payments must be processed.
  • Inventory must be updated.
  • Customers receive notifications about their orders.

One approach is to build everything inside a single application. The product catalog, shopping cart, order processing, payments, inventory management, and notifications all live in the same codebase and are deployed together. This is a monolithic architecture.

There's nothing inherently wrong with this approach. In fact, for many applications, it's an excellent starting point.

However, as the application grows, different parts may develop different requirements. For example, the product catalog might receive millions of read requests, while the payment functionality handles fewer but more sensitive transactions. The catalog team may want to deploy changes several times a day, while the payment team follows a stricter release process. If everything must be built, tested, and deployed together, coordinating these changes can become increasingly difficult.

Microservices offer a different way to organize the application. Instead of deploying everything as one unit, we divide the system into services with clear responsibilities. For our e-commerce application, we might create:

ServiceResponsibility
Catalog ServiceManage products and product information
Cart ServiceManage customer shopping carts
Order ServiceCreate and manage orders
Payment ServiceProcess payments
Inventory ServiceTrack and reserve stock
Notification ServiceSend emails and other notifications

Each service contains the application logic associated with its responsibility. The services communicate through well-defined interfaces, such as HTTP APIs, gRPC, or asynchronous messages. Together, they form one application from the customer's perspective, even though the backend consists of multiple independently operating services.

2. The Core Characteristics of Microservices

Not every application made up of multiple services qualifies as a well-designed microservices architecture. Several characteristics distinguish microservices from a collection of loosely organized applications.

Organized Around Business Capabilities

A microservice should represent a meaningful business capability. For example, an Order Service handles order creation, order status, and order lifecycle rules. A Payment Service handles payment initiation, payment status, and interactions with payment providers. These boundaries are based on what the business does rather than how the code is technically organized.

Consider an alternative design with separate services for controllers, business logic, and database access. Although these components run independently, every business operation might require calls across all three services. That creates unnecessary network dependencies and tight coupling.

A better approach is to keep closely related business functionality together. This principle is closely related to Domain-Driven Design, particularly the concept of bounded contexts.

Independent Deployment

One of the biggest benefits of microservices is that services can be deployed independently. Suppose the Catalog Service needs a new search filter. Ideally, the catalog team should be able to implement, test, and deploy that feature without rebuilding or redeploying the Order Service or Payment Service. This allows different teams to release changes at their own pace.

However, independent deployment doesn't mean services can change their interfaces without considering consumers. If the Catalog Service removes an API field used by the Cart Service, that change could break the application. Services still need stable contracts, backward-compatible changes, and appropriate testing.

Loose Coupling and High Cohesion

Two important architectural principles are loose coupling and high cohesion.

High cohesion means functionality that belongs together stays together.

For example, all logic related to payment processing should generally live within the Payment Service rather than being scattered across multiple services.

Loose coupling means services depend on each other as little as reasonably possible.

For example, the Order Service should interact with the Payment Service through a defined interface rather than depending on its internal classes or database tables. This makes it easier to modify one service without changing several others. Loose coupling doesn't eliminate communication. It reduces unnecessary knowledge and dependencies between services.

Independent Data Ownership

In a microservices architecture, each service should own the data associated with its business capability. For example:

  • Order Service owns order records.
  • Payment Service owns payment transactions.
  • Inventory Service owns stock information.

Other services shouldn't directly modify that data through the owning service's private database tables. Instead, they interact through APIs or events. This is often called the database-per-service pattern.

Here is how the Order Service reaches payment data through the owning service instead of its private tables:

This separation allows services to change their internal storage implementations without forcing unrelated services to change. However, it also introduces challenges with distributed transactions, data duplication, and eventual consistency.

Independent Scaling

Different services may experience different workloads. Consider our e-commerce application. During a major sale, the Catalog Service might receive hundreds of thousands of product browsing requests per second. Meanwhile, the Payment Service might handle only a fraction of that traffic.

In a microservices architecture, we can scale the Catalog Service independently by adding more instances. There's no need to scale every service equally. This can improve resource efficiency when workloads differ significantly.

However, independent scaling doesn't guarantee that the entire system scales automatically. A shared database, message broker, or downstream dependency can still become a bottleneck.

Decentralized Ownership

Microservices are often designed so that different teams can own different business capabilities. For example, one team might own catalog and search, while another owns orders and checkout. Each team can be responsible for developing, deploying, monitoring, and maintaining its services.

This reduces the coordination required for routine changes. The idea is sometimes described as "you build it, you run it."

However, microservices don't require every service to have a dedicated team. A small team might own several services, while a larger service might require multiple engineers working together. The goal is clear ownership and manageable coordination, not a fixed relationship between team count and service count.

3. How Microservices Communicate

Because microservices run as separate processes, they need mechanisms to exchange information. There are two broad approaches.

Synchronous Communication

In synchronous communication, one service sends a request to another and waits for a response. For example, the Order Service might call the Inventory Service to check whether an item is available. A simplified request might look like this:

The Inventory Service returns the available stock information. Common technologies include REST over HTTP and gRPC. Synchronous communication is useful when a service needs an immediate answer.

However, it introduces runtime dependencies. If the Inventory Service becomes unavailable, the Order Service may be unable to complete the operation. Network latency, timeouts, and cascading failures must also be considered.

Asynchronous Communication

In asynchronous communication, services exchange messages without requiring the sender to wait for the receiver to finish processing them. For example, after an order is confirmed, the Order Service might publish an event:

The Notification Service consumes the event and sends an order confirmation email. The Order Service doesn't need to wait for email delivery. Technologies such as Kafka, RabbitMQ, and cloud-managed messaging services are commonly used for asynchronous communication.

This approach can reduce runtime coupling and improve resilience. However, it introduces challenges such as duplicate messages, delayed processing, event ordering, and eventual consistency.

Neither communication approach is universally better. Most real-world microservices architectures use a combination of synchronous and asynchronous communication based on business requirements.

The two styles look like this side by side, using the inventory check and the order confirmation event from above:

4. Microservices Are Not Just Small Services

The word micro often creates confusion. Does a microservice need to contain fewer than 1,000 lines of code? Should every database table have its own service? Should every API endpoint become a separate service? The answer is no.

There's no universally accepted limit on how much code a microservice can contain.

A service might contain a few thousand lines of code or significantly more. What matters is whether it represents a cohesive business capability and can evolve with limited coordination with other services.

Consider a Payment Service. It might support payment authorization, capture, refunds, reconciliation, and integration with several payment providers. That could be a substantial amount of code. But these responsibilities may still belong together because they form a closely related business capability. Splitting them into separate services purely to reduce code size could make the architecture harder to maintain.

5. What Microservices Do Not Guarantee

Microservices provide architectural flexibility, but they don't automatically solve every engineering problem.

They Don't Automatically Improve Performance

A monolithic application can call internal functions directly. Microservices often require network communication, which adds latency, serialization overhead, and opportunities for failure. For some workloads, this can make microservices slower than a monolith.

They Don't Automatically Improve Reliability

Separate services can isolate certain failures. However, a failure in a critical dependency can still affect multiple services. Poorly configured retries or synchronous dependency chains can even create cascading failures. Reliability requires careful design, not merely distributing components.

They Don't Eliminate Coupling

Services can be deployed separately while remaining tightly coupled through shared databases, incompatible API changes, or complicated workflows. Such architectures are sometimes described as distributed monoliths. They introduce distributed systems complexity without delivering much independent evolution.

They Don't Automatically Increase Development Speed

Microservices can help multiple teams work independently. But a small team maintaining dozens of services may spend more time managing infrastructure, deployments, and debugging than delivering product features. The benefits depend heavily on system size, organizational structure, and operational maturity.

6. Microservices vs Distributed Monolith

Imagine an application with five independently deployed services. Every request passes through all five services. All services share the same database tables. A change to one service frequently requires coordinated changes and deployments across the others.

Technically, the application consists of multiple processes communicating over a network. But architecturally, it's still tightly coupled. This is a distributed monolith.

Compare that with an architecture where services own their business capabilities, control their data, expose stable interfaces, and can deploy most changes independently. That's much closer to the intended microservices model.

The contrast between the two architectures comes down to how requests and data cross service boundaries:

The difference is not the number of running applications. It's the degree of independence and the quality of the boundaries between them.

7. When Microservices Make Sense

Microservices are particularly useful when an application has multiple business capabilities that need to evolve independently. They can be valuable when:

  • Multiple engineering teams need independent ownership and release cycles.
  • Different parts of the application have significantly different scaling requirements.
  • The application has well-understood business domains.
  • Independent deployment and failure isolation provide meaningful benefits.
  • The organization has the infrastructure and operational expertise to manage distributed systems.

On the other hand, a modular monolith may be more appropriate for a small application with a single team, rapidly changing requirements, and limited operational resources. A modular monolith can still provide clear internal boundaries without introducing network communication between every component. Microservices should be adopted when their benefits justify their additional complexity.

Key Takeaways

Microservices are not simply small applications connected through APIs. They represent a way of designing software around business capabilities, independent ownership, loose coupling, and independent evolution. A well-designed microservices architecture allows different parts of a system to be developed, deployed, and scaled with limited coordination.

But achieving that independence comes with costs. Distributed communication, data consistency, service failures, deployment infrastructure, and observability all become more challenging.

The most important takeaway is that microservices are a tool for managing complexity, not a way to eliminate it. They trade some of the simplicity of a single application for greater independence between parts of a larger system. Understanding when that trade-off is worthwhile is essential for designing good architectures.

Quiz

What Microservices Actually Are Quiz

10 quizzes