Filter concepts by levelShowing all levels.

System Design · Basic Architecture Patterns

Basic Architecture Patterns

Six named shapes for a system, and the discipline that keeps any one of them from being the default answer

  • Three-tier & layeredclient → app → database, and the layers inside it
  • Modular monolithone deployable, enforced boundaries
  • Microservicesindependent services, network boundaries
  • Event-driven & pipelineproducers/consumers, and staged data flow

1.Three-tier architecture

Three-tier architecture splits a system into a client (what the user interacts with), an application tier (business logic), and a database tier (persistent storage) — each tier only talks to its immediate neighbor.

Key features

  • Client tier: the user-facing layer — browser, mobile app, or another API consumer
  • Application tier: business logic, validation, and orchestration — no direct client access to storage
  • Database tier: persistent storage — the client never talks to it directly
  • Each tier can be scaled, deployed and replaced independently of the others
  • The most common default shape for a new web system before any specialization is added

The three tiers

The three tiers
TierResponsibilityExample
Clientpresentation, user interactiona browser, a mobile app
Applicationbusiness logic, validation, orchestrationan API server
Databasepersistent storagePostgreSQL, MySQL
Three-tier architecture
requestqueryresultresponse

Client

browser, mobile app

Application

business logic, validation

Database

persistent storage

  • Client — browser, mobile app
    • leads to Application (request)
  • Application — business logic, validation
    • leads to Database (query)
    • leads to Client (response)
  • Database — persistent storage
    • leads to Application (result)

Command

text
client  --request-->  application  --query-->  database
client  <--response--  application  <--result--  database

client never talks to the database directly

Client (presentation) → application (business logic) → database (storage) — each tier only talks to its immediate neighbor.

2.Layered architecture

Layered architecture is a finer split within a single deployable: presentation (handling requests), application/service (orchestration), domain (core business rules), data access (querying), and storage. Each layer only calls the layer directly below it.

The five layers

The five layers
LayerResponsibilityExample
Presentationparses requests, formats responsesan HTTP controller/handler
Application/serviceorchestrates a use casePlaceOrderService.execute()
Domaincore business rules, independent of I/Oan Order entity's validation rules
Data accesstranslates domain objects to/from storagean OrderRepository
Storagethe actual persistence mechanismPostgreSQL, a table
The five layers, top to bottom

Presentation

parses requests, formats responses

Application/service

orchestrates a use case

Domain

core business rules, no I/O

Data access

translates domain objects to/from storage

Storage

the actual persistence mechanism

  1. Presentation — parses requests, formats responses
  2. Application/service — orchestrates a use case
  3. Domain — core business rules, no I/O
  4. Data access — translates domain objects to/from storage
  5. Storage — the actual persistence mechanism

Command

text
presentation -> application/service -> domain
                                            |
                              data access <-+
                                   |
                               storage

each layer only calls the layer directly below it

Presentation → application/service → domain → data access → storage — each layer calls only the layer directly below it; domain logic stays free of I/O.

3.Modular monolith

A modular monolith is one deployable system, but internally split into modules with strong, enforced boundaries — each module owns its own data and exposes a defined interface, even though everything ships and runs as a single unit.

Key features

  • One deployable, one process — deploys and scales as a single unit
  • Internally split into modules, each with an enforced boundary and its own data
  • Modules communicate through defined interfaces, not by reaching into each other's tables
  • No network calls between modules — communication is in-process function calls
  • A common stepping stone: a codebase can outgrow "no boundaries" without yet needing distributed-systems complexity

Modular monolith vs a plain monolith

Modular monolith vs a plain monolith
AspectPlain monolithModular monolith
Deploymentsingle deployablesingle deployable (same)
Internal boundariesnone enforced — any code can call any otherenforced module boundaries with defined interfaces
Data ownershipshared tables, any module can query any tableeach module owns its own data
Refactor cost to microserviceshigh — boundaries have to be discovered firstlower — boundaries already exist, just need a network hop added
One deployable, three enforced module boundaries

Orders module

Orders logic

orders table

Inventory module

Inventory logic

inventory table

Billing module

Billing logic

billing table

  • Orders module — owns the orders table
    • Orders logic
    • orders table
  • Inventory module — owns the inventory table
    • Inventory logic
    • inventory table
  • Billing module — owns the billing table
    • Billing logic
    • billing table

Command

text
one process, one deploy
  module A --(interface call)--> module B
  module A: owns its own data, no cross-module table access

if module A needs module B's data, it calls
module B's interface — never queries module B's
table directly

One deployable, strong internal module boundaries, each module owns its own data — communication is in-process, not networked.

4.Microservices

Microservices split a system into multiple independently deployable services, each with its own codebase, data, and deploy pipeline, communicating over explicit network calls rather than in-process function calls.

Key features

  • Each service is independently deployable — its own codebase, its own deploy pipeline
  • Each service owns its own data — no other service queries its database directly
  • Communication is over the network (HTTP, gRPC, messaging), not in-process function calls
  • Services can be scaled independently — a hot service gets more instances without scaling the rest
  • Every network call between services can fail, time out, or arrive out of order — failure modes an in-process call never has

Microservices vs a modular monolith

Microservices vs a modular monolith
AspectModular monolithMicroservices
Deploymentsingle deployablemany independently deployable services
Communicationin-process function callsnetwork calls (HTTP, gRPC, messaging)
Scalingthe whole app scales togethereach service scales independently
Failure modea bug can crash the whole processone service failing does not crash the others directly, but the network call to it can fail
Independently deployable services, each with its own data
HTTP/gRPCHTTP/gRPC

Orders service

own deploy + DB

Orders DB

Inventory service

own deploy + DB

Inventory DB

Billing service

own deploy + DB

Billing DB

  • Orders service — own deploy + DB
    • leads to Orders DB
    • leads to Inventory service (HTTP/gRPC)
    • leads to Billing service (HTTP/gRPC)
  • Orders DB
  • Inventory service — own deploy + DB
    • leads to Inventory DB
  • Inventory DB
  • Billing service — own deploy + DB
    • leads to Billing DB
  • Billing DB

Command

text
service A --(network call: HTTP/gRPC/queue)--> service B

each service: own codebase, own database, own deploy

a network call can fail in ways a function call cannot:
  timeout, partial response, service unavailable

Multiple independently deployable services, each owning its own data, communicating over the network — every call needs a timeout, retry, and idempotency plan a function call never did.

5.Event-driven architecture

Event-driven architecture decouples components through a message broker: producers publish events without knowing who consumes them, and consumers process events without the producer waiting for a response.

Event-driven architecture: the three roles

Event-driven architecture: the three roles
RoleResponsibilityExample
Producerpublishes an event, does not wait for a responseOrderService publishes "order.placed"
Brokerreceives, stores and routes events to consumersKafka, RabbitMQ, SQS
Consumersubscribes to events and processes them asynchronouslyEmailService, InventoryService both read "order.placed"
One event, fanned out to independent consumers
order.placed

OrderService

publishes, returns immediately

Broker

Kafka, RabbitMQ, SQS

EmailService

sends confirmation

InventoryService

decrements stock

AnalyticsService

logs the sale

  • OrderService — publishes, returns immediately
    • leads to Broker (order.placed)
  • Broker — Kafka, RabbitMQ, SQS
    • leads to EmailService
    • leads to InventoryService
    • leads to AnalyticsService
  • EmailService — sends confirmation
  • InventoryService — decrements stock
  • AnalyticsService — logs the sale

Command

text
producer --publish(event)--> broker --route--> consumer(s)

producer does not know who (or how many) consumers exist
producer does not wait for a consumer to finish

Producers publish events to a broker without knowing or waiting on consumers — new consumers subscribe independently, with no change to the producer.

6.Pipeline architecture

Pipeline architecture moves data through a sequence of stages — ingestion (bringing data in), processing (transforming it), and storage/output (where the result lands) — each stage feeding the next, common in data and batch-processing systems.

The three pipeline stages

The three pipeline stages
StageResponsibilityExample
Ingestionbrings raw data into the pipelinereading log files, an API webhook, a Kafka topic
Processingtransforms, filters, aggregates, or enriches the dataparsing, deduplication, computing aggregates
Storage/outputwhere the processed result landsa data warehouse, a dashboard, a downstream API
Clickstream pipeline, stage by stage
raw eventsper-minutecounts

Ingestion

read raw click events from Kafka

Processing

parse, filter bots, aggregate

Storage/output

aggregated counts in a warehouse

  • Ingestion — read raw click events from Kafka
    • leads to Processing (raw events)
  • Processing — parse, filter bots, aggregate
    • leads to Storage/output (per-minute counts)
  • Storage/output — aggregated counts in a warehouse

Command

text
ingestion --> processing --> storage/output

each stage: single responsibility, feeds the next
stage's input format

Ingestion (bring data in) → processing (transform it) → storage/output (where it lands) — each stage has one job and feeds the next.

7.Understand pattern trade-offs, not universal superiority

None of the six patterns in this section is universally best. Each trades something for something else — event-driven buys decoupling at the cost of ordering guarantees, microservices buy independent scaling at the cost of network complexity. Choosing one means choosing its trade-off, not just its benefit.

Key features

  • Three-tier / layered: simple to reason about, but everything scales and deploys together
  • Modular monolith: keeps boundary discipline without network cost, but all modules still share one deploy and one failure domain
  • Microservices: independent scaling and deployment, but adds network calls, partial failure, and operational overhead
  • Event-driven: decouples producers from consumers, but trades away strict ordering and immediate consistency
  • Pipeline: clean separation of stages, but adds latency between ingestion and the final output being available

What each pattern trades away

What each pattern trades away
PatternBuysCosts
Three-tier / layeredsimplicity, easy reasoningthe whole system scales and deploys as one unit
Modular monolithboundary discipline, no network costone shared deploy and failure domain across all modules
Microservicesindependent scaling and deploymentnetwork calls, partial failure, operational overhead
Event-drivendecoupled producers and consumersweaker ordering and consistency guarantees
Pipelineclean stage separation, replaceable stagesadded latency between ingestion and final output
Every pattern trades simplicity for a specific property
Three-tier / layered
simple, but scales/deploys as one unit
Modular monolith
boundary discipline, one shared deploy
Pipeline
clean stages, added latency
Event-driven
decoupled, weaker ordering
Microservices
independent scaling, network cost
  • Three-tier / layered: Simple to operate, Tightly coupled — simple, but scales/deploys as one unit
  • Modular monolith: Simple to operate, between Tightly coupled and Fully decoupled — boundary discipline, one shared deploy
  • Pipeline: between Simple to operate and Complex to operate, between Tightly coupled and Fully decoupled — clean stages, added latency
  • Event-driven: Complex to operate, Fully decoupled — decoupled, weaker ordering
  • Microservices: Complex to operate, Fully decoupled — independent scaling, network cost

Command

text
no pattern is free — each one:
  BUYS  a specific property (decoupling, scaling, simplicity)
  COSTS a specific price (network calls, ordering, shared deploys)

choosing a pattern = choosing which cost you can afford

Every pattern buys a specific property and costs a specific price — name both before choosing, and match the choice to the actual constraints, not to reputation.

Remember

  • Three-tier: client → application → database. Layered: presentation → service → domain → data access → storage.
  • Modular monolith: one deployable, enforced module boundaries, in-process calls. Microservices: independent services, network calls.
  • Event-driven: producers publish to a broker without knowing consumers. Pipeline: ingestion → processing → storage/output.
  • No pattern is universally best — every one buys a property and costs a price; name both before choosing.

Pro tip

  • A modular monolith gets boundary discipline without paying the network cost microservices requires — often the right stepping stone.
  • A network call between microservices needs a timeout, retry and idempotency plan a function call never did.

Next up

  • Monolith vs modular monolith vs microservices
  • Client-server and API gateways

Sources

  • System Design Primer — github.com/donnemartin/system-design-primer
  • Checked 2026-08-21

Spotted a mistake on this page? Tell us.