Service Architectures — Cross-System Comparison

This note compares the architectural styles a team picks between when shaping a system: monolith, modular monolith, microservices, nanoservices, serverless functions, event-driven, CQRS, event sourcing, hexagonal/ports-and-adapters, onion, clean, lambda, kappa, reactive, space-based, and pipeline. Each row maps to a real-world exemplar (Netflix, Amazon, Shopify, Stripe, Uber DOMA, LinkedIn, Twitter, Square, GitLab, Basecamp HEY, dbt Cloud, Vercel) and the tables compare on team size, deployment unit, data consistency, observability, cost, refactor cost, and lock-in. Read the dimension tables first, decision tree last.

See also

1. The architectural spectrum

monolithic                                                            distributed
  |                                                                       |
big-ball-of-mud → monolith → modular → CQRS → microservices → nanoservices → functions
                                                                              |
                                                                          serverless
                          ← event-sourcing → reactive → space-based →
                                pipeline (lambda / kappa)

Cross-cutting styles (orthogonal to deployment granularity):

hexagonal / ports-and-adapters
onion architecture
clean architecture
domain-driven design (DDD)
event-driven architecture (EDA)
CQRS (separate read + write models)
event sourcing (append-only ledger)

2. Deployment-unit granularity

StyleDeployment unitCode repoDatabaseTeam size sweet spotReal exemplar
Big-ball-of-mud1 binary1 repo1 schema1–5early-stage startup MVP
Monolith1 binary1 repo1 schema5–30early Basecamp, GitHub through 2014
Modular monolith1 binary, internal modules1 repo1 schema (logically partitioned)15–200Shopify, GitHub 2014+, Basecamp HEY, dbt Cloud (partial), early Stripe
Macroservices~5–30 servicesmono or multi-repoper-service-cluster30–200Stripe (2020s), GitLab (mostly mono), Square (early)
Microserviceshundredsmulti-repo or monorepoper-service100–10,000Netflix (~2000 svcs), Amazon (~2-pizza teams = thousands), Uber peak (~4000 svcs)
Nanoservices1 function = 1 servicemulti-reposhared or n/arare; usually anti-patternover-decomposed orgs (cautionary tale)
Serverless functions1 fnusually monorepoexternal (Aurora, Dynamo)anyLego Group on AWS Lambda; Bustle.com migration 2017; Liberty Mutual claims
Edge functions1 fn at edgeusually monorepoedge KV / regional DBanyVercel Edge Functions, Cloudflare Workers, Fastly Compute@Edge, Deno Deploy

The 2020s consensus: modular monolith is the default for teams < 50; microservices kick in around 100+ engineers. The pre-2018 pendulum swung too far toward microservices; the DOMA (Domain-Oriented Microservice Architecture) Uber paper in 2020 (Adam Gluck) crystallized the consolidation — Uber went from ~4000 microservices back to ~2200 by organizing them into ~70 domains.

3. Real exemplars — what teams actually run

CompanyArchitecture (2025)Service countNotableRecovery from
Netflixmicroservices on AWS~2000Chaos Monkey 2010, Hystrix → Resilience4j, Spinnaker, Eureka, Zuul, Conductor; multi-region active-activerapid post-Qwikster scaling
Amazon”two-pizza teams” microservicesthousandsfamous Bezos 2002 mandate; service-as-contract; Werner Vogels’ “you build it, you run it”aws.amazon.com Prime Video 2023 ironically moved a few microservices to a monolith for cost reasons (90% savings)
UberDOMA (Domain-Oriented)~2200 (down from ~4000 peak)Cadence/Temporal workflow engine, M3 metrics, Jaeger tracingover-decomposition lessons published 2020 (Gluck “Microservices at Uber”)
Shopifymodular monolith (Rails)1 main app + ~200 modules”majestic monolith” branding; intentional resistance to microservices2018 Ben Curtis blog on “deconstructing the monolith” — modules, not services
StripeAPI-first macroservices~50–100 main servicesRuby + Scala; strong API design culture; rare downtimeminimal, mostly forward growth
GitLabintentional monolith1 Ruby app + a few Go services (Gitaly, GitLab Pages, Workhorse)self-host viability requires monolithreinforced in 2020 platform docs
Basecamp HEYmodular monolith (Rails)1 appDHH’s “Majestic Monolith” essay 2016; Basecamp / HEY use the same patternn/a
dbt CloudPython microservicesdozensdistinct platform, query, scheduler servicesmigrated from monolith ~2019-2021
LinkedInmicroservices + Espresso storage + Kafka streamthousandsKafka born here (Jay Kreps), Pegasus 2.0 RPC, Pinot OLAPKafka revolution 2011+
Twitter / Xmicroservices on Manhattan + Heron streamthousandsHeron stream (post-Storm), Manhattan KV, Pelikan cachemassive 2022 layoff + post-acquisition consolidation
Squareservice mesh microserviceshundredsEnvoy + Istio adoption; protobuf-RPCgradual migration from Ruby monolith
Pinterestmicroservices on AWShundredsMysql sharded + PinLater + KafkaConnect-like Singergradual scaling
Airbnbmicroservices (“Service-Oriented” then “SOA-to-microservices”)hundredsApache Airflow born here, Presto extensive, Spinnaker userpost-IPO platform consolidation 2021+
DoorDashmicroservices on AWS + GCPhundredsKotlin + gRPC; Cadence/Temporal heavy usepost-IPO platform scaling
Verceledge serverlessvariesEdge Functions on V8 isolates; Next.js convergenceedge-first since founding
Cloudflareedge runtime + microservices in DCshundredsWorkers (V8 isolates), Durable Objects, R2, KVconstant evolution

4. Cross-cutting architectural styles

StyleOriginWhat it addsUsed by
Hexagonal / Ports-and-AdaptersAlistair Cockburn 2005application core isolated from I/O via portsSpring Boot apps, many DDD shops, dbt Cloud
OnionJeffrey Palermo 2008concentric dependency rule — outer depends on inner.NET community heavily
Clean ArchitectureRobert C. Martin (Uncle Bob) 2012 / book 2017unified hex + onion; dependency inversionpopular in iOS, Android, Spring
Domain-Driven Design (DDD)Eric Evans 2003bounded contexts, aggregates, ubiquitous languagemost large enterprise; Uber DOMA explicitly DDD
CQRSGreg Young 2010separate read + write modelsmany event-sourced systems; Axon Framework
Event SourcingGreg Young 2006+; Martin Fowlerappend-only event log as source of truthWalmart Inventory, Klarna, EventStoreDB (commercial), Axon
Event-drivenbroad — Faust, Spring Cloud Stream, EventBridge, Kafka Streamsservices react to events on a busLinkedIn, Confluent customers, Netflix
ReactiveReactive Manifesto 2014 (Bonér, Klang, Kuhn, Thompson)responsive + resilient + elastic + message-drivenAkka, Vert.x, Spring WebFlux, RxJS
Space-based architectureRoger Sessions 2008; Tarball / Tibco; later “Tuple Spaces”in-memory grid + replicated dataHazelcast, GigaSpaces, low-latency trading
Lambda architectureNathan Marz 2011batch + speed layer + servingearly big-data; mostly displaced by Kappa
Kappa architectureJay Kreps 2014unified stream-only architectureKafka-centric shops; Flink-first; Netflix Keystone
Pipeline / pipes-and-filtersclassic UNIXdata flows through transformationsdbt, Airflow DAGs, Apache Beam

5. Per-architecture trade-offs

StyleLatency overheadOperational costRefactor costLock-inObservability burden
Monolithminimallowlow (rename in IDE)nonelow (1 stack trace)
Modular monolithminimallowmedium (need module boundary discipline)nonelow
Microserviceshigh (10+ ms per hop)high (K8s + service mesh)high (distributed change)medium (service-mesh, OTel)very high (distributed tracing required)
Serverless functionscold-start 100ms–10sdepends on usagemedium (per-function deploy)high (per-cloud runtime)provider-specific (CloudWatch, GCP Logs, Azure Monitor)
Event-drivenasync (bus latency)medium (Kafka cluster)medium (event-schema evolution)medium (broker)very high (event tracing)
CQRSmedium (read model lag)medium (two persistence layers)high (must maintain two models)low (concept-only)high
Event sourcinghigh (event replay cost)medium (event store)very high (event schema is forever)medium-highvery high
Hexagonalminimalminimallow (port-swap)noneminimal

6. Data consistency boundary — where it bites

StyleCross-component consistencyTypical answer
Monolith1 ACID transaction across all featurestrivial
Modular monolith1 schema; 1 ACID; modules respect logical boundstrivial
Microservicesper-service DB; cross-service eventually consistentsaga (orchestration via Temporal / Cadence; choreography via events on Kafka)
Event-driveneach consumer at its own offset; eventualdead-letter queues + retry budget + idempotency keys
CQRSwrite model is consistent; read model lagsinform UI of staleness; “your change has been recorded, may take a moment to appear”
Event sourcingeventual on materialized views; perfect on event logreplay; snapshot every N events for performance
Lambdabatch is consistent; speed layer is approximatereconcile (batch overwrites speed daily)
Kappastream is source-of-truthreplay from earliest

The two-phase commit (2PC) across services is dead — too brittle, blocking-on-coordinator, bad partition tolerance. Modern services use sagas, outbox patterns, and event sourcing. See microservices-patterns §saga, outbox, and CDC.

7. The four service-coordination patterns

PatternMechanismUsed inTrade-off
Synchronous RPCHTTP/REST, gRPC, GraphQL request-responsemost “regular” microservicescascading failures; tight coupling
Asynchronous messagingRabbitMQ, SNS, ActiveMQclassical EDAat-least-once delivery; ordering not guaranteed
Event streamingKafka, Pulsar, Kinesis, RedpandaLinkedIn-style platformsper-partition order; replayable
Workflow orchestrationTemporal, AWS Step Functions, Camunda, CadenceUber-DoorDash-Coinbase styledurable state machine; coding model not infra model

Temporal (2019, Maxim Fateev + Samar Abbas, ex-Uber Cadence) deserves callout — by 2024 it’s the default for “I need a multi-step workflow that survives crashes” pattern, used by Snap, Coinbase, Stripe (partial), Datadog, Box, DoorDash. Step Functions is AWS-locked equivalent; Camunda 8 is the BPM-flavored variant.

8. Service mesh — when sidecars matter

MeshSidecar / dataplaneAdoption stage (2025)
IstioEnvoymature; consolidating with Cilium
Linkerdlinkerd2-proxy (Rust)mature; lightweight
Consul ConnectEnvoy + Consulenterprise (HashiCorp)
Cilium Service MesheBPF (no sidecar)growing fast; sidecar-less
Kuma / Kong MeshEnvoysmall footprint
AWS App MeshEnvoybeing deprecated 2024 in favor of EKS + Istio
Open Service Mesh (Microsoft)Envoydiscontinued 2024
Solo.io Gloo MeshEnvoycommercial Istio packaging

eBPF-based meshes (Cilium) are the late-2020s direction — no sidecar overhead, kernel-level enforcement. See ebpf-and-kernel-observability and containers-service-mesh.

9. The Prime Video 2023 reversal

Amazon Prime Video published a now-famous post-mortem (Marcin Kolny, March 2023): a monitoring service originally built as serverless Lambda functions + Step Functions was rewritten as a monolithic ECS task. The result: 90% cost reduction. Lesson: per-frame data flow is the wrong workload for serverless function pricing; long-lived shared memory wins.

This is not “microservices are dead” — it’s “match the workload to the architecture”. Prime Video’s broader catalog discovery / playback / DRM stack remains microservices.

10. Cloud provider preferences

ProviderMicroservices substrateServerlessEdge
AWSECS, EKS, App RunnerLambda, Step Functions, App Sync, EventBridgeCloudFront Functions, Lambda@Edge
GCPGKE, Cloud RunCloud Functions, Workflows, EventarcCloud Run + Cloud CDN
AzureAKS, Container AppsAzure Functions, Durable Functions, Logic AppsAzure Front Door / Functions Premium
Verceln/aServerless Functions, Edge Functionsyes (default)
Cloudflaren/aWorkersyes (default)
Fly.ioFly Machinesn/ayes (regional VM-per-app)
RenderWeb ServicesBackground Workerspartial
Fastlyn/aCompute@Edge (WASM)yes (default)

See cloud-provider-service-mapping for the full mapping.

11. Observability burden

ArchitectureLogsMetricsTracesRequired tooling
Monolith1 stream per replicaservice-levelfunction-levelDatadog / New Relic / one-stack
Microservicesper-service streamsper-service + service-meshOpenTelemetry + Jaeger / Tempo / Honeycomb / Datadog APMdistributed tracing mandatory
Serverlessper-invocationper-functionprovider-native + OTelCloudWatch + X-Ray, GCP Logging + Trace, etc.
Event-drivenper-consumerper-topic + lagevent-level correlation IDsKafka UI / Datastreams
Edge functionsper-regionper-regionOTel + providerCloudflare Trace Workers, Vercel Observability

OpenTelemetry (OTel, CNCF 2019 merger of OpenTracing + OpenCensus) is the de-facto standard 2023+ for distributed tracing. See observability-stack.

12. Cost profile

ArchitectureCompute costNetwork costOperational costEngineering cost
Monolithlow (reserved instance)low (intra-process)lowlow
Modular monolithlowlowlowmedium (discipline)
Microservicesmedium (overprovisioned to avoid cascading failure)high (inter-service hops, NAT)high (K8s + mesh + observability stack)high (oncall + tooling)
Serverlessusage-based; explosive past breakevenusage-basedlow (provider-managed)medium (cold start + provider lock-in)
Event-drivenmediummedium (broker)medium (broker ops)high (event schema discipline)
Edge functionsusage-basedminimallowmedium (cold start, runtime limits)

The serverless breakeven point: roughly 30% sustained utilization vs reserved capacity. Below 30%, serverless wins on cost. Above, reserved instances win. Provisioned concurrency softens the cold-start tax but costs like reserved.

13. Decision tree

What size is your team / how mature is the product?
├─ Solo / pre-PMF / < 5 engineers
│    → Monolith. Stop. Don't read the rest.
│    → e.g., Heroku-deployed Rails / Django / Phoenix
├─ 5–30 engineers, single product
│    → Modular monolith.
│    → Shopify, Basecamp, GitLab examples.
│    → Use bounded contexts (DDD) inside the monolith.
├─ 30–100 engineers, multiple product lines
│    → Macroservices (~5–30 services).
│    → Stripe-style: each service is large + owned by 1 team.
│    → Avoid premature decomposition.
├─ 100+ engineers, clear bounded contexts, scaling pain in deploy / data
│    → Microservices, organized into DDD domains.
│    → DOMA-style aggregation to avoid "service explosion".
│    → Need: service mesh, distributed tracing, K8s.
├─ 1000+ engineers
│    → Microservices with strong platform team.
│    → Netflix, Amazon, Uber DOMA scale.
│    → Internal developer platform (IDP) becomes a product.
├─ "I have spiky traffic and don't want to manage servers"
│    → Serverless (Lambda, Cloud Run, Vercel, Cloudflare Workers).
│    → Watch breakeven; cold start; vendor lock-in.
├─ "I need an audit log of every change, replayable"
│    → Event sourcing + CQRS.
│    → Financial systems, healthcare, regulated; Klarna, Walmart Inventory.
│    → Event schema discipline is mandatory; events live forever.
├─ "I need real-time analytics + transactional"
│    → Lambda or Kappa.
│    → Kappa preferred 2020+; Flink + Kafka.
├─ "I have a long-running multi-step workflow that needs to survive crashes"
│    → Workflow orchestration (Temporal, Step Functions, Cadence, Camunda).
│    → Don't roll your own state machine.
├─ "I want global low-latency"
│    → Edge functions (Cloudflare Workers, Vercel Edge, Fastly).
│    → Combine with edge DB (Turso libSQL, D1, Upstash).
└─ "I'm doing collaborative real-time"
     → CRDT-based + websocket/SSE.
     → Yjs + Liveblocks + edge.

14. The anti-patterns

  1. Distributed monolith — services that must deploy together because of tight schema coupling. Worse than a monolith.
  2. Nanoservices — one-function-one-service. Communication cost dwarfs compute. Uber learned this 2018–2020.
  3. Shared database across microservices — destroys the bounded-context boundary. Tempting; always wrong.
  4. Synchronous chain of calls through 5+ services — cascading failures, latency multiplication.
  5. 2PC across microservices — see §6 above. Use sagas.
  6. Event sourcing for everything — overkill for CRUD apps. Reserve for audit-heavy domains.
  7. Microservices before product-market fit — wastes engineering capacity solving a problem you don’t have.
  8. Monolith with no module boundary discipline — becomes a big-ball-of-mud at scale 50+.

15. The 2024–2026 frontier

  • Internal Developer Platforms (IDPs) — Backstage (Spotify, CNCF), Humanitec, Port, Cortex. Codifies the platform team’s offerings as a product.
  • Cell-based architecture (AWS, Netflix Vault) — bulkhead microservices into cells; each cell is independent. Recovery and blast-radius gains.
  • Sidecar-less mesh (Cilium) — eBPF instead of Envoy sidecar; 50–80% latency reduction.
  • WASM Components + WASI Preview 2 (2024) — WASM-as-microservice; Cosmonic, Fermyon Spin, Suborbital.
  • Active-active multi-region by default — Aurora DSQL, Spanner, CockroachDB, Yugabyte ship with this.
  • Service catalog + ownership (Backstage + OpsLevel + Cortex) — answering “who owns this service” at 1000+ service count is its own engineering problem.
  • Server Components / RSC (React 18+, Next.js 13+, Remix) — blur monolith/edge boundary at the rendering layer.
  • Database-per-tenant (Turso libSQL, Neon branches, Crunchy Bridge) — many small DBs instead of one big DB with row-level security.
  • The Prime Video reversal — public lesson that “microservices for everything” was an overcorrection. Match workload to architecture.

Adjacent

When to pick what

The fastest narrowing: < 30 engineers → modular monolith; 30–100 + bounded contexts → macroservices (5–30 large services); 100+ + clear domains → microservices organized DDD-style (DOMA); spiky / event-driven workload → serverless functions; global low-latency static-heavy → edge functions; audit-heavy financial / regulated → event sourcing + CQRS; multi-step durable workflow → Temporal/Step Functions. The single biggest mistake of 2015–2020 was premature microservices — splitting a monolith before you had bounded contexts to split along. The 2020–2025 lesson is the inverse direction: consolidate back when the inter-service tax outweighs the team-autonomy gain. Choose by team topology, deployment cadence, and blast-radius requirements; ignore Twitter’s microservices porn.