惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
量子位
V2EX - 技术
V2EX - 技术
K
Kaspersky official blog
Know Your Adversary
Know Your Adversary
Hacker News - Newest:
Hacker News - Newest: "LLM"
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
I
Intezer
H
Heimdal Security Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
S
SegmentFault 最新的问题
阮一峰的网络日志
阮一峰的网络日志
博客园_首页
博客园 - Franky
GbyAI
GbyAI
T
The Blog of Author Tim Ferriss
Recorded Future
Recorded Future
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Vercel News
Vercel News
Apple Machine Learning Research
Apple Machine Learning Research
The Hacker News
The Hacker News
T
Tenable Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
雷峰网
雷峰网
WordPress大学
WordPress大学
Blog — PlanetScale
Blog — PlanetScale
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Webroot Blog
Webroot Blog
L
LangChain Blog
C
Check Point Blog
N
News | PayPal Newsroom
L
LINUX DO - 热门话题
T
Tor Project blog
V
Visual Studio Blog
Microsoft Security Blog
Microsoft Security Blog
S
Security Affairs
Schneier on Security
Schneier on Security
Hacker News: Ask HN
Hacker News: Ask HN
Stack Overflow Blog
Stack Overflow Blog
Y
Y Combinator Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Security Latest
Security Latest
MyScale Blog
MyScale Blog
Cyberwarzone
Cyberwarzone
N
Netflix TechBlog - Medium
Scott Helme
Scott Helme
PCI Perspectives
PCI Perspectives
The Last Watchdog
The Last Watchdog
人人都是产品经理
人人都是产品经理
W
WeLiveSecurity

The System Design Newsletter

How to use NotebookLM Fine Tuning AI Models Kubernetes Architecture Graph based Agent Memory How does CDN work Agent to Agent Protocol Claude Folder System Design Mobile What is AI Infrastructure Agentic Engineering How do Docker containers work Design a Payment System OpenClaw Architecture AI Based Knowledge Management System Agentic AI Use Cases Virtualization Architecture AI Agent Memory - A Deep Dive Machine Learning System Design Interview Mobile System Design Interview AI chat assistant Multi Agent System LLM Evals What is a Vector Database Agentic Design Patterns Software Engineer Resume AI Concepts Generative AI System Design AWS S3 System Design Mobile System Design Mobile System Design Interview How RAG Works How Do AI Agents Work What Is Reinforcement Learning System Design Fundamentals
Microservices Design Patterns
Neo Kim · 2026-07-23 · via The System Design Newsletter

Some of these microservice patterns are foundational, and some are quite advanced. ALL of them are super useful to software engineers building scalable systems.

Curious to know how many were new to you:

  1. API Gateway,

  2. Database per Service,

  3. Circuit Breaker,

  4. Event-Driven Messaging,

  5. Service Discovery,

  6. Retry with Backoff,

  7. Decompose by Business Capability,

  8. Saga,

  9. Health Check API,

  10. Distributed Tracing,

  11. Service Instance per Container,

  12. API Composition,

  13. Transactional Outbox,

  14. Remote Procedure Invocation (REST/gRPC),

  15. Backends for Frontends (BFF),

  16. Bulkhead,

  17. Idempotent Consumer,

  18. Strangler Fig,

  19. CQRS,

  20. Sidecar/Service Mesh,

  21. Anti-Corruption Layer,

  22. Event Sourcing.

For each, I’ll share:

  • What it is in plain English & how it works,

  • A real-world analogy (if I found one),

  • Tradeoffs,

  • Why it matters.

Let’s go!

The most dangerous app in your company was built by someone in finance last Tuesday (Partner)

The number of vibe-coded apps in enterprise environments has skyrocketed.

Yet most vibe-coded apps cannot handle customer data securely, comply with your internal workflows, or pass production processes.

i.e., they “break” your company standards.

So your apps become an IT problem when you ask yourself these questions:

  • Where does the data live & who can access the app?

  • Where are the audit logs & how to enforce company security policies?

  • Can this safely reach production?

INTRODUCING SUPERBLOCKS

(Instead of cleaning up later, it makes IT the foundation from day one.)

  • Apps deploy inside your own AWS account and VPC, so sensitive data stays under your control.

  • Company login, role-based permissions, audit logs, and governance get enforced automatically across all apps.

  • Every deployment gets scanned for vulnerabilities before it reaches production.

So you build production-ready apps instead of demos that need to be rebuilt later…and your business moves faster.

If you’re serious about enterprise AI app development, try Superblocks right now:

TRY SUPERBLOCKS NOW

(Thanks to Superblocks for partnering on this post.)

An application programming interface (API) gateway is a single entry point for your services.

A client must “never” call services directly.

The gateway gives them a single address and forwards each request to the correct service. Plus, it centralizes the cross-cutting concerns: authenticates requests, enforces rate limits, terminates Transport Layer Security (TLS), caches responses, and translates protocols.

i.e., your services stay focused on business logic instead of repeating cross-cutting logic across the codebase.

A hotel front desk routes guest requests.

You never walk into the kitchen or the laundry room yourself. Instead, you ask the desk, and they route your request to the right department.

i.e., one point of contact hides a dozen moving parts.

A gateway simplifies clients1, centralizes security and observability, and lets you reshape services behind a stable interface.

But it adds a network hop, and could become a single point of failure if you run only one instance. Plus, it can become a development bottleneck when every team must change it, and it risks becoming a mini-monolith if you add business logic inside.

So run it behind a load balancer for high availability and keep it thin.

Use an API gateway when many services sit behind one public API, mobile and web apps need a single endpoint, or you want to handle authentication and rate limits in one place.

It can also help you move clients from a monolith to microservices without breaking the existing API…

Some popular implementations are Kong, NGINX, Envoy, AWS API Gateway, and Apigee.

TIP: Pair it with the Backends for Frontends2 pattern (more on this in concept 15) when different clients, such as web and mobile apps, need different APIs.

Each service has a private database that NO other service directly touches.

A service keeps its own data and exposes data only through its API.

Other services ask for what they need instead of directly reaching into the tables. This keeps services loosely coupled: you can change a schema, switch between databases, or add an index, and nothing breaks…

i.e., database becomes an implementation detail hidden behind the service boundary.

A shop with its own stockroom that only its staff enter.

Customers ask at the counter, and the staff fetches what’s needed. Nobody wanders into the back.

Because one team controls the stockroom, it stays organized, and changes surprise nobody.

Private databases give each team independence, isolate failures, and let each service pick the right storage for its job.

But queries that span services get harder, you lose cross-table joins & foreign keys, and keeping data consistent across services needs patterns such as Saga, API Composition, and Transactional Outbox3.

A shared database looks easier on day one but silently couples every service over time.

Every microservices system has independent deploys, or services with very different data shapes & access patterns.

This pattern makes microservices independent. So treat a “shared database” as a red flag.

Popular data stores are PostgreSQL, MySQL, MongoDB, and DynamoDB.

Share

A circuit breaker temporarily stops calls to a failing service, giving it time to recover and protecting callers from cascading failures.

The breaker wraps a remote call & watch failures:

  • When calls succeed, it stays closed and traffic flows.

  • When failures cross a threshold, it opens, and every call fails fast without touching the failed service.

  • After a cool-down, it goes half-open and lets one trial call through.

  • If this succeeds, it closes again; if not, it opens & waits longer.

This turns a slow, resource-draining timeout into an instant, cheap rejection.

An electrical fuse trips when too much current flows.

Instead of letting a fault burn down the house, the fuse cuts the circuit. Once the problem is fixed, you reset it and power returns.

The breaker does the same for a failing dependency, cutting it off before it drags everything down.

They add error-handling paths and need careful tuning of thresholds & timeouts.

Plus, they can trip on a “brief” blip and reject good traffic, and require monitoring so you notice an open circuit.

Calls to a remote/third-party dependency must degrade gracefully, or one slow service must NOT take down the whole request path.

Resilience4j (Java), Polly (.NET), and Envoy proxy implement breakers, and a service mesh (more on this in concept 20) such as Istio can apply them without code changes.

Services communicate by publishing & consuming events through a “message broker” instead of calling each other directly & wait.

A direct call couples the caller to the callee in time: the caller blocks for a reply, and a failure on either side breaks the request.

Event-driven messaging breaks this link. A service publishes an event to a broker and moves on, and any number of consumers can subscribe & react on their own schedule.

This publish-and-subscribe style also lets you add new consumers later without touching the producer.

A phone call versus a group channel:

A phone call needs both people free at the same instant. A message posted to a group channel waits until each reader is ready, and everyone interested sees it.

New people can join the group channel later and still get the updates.

It trades simple request-reply for eventual consistency.

Plus, debugging gets harder across an event chain, and there’s a need to handle duplicate & out-of-order delivery.

Workflows where steps can happen asynchronously, fanning one event out to many services, decoupling producers from consumers, or smoothing traffic spikes with a buffer.

Apache Kafka, RabbitMQ, AWS SNS and SQS, and Google Pub/Sub are popular broker implementations.

TIP: Pair it with the Idempotent Consumer pattern4 (more on this in concept 17), because at-least-once delivery means duplicates will happen.

Share

Service discovery lets services find each other by name through a registry, which updates itself as instances start, stop & move.

In microservices architecture, instances come and go, and their addresses change constantly. i.e., hard-coding a location breaks the moment a service moves.

Each instance registers its address with a service registry when it starts and de-registers when it stops. Callers query the registry by name to get a current, healthy address.

Here are 2 ways to implement service discovery:

  • client-side, where the caller queries the registry and load-balances itself,

  • server-side, where a load balancer or the platform does it.

A contacts app instead of numbers scribbled in pen…

When a friend changes their number, the app updates and you can still reach them. The registry keeps every service’s current contact details, so callers always reach them.

  • It adds infrastructure,

  • Makes the registry a critical dependency,

  • Needs health checks to stay accurate, and a stale cached lookup can still send traffic to a dead instance.

Fixed addresses are NOT practical for auto-scaling fleets, containerized deployments with shifting IPs, blue-green and rolling deploys5.

Consul, etcd, and Netflix’s Eureka are classic registries, while Kubernetes builds discovery in through DNS and Services.

Most service meshes6 include it, so you often get discovery for free at scale.

Retry with backoff reattempts a failed call a few times with a growing delay, turning brief glitches into successes without hammering a struggling service.

Networks blip, and a call that fails once often succeeds on the next try.

A naive retry loop can stampede a service that’s already down. Backoff fixes this by waiting longer between each attempt, usually “doubling” the delay, and jitter adds randomness so many clients don’t retry in lockstep.

A retry limit and a timeout cap the total effort so a stuck call gives up instead of hanging forever.

Redialing a busy phone line.

You wait a moment and try again, not forty times in a row, and you give up after a few rings rather than holding the line all day.

Each wait is a little longer so you’re not jamming the line.

Retrying a non-idempotent call can double-charge or double-write; aggressive retries can amplify an outage into a retry storm, and extra attempts raise tail latency7 for the request.

TIP: Only retry idempotent operations, always add jitter, and pair retries with a circuit breaker.

Calls to flaky networks/third-party APIs, transient database errors, or any remote operation that’s safe to repeat.

Resilience4j & Polly provide retry with exponential backoff and jitter out of the box.

Timeout, retry with backoff, and circuit breaker together are standard resilience mechanisms for remote calls.

Split a system into services along the natural lines of the business, using business capabilities and domain-driven design8 to draw the boundaries.

The HARD part of microservices is deciding where one service ends and the next begins…

Here are two methods to guide you:

  • Decomposing by business capability splits the system by what the organization does, such as orders, payments, or shipping. Then gives each capability a service.

  • Decomposing by subdomain uses domain-driven design (DDD) to model the business and carve it into subdomains.

Each becomes a bounded context: a boundary inside which every term carries one precise meaning.

Boundaries drawn this way follow the business, which shifts far more slowly than the code.

Think of a company with different departments:

Sales handles selling, Shipping handles deliveries, and Payments handles billing. Each department owns its own work. Even the same word can mean different things. For example, a "customer" means an order and delivery address to Shipping, but payment details & invoices to Payments.

A bounded context keeps each meaning separate, so teams don't interfere with each other.

Choosing the right service boundaries needs a good understanding of the business.

If you split services the wrong way, they end up constantly calling each other. While changing those boundaries later becomes difficult because each service already owns its own data and responsibilities.

Use this pattern when you’re building a new microservices system, breaking a monolith into smaller services, or giving each team ownership of a specific business area.

Reminder: this is a teaser of the subscriber-only newsletter, exclusive to my golden members.

When you upgrade, you’ll get:

  • High-level architecture of real-world systems.

  • Deep dive into how popular real-world systems work.

  • How real-world systems handle scale, reliability, and performance.

Unlock Full Access

Ready for the best part?