An architecture style is a family of designs with the same shape: a monolith, a modular monolith, web-queue-worker, microservices, event-driven, serverless or cell-based. Choosing one means deciding which constraints you accept in exchange for which qualities. There is no best style, only the one whose costs you can pay and whose benefits you actually need, for this team, this domain and this load, today.
Picture it first: choosing how to move goods
A kirana store delivers on one scooter. A regional distributor runs a few tempos from one godown. A national e-commerce company runs hundreds of trucks out of dozens of hubs, each hub serving its own area, so a flood in one city doesn’t stop deliveries in another. For a one-off rush, anyone can hire cabs by the trip.
No vehicle is “best”. The scooter is cheap and nimble but carries little; the truck fleet carries everything but needs dispatchers, mechanics and route planners before it moves a single parcel; hired cabs cost nothing when idle and a lot per kilometre when busy. The right choice depends on the load, the routes, the crew and the budget, and it changes as the business grows.
Map it back. The scooter is a monolith, the tempos from one godown a modular monolith with a few services, the truck fleet microservices with their platform, the hubs cells, and the hired cabs serverless. The load, routes, crew and budget are the forces this article is about.
Styles are bundles of trade-offs
Azure’s Architecture Center describes a style as a family of architectures that share characteristics, and makes a useful point: a style is a set of constraints. It restricts which elements can appear and how they may relate, and when you respect those constraints, certain properties emerge. Its microservices example: each service has one responsibility, services are independent, and each owns its data. Respect those and you get independent deploys, fault isolation, frequent updates and freedom to adopt new technology.
The same constraints create the challenges Azure lists for every style: complexity that must match the domain, asynchronous messaging and eventual consistency, communication overhead between services, and manageability: monitoring, deploying and keeping everything healthy. Two pieces of its advice shape the rest of this page. Focus on why you select a style more than on how to implement it, and be practical: relaxing a constraint can beat architectural purity. And weigh benefits against challenges for each subdomain and bounded context, not once for the whole company.
The catalogue on one page
Each row links to the article that covers the style in depth; here the point is the trade.
| Style | Shape | Optimises for | Costs you |
|---|---|---|---|
| Layered (N-tier) monolith | One deployable in horizontal layers: UI, logic, data | Simplicity, one transaction, fast early delivery | Changes ripple across layers; one release train (monolith vs microservices) |
| Modular monolith | One deployable, modules per business area with private tables, boundaries checked in CI | Cheap in-process calls with real seams to split later | Discipline and tooling to keep modules honest; still one blast radius |
| Web-queue-worker | Web front end, a queue, background workers | Fast responses with heavy work moved off the request path | Front end and worker can each grow into monoliths |
| Microservices | Independently deployable services per bounded context, each owning its data | Team autonomy, independent deploys and scaling, fault isolation | Network hops, sagas instead of transactions, a platform before features |
| Event-driven | Producers publish facts; consumers react through a broker | Loose coupling, fan-out, absorbing bursts | Eventual consistency, duplicates, harder debugging (event-driven architecture) |
| Serverless | Functions plus managed services, scale to zero, pay per use | Spiky or idle workloads, no servers to run | Cold starts, limits, cost at steady load, lock-in (serverless architecture) |
| Cell-based | Many independent copies of the stack, each serving a slice of users | Blast-radius limits at very large scale | Routing layer, duplicated infrastructure, cross-cell features (cell-based architecture) |
Two more styles in Azure’s list, big data and big compute, are specialised: analytics pipelines and high-performance computing. Underneath every row sits a communication topology: almost all of them are client-server at the edge, where clients ask and servers answer, while peer-to-peer systems, from file sharing to video calls, make every node both client and server to avoid a central bottleneck. Styles also mix: a microservice is usually internally layered, and an event-driven system is often microservices that talk by events.
The forces that decide
A style is only right relative to the forces acting on your system. These are the ones that matter most, with how each pushes the choice:
| Force | Pushes towards | Rule of thumb |
|---|---|---|
| Teams | 1–2 teams: one deployable. Many teams: services per bounded context | A team may own several services; a service never has several owning teams |
| Domain maturity | Unknown domain: monolith first | Don’t fix service boundaries before you’ve watched the domain change |
| Load shape | Spiky or idle: serverless. Steady and high: containers. One hot spot: extract that part | The serverless article’s example breaks even at about 27 requests a second |
| Latency and availability | Fewer synchronous hops | N hops at 99.9% each succeed 0.999ᴺ of the time |
| Consistency | Data that must change atomically stays in one service | One ACID transaction means one owner; otherwise a saga |
| Operational maturity | Without the basics: monolith | Provision in hours, monitor errors and orders, deploy in a couple of hours, devs on call |
| Cost | Fewer, larger deployables; pay-per-use for idle work | Every service adds a pipeline, dashboards, alerts and upgrades |
| Compliance and isolation | Separate the regulated part; cells or silos for tenants | Shrink the audit scope to the smallest component that touches the data |
| Time to market | The simplest thing that ships | A sacrificial monolith is fine if it gets you to market |
Teams first. Amazon’s rule is to build teams no larger than two pizzas can feed, and give them end-to-end ownership. Coordination is what grows: the possible conversations among n people are n(n − 1)/2, so a 6-person startup has 15 and 280 engineers have 39,060. A 6-person team gains nothing from service boundaries it must cross by itself; 40 teams of 7 sharing one release train lose weeks to coordination. Services are mainly a tool for letting teams move without each other.
Domain maturity. Fowler’s MonolithFirst observes that almost every successful microservice story began with a monolith that grew too big, and almost every system built as microservices from scratch got into serious trouble. His two reasons: you don’t yet know whether the product is useful, so speed matters most, and you can’t draw stable boundaries yet, while moving functionality between services is far harder than inside one codebase.
Scale is weaker than people think. Stack Overflow’s 2016 write-up describes 209 million HTTP requests in one day, about 2,400 a second on average (209,420,973 ÷ 86,400), served by nine primary web servers and four SQL Servers, with one multi-tenant Q&A application serving every Q&A site. High traffic alone doesn’t force a split; caches, replicas and a well-tuned monolith go a long way. What forces splits is usually team count, a workload with a very different shape, or isolation.
Operational maturity. Fowler’s MicroservicePrerequisites are a gate, not a wish list: provision a server in hours, monitor technical and business signals (a drop in orders), deploy through a pipeline that runs in no more than a couple of hours, with developers and operators handling incidents together. Beyond a handful of services you also need distributed tracing and full continuous delivery. If you don’t have these, the choice is made for you.
Latency, consistency and compliance. Every synchronous hop adds a network round trip and multiplies availability: three services in a chain at 99.9% each give 0.999³ ≈ 99.7%, about 130 minutes of failure a month instead of 43. So the latency budget caps how many services one request may touch in series, usually two or three. Consistency draws hard lines: data that must commit together belongs to one service, because across services you trade a ROLLBACK for a saga with compensating steps. Compliance pulls the other way, towards more separation: putting card or UPI data in one small service shrinks what the auditor inspects, and regulated tenants may need their own silo or cell.
Cost and time to market. A monolith is the cheapest thing to build and run until coordination costs dominate; each extra service adds a pipeline, dashboards, alerts and upgrades. Serverless makes idle time free and steady load expensive. When the deadline is the main force, ship the simplest design and plan to replace parts of it: Fowler calls this a sacrificial architecture.
In the interview
Name the force before the style: “We have one team and a domain we’re still learning, so I’ll start with a modular monolith; payments is separate because of its audit scope.” A style without a force sounds like fashion; a force without a style sounds like analysis paralysis.
A decision flow, not a dogma
Put the forces together and a practical path appears. Start simple, and add each style where a force demands it, for the part of the system that feels the force.
Three details make the flow work. Draw the modules along bounded contexts from the start, so a later split follows a seam that already exists. Treat each “yes” as permission to change one context, not the whole system. And let the boring answer win ties: a queue and a worker solve most “this is slow” problems long before a new style does.
What real teams learned
Segment (2018): back from 140+ services to one. Segment had given each of its 140+ event destinations its own service and queue to isolate failures. The small team ended up with three full-time engineers spending most of their time keeping the system alive. They merged everything into one service behind a new queueing system, and shared-library improvements rose from 32 in the microservices year to 46 the year after; one engineer could deploy in minutes. They accepted the price openly: weaker fault isolation, less effective in-memory caches spread over 3,000+ processes, and dependency upgrades that can break many destinations at once.
Shopify (2016–2019): a modular monolith on purpose. Shopify’s Rails monolith, worked on by more than a thousand developers, had become fragile by 2016: innocuous changes caused cascades of unrelated test failures. The team considered microservices and rejected them for the pipelines, infrastructure, network latency and cross-service refactors they would bring. Instead they sorted about 6,000 classes into components and built a tool, Wedge, to track boundary violations. One deployable, real seams.
Prime Video (2023): one service, not the company. A single quality-monitoring tool moved from serverless orchestration to one process and cut its infrastructure cost by over 90%; the story, and why it is about workload shape, is in serverless architecture.
Stack Overflow (2016): one application at scale. The traffic figures above came from a single multi-tenant Q&A application, which rendered question pages in about 23 ms on average; products such as the API and Careers ran as separate applications. Scale alone didn’t demand a split.
None of these teams were wrong at the start. Each chose for the forces it had, and changed style when the forces changed.
Most real systems are hybrids
The question is rarely “which style?” but “which style where?”. A food- or grocery-delivery platform at scale might run a modular monolith for its core, separate services for payments and rider location, events between them, a queue-fed worker for notifications, functions for document generation, and the whole stack copied per region as cells.
Architecture evolves: a sequence of decisions
An architecture isn’t chosen once; it is a sequence of decisions, each made with what you knew at the time. Amazon’s 2015 shareholder letter gives a useful split. One-way doors (Type 1) are consequential and nearly irreversible, and deserve slow, careful deliberation. Two-way doors (Type 2) can be reversed, and should be made quickly by small groups; the letter warns that using the heavyweight process for every decision causes slowness and too little experimentation.
Most style choices are two-way doors if you keep the seams: extracting a module behind an existing interface is a routine change. The one-way doors are mostly about data: splitting a shared database, choosing a primary datastore, or publishing an event schema many teams consume. Spend your deliberation there.
To keep an architecture honest as it evolves, write fitness functions: automated checks of an architectural characteristic, as Thoughtworks describes them, built from tests, metrics and monitors. Examples: a CI check that fails if one module reads another module’s tables; a load test that fails if checkout p99 exceeds 300 ms; an alert if the deploy pipeline takes longer than 30 minutes. They turn “we chose a modular monolith” into something the build enforces.
Recording the decision: ADRs
Michael Nygard’s 2011 post proposed Architecture Decision Records: short text files kept in the repository, one per architecturally significant decision, numbered and never reused. Each has a title, the context (the forces at play, stated neutrally), the decision (“We will …”), a status (proposed, accepted, deprecated or superseded) and the consequences, all of them, not just the good ones. When a decision is reversed you keep the old record and mark it superseded, so a newcomer can see what was decided, why, and when the context changed. Nygard’s own test: write it as a conversation with a future developer, in one or two pages.
ADR 007: Start as a modular monolith with an isolated payments service
Status: Accepted (2026-10-27)
Context: 12 engineers in 2 teams; launch in 4 months. The domain
(bill payments, rewards) is new to us and will change weekly. Traffic
is spiky around salary days. Card and UPI data must stay in a small
audit scope. We have CI/CD and basic monitoring, but no tracing.
Decision: We will build one deployable with modules per bounded
context (accounts, billers, rewards, notifications), each with its own
schema, boundaries checked in CI. Payments runs as a separate service
with its own database. Reminders and receipts run as queue-fed workers.
Consequences: Fast delivery and one pipeline. One blast radius for
everything except payments. A payments call adds a network hop to
checkout. We revisit this when we pass 4 teams, or when one module
needs a different scaling profile. Supersedes nothing.
Worked example: a weighted decision matrix
Take the startup in that ADR: a UPI bill-payments app with 12 engineers, launching in four months, with spiky salary-day traffic and a compliance scope. Score four candidates from 1 to 5 on six criteria, and weight the criteria by what matters to this company now.
Startup weights: time to market 30%, operational simplicity 25%, team autonomy 5%, compliance isolation 15%, cost at this load shape 10%, evolvability 15%. Multiply each score by its weight and add. For the modular monolith:
0.30 × 4 + 0.25 × 5 + 0.05 × 3 + 0.15 × 3 + 0.10 × 3 + 0.15 × 5 = 1.20 + 1.25 + 0.15 + 0.45 + 0.30 + 0.75 = 4.10
The same sum gives 3.70 for the plain monolith and for serverless, and 2.50 for microservices, which lose on time to market and operational simplicity, the two heaviest weights.
The modular monolith wins at 4.10, with serverless close behind at 3.70, which hints at the real answer: a modular monolith with serverless or queue workers for the spiky jobs, as the ADR says.
Now re-run it five years later, with 40 teams, a platform team and steady high traffic. The weights move to time to market 10%, simplicity 5%, autonomy 35%, compliance 20%, cost 10%, evolvability 20%, and a steady load rescores cost: 4 for both monoliths, 3 for microservices, 1 for serverless. Microservices now score 0.10 × 2 + 0.05 × 1 + 0.35 × 5 + 0.20 × 5 + 0.10 × 3 + 0.20 × 3 = 3.90, ahead of the modular monolith at 3.70, serverless at 3.45 and the monolith at 2.30.
The weights are the decision
A matrix looks objective, but between the two runs only the cost row of scores changed; the weights did the rest. So argue about the weights with your stakeholders first, write them down in the ADR, and treat any close result (4.10 against 3.70) as a tie to be broken by judgment, not decimals.
When to pick each style
| Pick it when | Avoid it when | Watch for | |
|---|---|---|---|
| Layered monolith | One team, a new or simple product, speed matters most | Several teams queue behind one release | Boundaries eroding into a big ball of mud |
| Modular monolith | The default for most products, even with hundreds of developers (over a thousand have worked on Shopify’s) | Parts need truly different scaling, runtimes or audit scopes | Modules reaching into each other’s tables |
| Web-queue-worker | A simple domain with heavy or slow background work | Many independent workflows with different owners | Front end and worker both growing into monoliths |
| Microservices | Many teams, stable bounded contexts, platform in place | Small team, unknown domain, no tracing or CI/CD | The distributed monolith: shared data, lockstep deploys |
| Event-driven | Fan-out, workflows that tolerate delay, absorbing bursts | The caller needs an immediate, consistent answer | Duplicates, ordering, invisible coupling through schemas |
| Serverless | Spiky, idle or glue workloads; small ops team | Steady high load, long jobs, heavy state | Cost at scale, cold starts, concurrency limits |
| Cell-based | Millions of users where one bad deploy is unacceptable | Early stage or one region’s worth of users | Cross-cell features, cell routing and capacity planning |
Going deeper: mistakes and signals
Common mistakes
- Choosing by résumé or hype. “Netflix uses microservices” is not a force acting on your system. Ask which force the style answers.
- Microservices before the platform. Without fast provisioning, monitoring, pipelines and tracing, you get a distributed monolith: Segment’s three engineers keeping 140+ services alive is the cautionary tale.
- One style everywhere. Most real systems are hybrids. Forcing every part into events, or into functions, makes the parts that don’t fit painful.
- Ignoring the data. Code splits in days; shared tables take months. If two services would share a database, you haven’t split anything (monolithic persistence).
- Premature cells. Cells pay off when one deploy can hurt millions of users. Before that, they multiply your infrastructure and add a routing layer for little benefit.
- No exit plan. Every choice should state when you will revisit it, in the ADR’s consequences.
Signals that it is time to change
| Signal | Likely move |
|---|---|
| Teams queue for one release train; deploys need cross-team sign-off | Split along the busiest bounded context |
| One module’s load or hardware needs differ sharply from the rest | Extract it, or move it to queue-fed workers |
| An auditor’s scope covers the whole codebase | Isolate the regulated data in its own service |
| Every feature changes the same three services together | Merge them back |
| Small team, many services, most of the week spent on upkeep | Consolidate, as Segment did |
| An incident in one region or tenant group takes down everyone | Introduce cells along that fault line |
Move one part at a time
Changing style is a migration, not a rewrite. Extract one context behind the strangler fig, move its data last, and check fitness functions before taking the next step (strangler fig and anticorruption layer).
Cheat sheet
| Remember | Rule or number |
|---|---|
| What a style is | A set of constraints; qualities emerge if you respect them |
| Default | Modular monolith, modules along bounded contexts, a queue for background work |
| Split when | A force appears: team contention, a hot spot, a compliance scope |
| Teams | Two-pizza teams; coordination paths n(n − 1)/2: 6 people → 15, 280 → 39,060 |
| Availability | 3 synchronous hops at 99.9% ≈ 99.7%; keep chains to 2–3 |
| Prerequisites | Provisioning in hours, monitoring, pipeline in a couple of hours, DevOps culture |
| Serverless | Spiky or idle work; about 27 req/s break-even in the serverless example |
| Scale alone | Stack Overflow: ≈ 2,400 req/s average from one Q&A app on 9 web servers |
| Decisions | Deliberate on one-way doors (data); move fast on two-way doors |
| Record it | ADR: title, context, decision, status, consequences |
| Matrices | The weights are the decision |
How to say it in the interview
“Before choosing a style, I want four answers: how many teams build this, how well we understand the domain, what the load looks like, and which latency, consistency and compliance constraints are hard. For this design, with one or two teams and a new domain, I’d build a modular monolith with modules along bounded contexts and their own schemas, and a queue with workers for anything that can finish after the response. Payments would be a separate service from day one because of its audit scope. I’d name the seams I expect to split later, such as rider location if its write load explodes, and say what would trigger the split: more teams, a hot spot or a new compliance need.”
Why not microservices from day one? You’d pay for the platform, network hops and sagas before you know whether the product works or where the boundaries are, and moving a boundary between services is far harder than between modules. The exception is a well-understood domain with several experienced teams from the start.
When would you pick serverless? For spiky, idle or glue workloads: webhooks, scheduled jobs, file processing, a results portal that sleeps most of the year. Not for steady high load, where per-request pricing overtakes always-on containers, or for long-running or stateful work.
How do you know it’s time to split the monolith? When a force appears that a module boundary can’t solve: teams blocked on one release train, a part with a very different scaling or hardware profile, or a compliance scope you want to shrink. Not because traffic grew, which caches and replicas usually handle.
How do you justify the choice to stakeholders? Tie it to their goals: time to market, cost, risk and compliance. Show the weighted criteria and agree the weights first, record the decision in an ADR with its consequences, and state the signal that will make you revisit it.
Is event-driven an alternative to microservices? No, they’re orthogonal. Event-driven is about how parts communicate; microservices are about how you deploy them. A modular monolith can publish events internally, and microservices often talk through events.
Where to go next
- Monolith vs microservices: the costs of splitting, Conway’s law and migration.
- Finding service boundaries with DDD: where to draw the seams.
- Event-driven architecture: events, brokers and the dual-write trap.
- Serverless architecture: cold starts, limits and the cost crossover.
- Sidecar, ambassador and service mesh: plumbing for many services.
- Cell-based architecture: limiting blast radius at scale.
- Client-server and peer-to-peer: the topologies underneath.
References and further reading
- Architecture styles (Azure Architecture Center)learn.microsoft.comThe six cloud styles, styles as constraints from which properties emerge, the microservices example, the dependency and domain-type table, and the four kinds of challenge.
- MonolithFirst (Martin Fowler, 2015)martinfowler.comSuccessful microservice systems mostly began as monoliths, the YAGNI and boundary arguments, four ways to run monolith-first, and the counter-argument.
- MicroservicePrerequisites (Martin Fowler, 2014)martinfowler.comRapid provisioning, basic monitoring, rapid deployment and a DevOps culture before a first handful of services; tracing and continuous delivery beyond that.
- Goodbye Microservices: From 100s of problem children to 1 superstar (Segment, 2018)twilio.comThree engineers keeping 140+ destination services alive, the merge into one service, 32 versus 46 library improvements, and the trade-offs accepted.
- Deconstructing the Monolith (Shopify Engineering, 2019)shopify.engineeringWhy Shopify chose a modular monolith over microservices in 2016, the 6,000-class componentisation and the Wedge boundary-tracking tool.
- Stack Overflow: The Architecture, 2016 Edition (Nick Craver)nickcraver.comA day of traffic (209 million HTTP requests), nine primary web servers, four SQL Servers, and one multi-tenant Q&A application for every site.
- Introduction to DevOps on AWS: Communication and collaboration (AWS whitepaper)docs.aws.amazon.comAmazon’s two-pizza team rule and team ownership of the end-to-end process.
- 2015 Letter to Shareholders (Amazon)s2.q4cdn.comOne-way-door (Type 1) and two-way-door (Type 2) decisions, and why using the heavy process for both causes slowness.
- Documenting Architecture Decisions (Michael Nygard, 2011)cognitect.comThe ADR format (title, context, decision, status, consequences), numbering, superseding instead of deleting, and keeping ADRs in the repository.
- Architectural fitness function (Thoughtworks Technology Radar)thoughtworks.comFitness functions as objective, automated checks that preserve architectural characteristics in an evolutionary architecture.