Cloud design patterns are named, reusable answers to problems every distributed system runs into: payloads too big for a queue, clients that can’t wait for a long job, a monolith you can’t rewrite in one go, reads that need a different shape from writes. The Azure Architecture Center and AWS Prescriptive Guidance both publish catalogues. This page sorts about forty patterns into seven families, each with its problem, mechanism, cost, when to skip it and the interview prompt where it shows up.
Picture it first: catering a big Indian wedding
A caterer feeding 2,000 guests over three days relies on a handful of tricks, and each has a cloud twin:
- The kitchen cooks to recipe; buffet counters are laid out by cuisine. Nobody eats from the kitchen: CQRS and materialized views.
- Order slips hang on one rail, and whichever cook is free takes the next. The family table jumps the line. Competing consumers, priority queue.
- “Dessert is out” is announced once, and every table that cares hears it. Publisher-subscriber.
- Gifts go to a counter and guests keep a token. The token travels; the box stays put. Claim check.
- The valet gets a key that starts the car but won’t open the boot. The valet key pattern is named after exactly this.
- At the gate, a guard checks invitations and an usher points you to the right hall. Gatekeeper, gateway routing. The invitation counts because the family vouched for you: federated identity.
- A new kitchen takes over dish by dish while the old one keeps cooking, with a helper translating the old cook’s shorthand. Strangler fig, anti-corruption layer.
- Three venues get three identical kitchens, not one giant one. Deployment stamps.
Map it back: dishes are data, cooks are workers, the gate is your API gateway, and venues are regions or groups of tenants.
The map: where patterns sit
Most patterns live at a predictable spot. Fig. 1 places twelve of them on a food-delivery backend; the sections after it go family by family.
In the interview
Name the problem before the pattern: “photos are up to 20 MB and shouldn’t touch our app servers, so the client uploads with a presigned URL” beats “I’ll use the valet key pattern”. Pattern names without problems sound like a buzzword list.
Data management: shape data for the read
Most data patterns accept an extra copy and some staleness to make an expensive read cheap. Deep dives: event sourcing and CQRS, denormalisation, scaling reads.
| Pattern | Problem | How it works | Use when | Cost; avoid when | Shows up in |
|---|---|---|---|---|---|
| Cache-aside | Hot reads hammer the database | Read cache; on a miss, load from the DB and fill; writes invalidate | Read-heavy, seconds of staleness are fine | Stale reads, stampedes; write-heavy keys | Product page, short-link redirect |
| CQRS | One model can’t serve rich writes and varied reads | Commands hit a write model; queries hit separate models fed by its changes | Read and write shapes or scale diverge | Lag, two models; plain CRUD | News feed, order dashboard |
| Event sourcing | You need history, not just current state | Append every change as an event; state is a replay, sped up by snapshots | Audit, replay, “state as of Tuesday” | Event versioning, erasure; CRUD screens | Ledger, wallet, audit log |
| Materialized view | A query needs joins or aggregates the store can’t do fast | Precompute the answer into its own table, refreshed on change | The same costly query runs constantly | Storage, refresh lag; fast-changing sources | Leaderboard, sales dashboard |
| Index table | Store looks up only by primary or shard key | Keep a table mapping another field to the primary key | Lookups by a second field in a sharded or NoSQL store | Extra write that can drift; low-cardinality fields | User lookup by email |
| Sharding | One node can’t hold the data or the writes | Split rows across nodes by a shard key | Data or writes outgrow one node | Cross-shard queries, rebalancing, hot keys | Chat history, URL shortener |
| Static content hosting | App servers burn cycles serving files | Serve assets from object storage behind a CDN | Images, scripts, video segments | Invalidation; private files need signed URLs | Video streaming, web app assets |
The index table earns its place in a sharded design. Say users are sharded by user_id across 64 shards and someone logs in by email. Without help you ask all 64 shards; with an index table keyed by email, you read one index row, then one shard: 2 reads instead of 64. The index row is a separate write, so make it idempotent and repairable from the source of truth.
CQRS and materialized views usually travel together (Fig. 2). Martin Fowler, who first heard the idea from Greg Young, warns that CQRS adds risky complexity for most systems and belongs in one bounded context, not everywhere.
Messaging and integration: decouple in time
Queues and topics let a producer finish before its consumer starts. Queue-based load leveling lives in the reliability family; the patterns here build on it. Deep dives: message queues, publish/subscribe, long-running jobs.
| Pattern | Problem | How it works | Use when | Cost; avoid when | Shows up in |
|---|---|---|---|---|---|
| Asynchronous request-reply | Work outlasts an HTTP request | Return 202 with a status URL; client polls until it points to the result | Jobs of seconds to hours | Polling load, status storage; fast calls | Report export |
| Competing consumers | One worker can’t keep up | Many workers pull from one queue; each message goes to one worker | Independent jobs, bursty volume | No ordering; needs idempotent handlers | Order processing, email sends |
| Priority queue | Urgent work waits behind bulk work | Separate queues or priorities, with more consumers on urgent ones | Classes need different latency | Starving low priority; when all work is equal | Notifications: OTPs vs promos |
| Publisher-subscriber | Producer shouldn’t know every consumer | Publish once to a topic; each subscription gets a copy | One event, many reactions | Duplicates, schema contracts; a single consumer | “Order placed” fans out |
| Sequential convoy | Parallel consumers break per-entity order | Group messages by key; one consumer per group at a time | Order matters per key, keys are many | A slow key blocks its group; hot keys | Events per trip or account |
| Claim check | Payload too big for the broker | Store the payload; the message carries its key | Payloads near broker limits | Extra hop, orphaned payloads; small messages | Video processing pipeline |
| Pipes and filters | One big job is hard to scale or reuse | Chain small stages through queues; each scales alone | Stages differ in cost, or are reused | Per-hop latency, harder tracing | Media transcoding, log ingestion |
| Messaging bridge | Two brokers can’t talk | A relay consumes from one and republishes to the other | Mergers, broker migrations | Feature mismatch; synchronous needs | RabbitMQ-to-Kafka move |
Claim check in numbers. Amazon SQS caps a message at 1 MiB; its Extended Client Library is the pattern packaged, keeping payloads of up to 2 GB in S3 and sending a pointer. Publish the reference only after the payload write succeeds, expire orphans with a lifecycle rule, and make consumers idempotent, because the same check can arrive twice.
Async request-reply in detail. RFC 9110 calls 202 Accepted “intentionally noncommittal”: the work may still be refused, and the response ought to point to a status monitor. Validate before accepting, so bad input still gets an immediate 400. The finished status answers 303 See Other, which tells the client to GET another URL; Azure’s guidance prefers it to 302, which some clients answer by replaying the POST.
Two details interviewers like. RFC 9110 defines Retry-After for 503 and 3xx responses; on 202 and status responses it is a convention, so document it. And polling cost is jobs in flight ÷ interval: 1,000 jobs at 10 s is 100 GETs/s, cheap if each read is a key lookup. Clients that accept pushes can get a webhook or server-sent events instead. Protect the POST with an idempotency key, or a client that times out starts the job twice.
Coordinating workflows
When one operation spans several services, decide who knows the flow. Deep dives: multi-step workflows, workflow engines, 2PC vs sagas.
| Pattern | Problem | How it works | Use when | Cost; avoid when | Shows up in |
|---|---|---|---|---|---|
| Choreography | A central coordinator couples every team | Each service reacts to events and emits its own | Few steps, independent teams | No one place shows the flow; long flows | Order → payment → kitchen events |
| Scheduler agent supervisor | Multi-step remote work must finish or be undone | Scheduler runs steps from a durable record; agents call services; a supervisor retries or undoes stuck steps | Long workflows with real failures | A coordinator; a single call | Workflow engine |
| Compensating transaction | Committed steps elsewhere can’t be rolled back | Run reverse steps, such as refund or release, in order; make them idempotent | Sagas across services | Visible half-done states; irreversible steps | Trip or ticket cancellation |
Orchestration is easier to debug: one record answers “where is order 42?”. Choreography scales across teams but scatters the flow. Rule of thumb: choreograph two or three steps, orchestrate anything longer.
Edge and gateway: one front door
A gateway does three jobs the Azure catalogue lists separately: routing, offloading and aggregation. Behind it, a backend for frontend serves each client type. Deep dives: API gateway, API composition and BFF, rate limiting.
| Pattern | Problem | How it works | Use when | Cost; avoid when | Shows up in |
|---|---|---|---|---|---|
| Gateway routing | Clients must know every service address | One endpoint routes by path, host or header | Many services, versions, canaries | A hop; must be redundant | Any microservices design |
| Gateway offloading | Every service re-implements TLS, auth, logging | Terminate TLS, validate tokens, log and compress at the edge | Identical cross-cutting concerns | Gateway becomes a team bottleneck | Public API |
| Gateway aggregation | Client makes many calls over a slow network | Gateway fans out inside the data centre, returns one response | Mobile clients, high-latency links | Tail latency of the slowest call; nearby clients | App home screen |
| Backends for frontends | One API serves web, mobile and TV badly | One backend per client type, owned by that client’s team | Clients need different shapes | Duplicated logic; a single client | Mobile vs web vs partner app |
| Throttling | One tenant or spike eats shared capacity | Server caps use per tenant; rejects with 429 or degrades | Shared, multi-tenant services | Some valid requests refused | Rate limiter, public API |
| Rate limiting (client side) | A dependency keeps throttling you | Pace your own calls under its quota with a token bucket or queue | Bulk calls to a metered API | Added delay; latency-critical calls | Bulk import, SMS gateway |
Aggregation is about round trips. Assume a mobile round trip costs about 100 ms and the home screen needs six calls in three dependent waves: 3 × 100 = 300 ms of radio time. One aggregated call costs one round trip plus a few milliseconds of fan-out inside the data centre; AWS’s catalogue calls that fan-out-and-merge step scatter-gather.
Throttling vs rate limiting
Azure names the two sides separately. Throttling protects a service: cap each tenant, reject or degrade the excess. The rate limiting pattern is client-side courtesy: pace your own requests under the provider’s quota so you rarely see a 429. Designs usually need both.
Security: narrow, short-lived access
These patterns shrink what a stolen credential or a hostile request can reach. Deep dives: OAuth 2.0 and OpenID Connect, blob storage, reverse proxies.
| Pattern | Problem | How it works | Use when | Cost; avoid when | Shows up in |
|---|---|---|---|---|---|
| Gatekeeper | Public hosts holding secrets get compromised | A secret-free tier validates and sanitises requests, then forwards to private back ends | Sensitive data, hostile traffic | Extra hop; platform controls suffice | WAF and edge auth |
| Valet key | Big transfers through app servers waste compute | App issues a signed, scoped, expiring token; client talks to storage directly | File uploads and downloads | A leaked URL works until expiry | Dropbox-style uploads |
| Federated identity | Every app storing passwords | Delegate sign-in to a trusted identity provider; apps accept its tokens | SSO, partners, social login | The IdP becomes a critical dependency | Enterprise SSO |
| Quarantine | Untrusted artefacts reach the workload | Land them in an isolated area, scan and validate, then promote | Third-party images, packages, user files | Delay before use; false positives | Scanning uploaded files |
Valet key numbers. An S3 presigned URL can live up to 7 days when signed with Signature Version 4 from the SDK or CLI, but never longer than the credentials that signed it. S3 checks expiry when a request starts, so a running download finishes. It is a reusable bearer token until then, so scope it to one key and one method and keep it short. The win: 10,000 uploads a day at 200 MB is 2 TB, which through the app tier means 2 TB in plus 2 TB out to storage: 4 TB a day the valet key removes.
Azure frames quarantine around third-party artefacts, such as container images and packages, entering your pipeline. The same shape suits user uploads: write to a quarantine bucket, scan, then copy to the bucket you serve from.
Design and evolution: change a running system
These patterns restructure or migrate a system without stopping it. Deep dives: strangler fig and anti-corruption layer, sidecar, ambassador and service mesh, consensus and leader election.
| Pattern | Problem | How it works | Use when | Cost; avoid when | Shows up in |
|---|---|---|---|---|---|
| Strangler fig | Big-bang rewrites fail | A routing façade sends migrated routes to new code, the rest to legacy | Large legacy that must keep serving | Two systems and data sync; small systems | Migrating a monolith |
| Anti-corruption layer | The legacy model leaks into the new design | A translation layer converts between the two models | Old and new semantics differ | Extra hop and service; no business logic in it | Integrating a legacy bank core |
| Sidecar | Every service needs the same helper, in many languages | Run the helper as a separate container beside each instance | Polyglot fleet, platform team owns the helper | CPU, memory and a hop per instance | Service mesh |
| Ambassador | A client can’t be changed to add retries, TLS or routing | An out-of-process proxy for one app’s outbound calls | Legacy or third-party client code | Latency; per-app config | Calling a flaky partner API |
| External configuration store | Config baked into builds needs a redeploy to change | Central, versioned config that apps read and cache | Many services, frequent changes | Store outage; cache last known good | Feature flags, kill switches |
| Compute resource consolidation | Many tiny, mostly idle tasks each pay for a host | Pack several tasks into one compute unit | Idle, low-risk tasks from one team | Shared fate; critical or sensitive tasks | Cron jobs on one worker pool |
| Leader election | Only one instance may run a singleton job | Instances race for a lease in a consensus store; the holder renews it | Schedulers, single writers | Failover pause; needs fencing | Job scheduler |
The strangler fig is Martin Fowler’s name, after the vines he saw in Queensland’s rainforests in 2001, which grow around a host tree until they stand alone. He argues gradual replacement beats a rewrite, because the business can’t wait years for features and much legacy behaviour turns out to be unwanted. The anti-corruption layer comes from Eric Evans’ Domain-Driven Design.
Sidecar, ambassador and gateway are all proxies; what differs is where they sit and whom they serve (Fig. 6).
Deployment topology: copy the whole stack
When one deployment hits a limit, copy all of it. Single point of failure covers cells briefly; cell-based architecture and tenancy models go deeper.
| Pattern | Problem | How it works | Use when | Cost; avoid when | Shows up in |
|---|---|---|---|---|---|
| Deployment stamps | One deployment hits limits or mixes tenants that should be apart | Full copies of app and data, each serving some tenants; a router maps tenant to stamp | SaaS growth, residency, staged rollouts | Many deployments; data needed everywhere | Multi-region SaaS |
| Geode | Global users sit far from one region | Identical nodes in many regions serve any user over globally replicated data | Global read-write, region loss | Multi-region write conflicts; residency rules | Global consumer app |
The Deployment Stamps guidance draws the line: if every instance needs all the data, use geodes; if data must stay put, as under residency rules, use stamps behind a router that knows each tenant’s home (routing requests to tenants). Cells are stamps built for blast radius.
Reliability: the short version
The resiliency family has its own page, the reliability patterns cheat sheet; here is just the map.
| Pattern | In one line | Deep dive |
|---|---|---|
| Retry | Retry transient faults with capped, jittered backoff | Timeouts and retries |
| Circuit breaker | Stop calling a failing dependency; probe to recover | Circuit breaker |
| Bulkhead | Separate pools so one failure can’t drain them all | Bulkheads |
| Queue-based load leveling | Buffer spikes and drain at a steady rate | Backpressure |
| Health endpoint monitoring | Expose checks that balancers and monitors poll | Health checks |
| Saga | Local transactions plus compensations | 2PC vs sagas |
| Idempotent consumer | A duplicate delivery has one effect | Effectively-once |
| Transactional outbox | Commit the row and its event together | Outbox |
Choosing: from interview signal to pattern
Prompts drop hints. Listen for the phrase, then name the pattern and its cost.
| You hear | Reach for | Then mention |
|---|---|---|
| “Users upload photos or videos” | Valet key | Claim check, quarantine scan |
| “Large payloads through a queue” | Claim check | Lifecycle rules for orphans |
| “The job takes minutes; the client waits” | Async request-reply | Webhook or push on completion |
| “Migrate the monolith” | Strangler fig | Anti-corruption layer, CDC for data |
| “Mobile and web need different data” | Backends for frontends | Gateway aggregation, per-call timeouts |
| “Reads and writes look very different” | CQRS + materialized views | Outbox to feed the read side |
| “We need an audit trail or replay” | Event sourcing | Snapshots, CQRS read models |
| “Find a user by email; data is sharded” | Index table | Uniqueness enforced via the index |
| “Events per order must stay in order” | Sequential convoy | Partition by key |
| “OTPs are stuck behind promos” | Priority queue | Separate consumer pools |
| “One event, many reactions” | Publisher-subscriber | Outbox, idempotent consumers |
| “Only one instance may run the job” | Leader election | Fencing tokens |
| “Big tenants, data residency” | Deployment stamps | Tenant router |
| “Users worldwide; any region serves anyone” | Geodes | Conflict resolution |
| “Same helper code in five languages” | Sidecar | Service mesh |
Patterns that pair
Designs combine patterns. These pairings come up most:
- CQRS + event sourcing + materialized views. The event log is the write model, projections are the read models, and replay rebuilds any view.
- Valet key + claim check + quarantine. Bytes go client → storage → scanner → worker; only keys travel through APIs and queues (Fig. 4).
- Strangler fig + anti-corruption layer + CDC. The façade moves routes, the ACL keeps legacy concepts out of new code, and change data capture syncs data while both systems live.
- Gateway + BFF. The gateway does what every client needs (routing, TLS, tokens); each BFF does what one client needs (shape, aggregation).
- Outbox + pub/sub + idempotent consumers. Commit and publish atomically, deliver at least once, apply once.
- Load leveling + competing consumers + priority queue. Buffer the spike, scale workers on queue depth, keep urgent work in front.
- Async request-reply + valet key. The finished status hands back a short-lived signed URL, so a large report downloads straight from storage.
Going deeper: common misuse
Every pattern adds moving parts; interviewers probe for when they don’t pay.
- Event sourcing for CRUD. A settings page gains nothing from replay, yet pays for event versioning, projections and erasure on an append-only log (usually crypto-shredding per-user keys).
- CQRS everywhere. Fowler’s advice is one bounded context at a time; a read replica often gives the read scaling without two models.
- BFF sprawl. One BFF per client experience, not per screen. When BFFs copy business rules, push the rules down into a service.
- Business logic in the gateway. Every team then queues for one deploy. Keep it to cross-cutting concerns.
- Sidecar overhead. It is paid per pod: at 100 MB each, 2,000 pods spend 2,000 × 100 MB = 200 GB of memory on proxies, plus a hop per call. A one-language fleet may be better served by a library.
- Leaky valet keys. Seven-day, bucket-wide upload URLs are standing access. Prefer minutes, one key, one method and a size limit.
A 202 is a promise to look, not to succeed
RFC 9110 calls 202 noncommittal: the work may still fail or be refused. Persist each job’s state before replying, give failures a terminal status with a structured error, and expire old status records, or clients poll forever for jobs that died.
Cheat sheet
| Pattern | Remember it as |
|---|---|
| Cache-aside | Miss → load → fill; writes invalidate |
| CQRS | Separate write and read models |
| Event sourcing | Events are the truth; state is a replay |
| Materialized view | Precompute the expensive query |
| Index table | Second key → primary key lookup |
| Sharding | Split rows by key across nodes |
| Static content hosting | Files from object storage plus CDN |
| Async request-reply | 202 + status URL + Retry-After → 303 |
| Competing consumers | Many workers, one queue |
| Priority queue | Urgent work gets its own lane |
| Publisher-subscriber | Publish once, every subscriber gets a copy |
| Sequential convoy | Order per key, parallel across keys |
| Claim check | Payload in storage, key in the message |
| Pipes and filters | Small stages joined by queues |
| Messaging bridge | Relay between incompatible brokers |
| Choreography | Services react to events; no conductor |
| Scheduler agent supervisor | Orchestrator with a durable record and a supervisor |
| Compensating transaction | Undo committed steps with reverse steps |
| Gateway routing / offloading / aggregation | One door: route, handle cross-cutting, fan out |
| Backends for frontends | One backend per client type |
| Throttling / rate limiting | Server caps tenants; client paces itself |
| Gatekeeper | Secret-free validating tier in front |
| Valet key | Scoped, expiring, direct-to-storage token |
| Federated identity | Let an IdP sign users in |
| Quarantine | Isolate, scan, then promote |
| Strangler fig | Façade moves routes until legacy dies |
| Anti-corruption layer | Translate; don’t inherit the old model |
| Sidecar / ambassador | Helper beside each instance / outbound proxy |
| External configuration store | Central, versioned, cached config |
| Compute resource consolidation | Pack idle tasks together |
| Leader election | One lease holder runs the singleton |
| Deployment stamps / geodes | Pinned copies / any-region copies |
How to say it in the interview
“Each pattern I name answers a specific problem. Clients hit one gateway that routes, terminates TLS and checks tokens from our identity provider; the mobile app gets a BFF that turns the home screen into one call. Photos upload through a presigned URL straight to object storage, and the upload event carries only the key to a queue where competing workers scan and resize. Orders go to one write model and out through an outbox to a topic; subscribers build the restaurant dashboard as a materialized view and send notifications through a priority queue, so OTPs never wait behind promos. Report exports return 202 with a status URL. To replace a legacy system, I’d strangle it route by route behind the gateway, with an anti-corruption layer.”
Gateway aggregation or a BFF? Aggregation is a capability: fan out and merge. A BFF is an ownership decision: one backend per client type, run by that client’s team, and it usually does the aggregating. One client: aggregate in the gateway. Very different clients: BFFs behind a thin gateway.
How does the client learn the job finished without hammering you?
Retry-After sets the pace, and the cost is jobs in flight ÷ interval: 1,000 jobs at 10 s is 100 cheap reads a second. Clients that accept pushes get a webhook or SSE event, with polling as the fallback.
Isn’t a presigned URL a security hole? It is a bearer token, so bound it: one key, one method, minutes not days, a size limit, and a quarantine scan before anything is served. On S3 it can’t outlive its signing credentials, and 7 days is the ceiling.
When would you not use CQRS? When reads and writes share a shape, or a read replica fixes the load. You pay for two models and visible lag, so use it only where needed, such as a feed or a dashboard.
Stamps or geodes? Stamps pin each tenant to one full copy: good for residency rules and blast radius. Geodes let any region serve anyone over globally replicated data: good for global consumer apps, at the price of multi-region writes and conflict handling.
Where to go next
- Reliability patterns cheat sheet: retries, breakers, bulkheads, shedding and the rest of the resiliency family.
- Event sourcing and CQRS: projections, snapshots and event versioning in depth.
- Migrating a legacy system: strangler fig and anti-corruption layer step by step.
- API composition: aggregation, BFF and GraphQL federation: the edge family compared.
- Sidecar, ambassador and service mesh: proxies, meshes and their overhead.
- Large file uploads and long-running jobs: valet keys, claim checks and async request-reply in practice.
- Cell-based architecture: stamps, cells and geodes for blast radius and scale.
- Ten principles senior engineers design by: the judgement behind picking any pattern.
References and further reading
- Cloud design patterns (Azure Architecture Center)learn.microsoft.comThe catalogue itself: over 40 technology-agnostic patterns with problem statements, trade-offs and suggested combinations.
- Cloud design patterns, architectures, and implementations (AWS Prescriptive Guidance)docs.aws.amazon.comAWS’s modernisation set: anti-corruption layer, API routing, event sourcing, publish-subscribe, sagas, scatter-gather, strangler fig and transactional outbox.
- Asynchronous Request-Reply pattern (Azure Architecture Center)learn.microsoft.comThe 202, status endpoint, Location and Retry-After flow, why 303 beats 302 for the final redirect, and retention of status resources.
- RFC 9110: HTTP Semanticsrfc-editor.orgDefines 202 Accepted as intentionally noncommittal, 303 See Other as a redirect to a GET-able result, and Retry-After for 503 and 3xx responses.
- Download and upload objects with presigned URLs (Amazon S3 User Guide)docs.aws.amazon.comPresigned URLs as bearer tokens: up to 7 days with Signature Version 4, cut short by the signer’s credentials, and checked when a request starts.
- Claim Check pattern (Azure Architecture Center)learn.microsoft.comStore the payload, send a reference; publish only after the write succeeds, and own payload lifecycle and duplicate handling.
- Amazon SQS message quotasdocs.aws.amazon.comA 1 MiB message ceiling, and the Extended Client Library that keeps payloads of up to 2 GB in S3: a claim check in a library.
- Deployment Stamps pattern (Azure Architecture Center)learn.microsoft.comIndependent copies of the whole stack for scale limits, tenant isolation and blast radius, and when to choose geodes instead.
- Strangler Fig (Martin Fowler)martinfowler.comWhere the name comes from, why big-bang replacements usually fail, and why transitional architecture is worth paying for.
- CQRS (Martin Fowler)martinfowler.comSeparate models for update and display, first heard from Greg Young, and a warning to apply it to one bounded context, not a whole system.