Field Guide

A field guide

How a system is shaped is half of what it is.

These ten architectures are top-level shapes — the topology, hosting model, and runtime your system lives in. The question isn't whether each is good in the abstract; it's whether its constraints fit the system you're trying to build.

10 architectures · ~12 min read · Updated 2026

How to read this guide

Each architecture follows the same shape: the problem it answers, the structural shape it imposes, and the pitfalls that come with picking it. The "When it fits" line at the end is where the choice lives.

Vogels's adage: Everything fails, all the time. Pick a shape that survives the failures it'll actually meet, not just the ones in textbooks.

01

Client-Server (2-Tier)

Clients talk directly to a single shared server.

Client A Client B Client C Server app + logic Database

Problem

Multiple users need to share state and resources, but each runs on their own machine. Where does the shared truth live, and how do clients reach it?

Shape

A central server holds the data and runs the logic. Clients (desktop apps, terminals, browsers) make requests over the network. Two roles, two tiers, one network hop.

Watch for

The server is a single point of failure and the scaling ceiling. Logic split awkwardly between fat client and thin server (or vice versa) ages badly.

When it fits: Internal LOB tools, small-team systems, anywhere the user count is bounded and the deployment story is "one box per customer."

02

3-Tier / N-Tier

Separate the presentation, application, and data tiers — and scale each independently.

Web tier presentation · static + html App tier business logic · stateless Data tier persistence · transactions

Problem

One server doing UI, business logic, and data access conflates concerns. You can't scale the database the same way you scale the web layer, and changes ripple unpredictably.

Shape

Three distinct tiers — web, application, database. Each runs on its own machines, with its own scaling and security boundary. Add more tiers (caching, search) and it becomes N-tier.

Watch for

Tiers are deployment boundaries, not always good design boundaries. Cross-tier round-trips add latency, and the "logic in the wrong tier" debate is forever.

When it fits: Most traditional enterprise web apps. The default starting topology when one machine isn't enough but full distributed systems are overkill.

03

Static Site / JAMstack

Pre-render HTML and serve it from a CDN — at build time, on demand, or incrementally.

Source repo build CDN prerendered html global edges Browser

Problem

Most pages don't change between requests, but you're paying for an app server to render the same HTML over and over. Latency, cost, and complexity all suffer.

Shape

Pre-render pages to static HTML/CSS/JS and serve them from a CDN. Modern variants — incremental static regeneration (ISR), on-demand rebuilds, hybrid SSR/SSG (Next.js, Astro, Remix) — relax the strict "build time only" rule. Dynamic bits (forms, auth, search) call separate APIs from the browser.

Watch for

Build times grow with page count. Truly personalized content has to move to client-side fetches or edge functions, which brings the complexity back in.

When it fits: Marketing sites, documentation, blogs, e-commerce catalogs — anywhere content updates infrequently and you want CDN-speed delivery globally.

04

SPA + API

A static frontend shell loads in the browser and talks to a stateless JSON backend.

Browser SPA bundle React / Vue JSON API server stateless DB

Problem

You want a fluid, app-like UX without server round-trips for every interaction, but you also want clean separation between presentation and data.

Shape

A single-page app (React, Vue, Svelte) ships as a static bundle. After load, it calls a stateless JSON API for data. The frontend lives on a CDN; the backend scales independently.

Watch for

First paint is slow without SSR or prerendering. SEO needs care. Bundle size becomes a never-ending diet, and the API becomes the system's product surface — version it deliberately.

When it fits: Logged-in apps with rich client interactions — dashboards, editors, internal tools — or any time the same backend serves multiple frontends.

05

Event-Driven Architecture

Services publish events to a broker; other services react. No direct calls between them.

Producer Producer Broker topics · partitions Notify Charge Analyze

Problem

Tightly coupled services force coordinated deployments and cascading failures. Adding a new consumer means changing the producer. Synchronous chains amplify slowness.

Shape

Producers emit events to a broker (Kafka, NATS, EventBridge). Consumers subscribe to topics they care about. The two are decoupled in identity and lifecycle — neither needs to know who's on the other end — but they still share a contract: the event schema. Three flavors worth distinguishing: event notification (lightweight "this happened"), event-carried state transfer (the event includes enough state for consumers to act independently), and event sourcing (the event log is the source of truth).

Watch for

Debugging means following a trail across systems. Event schemas need governance — a renamed field is a wire-protocol break. Eventual consistency becomes the default.

When it fits: Workflows with many side effects (order placed → notify, charge, fulfill, analyze), high-throughput ingestion, or anywhere consumers should be added without touching producers.

06

Pipeline / Stream Processing

Data flows through a chain of processing stages, each transforming and forwarding.

Source Clean stage Enrich stage Aggregate stage Sink

Problem

Large volumes of data need to be cleaned, enriched, joined, and stored — and each step has different scaling and reliability needs. Doing it all in one job is fragile.

Shape

A directed graph of stages. Each reads from an input stream, transforms, writes to an output stream. Engines like Flink, Kafka Streams, and Spark Streaming handle backpressure, ordering, and (with cooperating sources/sinks) end-to-end exactly-once semantics. Apache Beam is a portable programming model that runs on top of these engines, not an engine itself.

Watch for

Reprocessing history (after a bug or schema change) is its own engineering project. Latency vs throughput trades show up at every stage. Stateful operators (joins, windows) are the hard parts.

When it fits: ETL/ELT pipelines, real-time analytics, fraud detection — anything that ingests a firehose and produces derived views.

07

Serverless / FaaS

Functions run on demand. No servers to provision; you pay per invocation.

HTTP Queue Schedule Serverless platform fn instance fn instance fn instance spin up tear down

Problem

Your traffic is spiky or unpredictable, and paying for idle capacity is wasteful. Operating servers at all is overhead you'd rather not own.

Shape

Code is packaged as functions. The platform (Lambda, Google Cloud Functions, Azure Functions) spins them up on each request and tears them down after. State lives elsewhere — DBs, blob stores, caches. Edge runtimes like Cloudflare Workers fit a related but different model — V8 isolates rather than container-per-invocation — and are covered separately under Edge-First.

Watch for

Cold starts hurt latency. Long-running or stateful work fights the model. Local dev and observability are awkward. Cost flips at high steady throughput.

When it fits: Bursty workloads, event handlers, glue code between services, low-traffic APIs — anywhere "what's a server?" should not be a question you answer monthly.

08

Edge-First

Compute runs at CDN points-of-presence close to users, not in a single region.

Origin single region Edge PoP Edge PoP Edge PoP Edge PoP

Problem

A single-region deployment leaves users far from your compute paying long round-trips. Pushing static assets to the edge helps, but dynamic responses still hit the origin.

Shape

Run lightweight functions or full workloads at the CDN edge (Cloudflare Workers, Fastly, Vercel Edge). Each request is handled at the PoP nearest the user. Origin is reserved for things that genuinely need it.

Watch for

The runtime is constrained — limited memory, limited libraries, no long-lived connections. State at the edge is hard; consistency across PoPs is harder still.

When it fits: Latency-sensitive personalization, A/B routing, auth at the edge, geo-aware redirects — anywhere shaving 100ms across the world matters more than runtime power.

09

Cell-Based Architecture

Replicate the whole stack as isolated cells; route each customer to one cell.

Router customer → cell Cell A App DB Cell B App DB Cell C App DB

Problem

Even with bulkheads, a fully shared system means one bug or one bad deploy can affect every customer. The blast radius of a failure is "everyone."

Shape

Build the system once, deploy it many times as identical cells. Each cell serves a slice of customers (or a region). A thin routing layer maps requests to cells. Cells share nothing. Pair with shuffle sharding — randomize each customer's cell assignment across multiple dimensions — to make the probability of any two noisy customers landing in the same cell vanishingly small.

Watch for

Operational overhead multiplies — N copies of everything to monitor and upgrade. Cross-cell features (global search, shared inventory) become genuine engineering projects.

When it fits: Mature SaaS at scale (AWS Route 53, DynamoDB, S3; Salesforce instances), regulated industries with isolation requirements, anywhere a single bad deploy taking down all customers is unacceptable.

10

Multi-Region Active-Active

Run the full stack in multiple regions; traffic routes to the nearest healthy one.

DNS / Anycast Region A App DB Region B App DB replication

Problem

Single-region deployments give global users bad latency, and a regional outage takes you down entirely. Active-passive failover is slow and rarely tested.

Shape

Deploy the full app in two or more regions, each handling live traffic. Route users to the nearest region using DNS-based routing (Route 53 latency/geo policies — TTL-bound, slower failover) or BGP anycast (network-layer rerouting, sub-second failover). Data replicates between regions — sync or async depending on the consistency budget — and CAP/PACELC is the theoretical ceiling on what you can guarantee here.

Watch for

Cross-region data is the hardest part — conflict resolution, replication lag, split-brain during partitions. Costs roughly double. Testing the failure modes is non-trivial.

When it fits: Global products with strict uptime SLAs, regulated workloads that must survive regional outages, latency-sensitive consumer apps with users worldwide.

Choose the shape that survives your failures

The architecture you pick is a bet about what will fail and what will scale. The bet is right when the problems you actually meet are the ones the shape was designed for.

Most teams arrive at the wrong shape by copying a successful one without copying the constraints that made it the right answer. The shape isn't the win — matching the shape to the constraints is.

Two axes are deliberately covered elsewhere: monolith vs. modular monolith vs. microservices (the decomposition choice — see the trade-offs page) is orthogonal to most of the topologies above. Several of them — Event-Driven, Cell-Based, Multi-Region — presuppose a decomposition has already happened.