Microservice Architecture and Its 10 Most Important Design Patterns
This article explains the evolution of software architecture toward microservices, defines microservice architecture, outlines its key characteristics, advantages and disadvantages, and then details ten essential design patterns—including database per service, event sourcing, CQRS, Saga, BFF, API gateway, Strangler, circuit breaker, externalized configuration, and consumer‑driven contract testing—while advising when each should be applied.
Since the 1960s, software engineers have struggled with the complexity of large systems, using techniques such as modularization, separation of concerns, and SOA, but these approaches no longer scale for modern web‑level applications.
Microservice architecture continues the divide‑and‑conquer principle by splitting a large system into independently deployable services that communicate via lightweight synchronous (e.g., REST, gRPC) or asynchronous (e.g., messaging) network calls.
Key characteristics of microservices
The application is divided into independent subprocesses, each containing multiple internal modules.
Services are vertically sliced by business domain rather than horizontally modularized.
Boundaries are external; services interact over the network.
Each service runs as an independent process and can be deployed separately.
Communication is lightweight and does not require a sophisticated messaging layer.
Advantages
Improved development scale and speed.
Supports iterative and incremental development.
Leverages modern ecosystems (cloud, containers, DevOps, serverless).
Enables horizontal and fine‑grained scaling.
Reduces cognitive load per developer.
Disadvantages
Increases the number of active components (services, databases, containers, frameworks).
Shifts complexity from code to infrastructure.
More RPC calls and network traffic.
Security management becomes more challenging.
System design grows harder and distributed‑system complexity rises.
When to adopt microservices
Large‑scale web applications.
Cross‑team enterprise projects.
Long‑term value outweighs short‑term cost.
Team has architects or senior engineers capable of designing microservices.
Design Pattern 1: Database per Microservice
Each service should own its data store, either a separate logical schema within a shared physical database or a completely independent database, to avoid tight coupling at the persistence layer.
Pros
Data ownership is clear.
Reduces coupling between development teams.
Cons
Data sharing across services becomes harder.
Maintaining ACID transactions across services is difficult.
Designing the data split is challenging.
Design Pattern 2: Event Sourcing
Instead of storing the current state, store every state‑changing event; services can reconstruct state by replaying events.
Pros
Provides atomic operations for highly scalable systems.
Automatically records history and enables temporal queries.
Supports loose coupling and event‑driven architectures.
Cons
Reading state requires replaying events or a separate read model (CQRS).
Overall system complexity increases.
Needs handling of duplicate or missing events.
Design Pattern 3: Command‑Query Responsibility Segregation (CQRS)
Separate the write side (commands) from the read side (queries), often paired with event sourcing.
Pros
Faster reads in event‑driven microservices.
High availability of data.
Independent scaling of read and write stores.
Cons
Read store is eventually consistent.
Added complexity can jeopardize projects if misused.
Design Pattern 4: Saga
Implements distributed transactions by chaining local transactions, each publishing an event that triggers the next step; compensating transactions roll back on failure.
Pros
Provides consistency for highly scalable, loosely coupled systems.
Works with databases that do not support two‑phase commit.
Cons
Requires handling of transient failures and idempotency.
Debugging becomes harder as the number of services grows.
Design Pattern 5: Backend‑for‑Frontend (BFF)
Creates a dedicated backend for each UI (web, mobile, TV) to tailor APIs and improve security.
Pros
Separates concerns per UI, enabling optimization.
Improves security.
Reduces chatty communication between UI and downstream services.
Cons
Potential code duplication across BFFs.
Requires careful design to keep business logic out of the BFF.
Design Pattern 6: API Gateway
Acts as a façade between clients and microservices, handling routing, aggregation, and cross‑cutting concerns such as SSL termination, authentication, rate limiting, and logging.
Pros
Provides loose coupling between front‑end and back‑end.
Reduces the number of client‑to‑service calls.
Centralizes security and other cross‑cutting concerns.
Cons
Can become a single point of failure.
Introduces additional latency.
May become a bottleneck without proper scaling.
Design Pattern 7: Strangler
Gradually replaces parts of a monolithic application with microservices behind a façade (often the API gateway) until the legacy system can be retired.
Pros
Enables safe, incremental migration.
Allows parallel development of new features.
Controls migration pace.
Cons
Sharing data between legacy and new services is challenging.
Facade adds latency.
End‑to‑end testing becomes more complex.
Design Pattern 8: Circuit Breaker
Prevents cascading failures by short‑circuiting calls to an unhealthy service after a configurable failure threshold is reached.
Pros
Improves fault tolerance and resilience.
Stops cascading failures.
Cons
Requires sophisticated exception handling and monitoring.
Needs manual reset mechanisms.
Design Pattern 9: Externalized Configuration
Moves configuration out of the codebase into environment‑specific sources, reducing security risk and eliminating the need to rebuild for config changes.
Pros
Reduces security exposure.
Allows runtime configuration changes without recompilation.
Cons
Requires a framework that supports externalized configuration.
Design Pattern 10: Consumer‑Driven Contract Testing
Consumers define expectations (contracts) for provider APIs; providers run these contracts as part of their test suites to catch breaking changes early.
Pros
Detects provider changes quickly.
Improves robustness in large, multi‑team systems.
Enhances team autonomy.
Cons
Additional effort to create and maintain contracts.
Misaligned contracts can cause production failures.
In summary, microservice architecture offers scalability and long‑term benefits for large enterprise applications, but it is not a universal silver bullet. Teams should follow best practices and adopt the above reusable design patterns—especially database per service, event sourcing, CQRS, Saga, BFF, API gateway, circuit breaker, Strangler, externalized configuration, and consumer‑driven contract testing—to build robust, maintainable systems.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
