10 Web Application Architecture Patterns and When to Use Them
Monolith, modular monolith, microservices, serverless, event-driven, web-queue-worker, BFF, static-first and more: when each pattern fits and what it costs.
Which architecture pattern should a web application use?
Start with the simplest pattern that handles your known requirements: usually a monolith or modular monolith, with a queue and background workers for slow jobs. Move to serverless functions for spiky or occasional workloads, to event-driven designs when several systems must react to the same business events, and to microservices only when separate teams need to release independently and you can afford the operational overhead. Patterns can be combined, and the right answer changes as the product and team grow.
This guide is for founders, product owners and technical leads making or reviewing architecture decisions. Microsoft's Azure Architecture Center makes the useful point that every style places constraints on a design and has trade-offs, and that the choice should follow from the problem and its priorities, such as time to market or budget. We have tried to show those trade-offs rather than rank the patterns. For the frontend layer, see frontend frameworks for web applications.
1. Monolith
One codebase and one deployable application containing the user interface, business logic and data access, usually with one database. It is the default for good reasons: one thing to build, test, deploy and monitor, and transactions that just work.
Use it when: you are building a first version, the team is small, or the domain is not yet well understood. Limits: without discipline it becomes tangled, and every change redeploys everything. Scaling is all or nothing, although that rarely matters as early as people fear.
2. Modular monolith
Still one deployable application, but divided internally into modules with clear boundaries, such as billing, catalogue and accounts, which talk to each other through defined interfaces and own their own data.
Use it when: the application is growing and you want the structure that makes a later split possible without paying for distribution now. Limits: boundaries need enforcing, through code review or tooling, or they erode. See modular monolith vs microservices.
3. N-tier (layered)
The application is split into layers, typically presentation, business logic and data, each calling only the layer below, and often deployed on separate servers. It is the traditional enterprise structure.
Use it when: you are modernising or moving an existing layered application, or working in an environment built around it. Limits: Microsoft notes that horizontal layering can make changes ripple across several layers, which slows frequent updates.
4. Web-queue-worker
A web front end handles requests and puts slow or heavy work, such as generating reports, sending emails, resizing images or calling slow APIs, onto a message queue. Separate worker processes take jobs from the queue. Microsoft's guide describes it as ideal for relatively simple domains with some resource-intensive processing.
Use it when: users should not wait for slow tasks, or you need retries for work that can fail. Most monoliths benefit from adding this early. Limits: you need to handle failed jobs, duplicates and monitoring of the queue. See queue architecture for reliable processing.
5. Microservices
The application is split into small services, each owning one business capability and its own data, deployed and scaled independently and talking over APIs or messages. Microsoft notes the benefit, team autonomy and faster releases in complex domains, and the cost: service discovery, data consistency and distributed operations, which need mature development and DevOps practice.
Use it when: several teams need to release independently, parts of the system have very different scaling or reliability needs, and you have the platform skills to run it. Limits: harder debugging, network latency between services and no simple cross-service transactions. Many teams adopt it too early.
6. Serverless functions
Code runs as functions triggered by HTTP requests, schedules or events, on a platform that provisions and scales the servers for you and usually bills per execution.
Use it when: workloads are spiky or occasional, such as webhooks, scheduled jobs, file processing or a low-traffic API, and you want minimal operations. Limits: cold starts, execution time limits, harder local testing and costs that can exceed a server at steady high volume. See Kubernetes vs serverless vs virtual machines.
7. Event-driven architecture
Components publish events ("order placed", "invoice paid") to a broker, and any number of consumers react independently. Producers do not need to know who is listening. Microsoft lists its strengths as scalability and fault isolation, and its challenges as guaranteed delivery, ordering and eventual consistency.
Use it when: several systems must react to the same business events, such as fulfilment, analytics and email after an order, or you are integrating many systems without point-to-point tangles. Limits: it is harder to see the whole flow, and consumers must cope with duplicates and out-of-order events. See event-driven architecture and integration architecture patterns.
8. Backend for frontend (BFF)
A thin server layer built for one client, such as the web app or the mobile app, which gathers data from backend services and shapes it for that client's screens.
Use it when: web and mobile apps need different data shapes, or a frontend would otherwise make many calls to several services. Limits: another layer to maintain, and logic can be duplicated between BFFs if business rules leak into them.
9. Static-first (Jamstack-style) with APIs
Pages are pre-built as static files at build time and served from a CDN, with dynamic features handled by APIs and serverless functions. Modern frameworks blend this with server rendering per page.
Use it when: most content changes infrequently, such as marketing sites, documentation and blogs, and you want fast pages and simple hosting. Limits: frequently changing or personalised pages need server rendering or client-side data. See static generation vs server rendering.
10. Strangler fig (for replacing legacy systems)
Rather than rewriting a legacy application in one go, you route traffic for one feature at a time to new code while the old system handles the rest, until the old system can be retired. Martin Fowler named it after the strangler fig, which grows around a host tree.
Use it when: replacing a business-critical system that cannot be frozen for a big-bang rewrite. Limits: running two systems in parallel costs more for a while, and data must stay in sync between them. See legacy migration.
Reviewing an architecture decision?
ZSpace Labs designs and builds web applications in Next.js, React and TypeScript, and can review whether your planned architecture fits your team and product. See our web application development service.
Comparison table
| Pattern | Best fit | Main benefit | Main cost |
|---|---|---|---|
| Monolith | First versions, small teams | Simplicity | Can tangle as it grows |
| Modular monolith | Growing products | Structure without distribution | Boundaries need enforcing |
| N-tier | Existing layered apps | Familiar separation of concerns | Changes ripple across layers |
| Web-queue-worker | Apps with slow or heavy tasks | Responsive UI, retries | Queue operations |
| Microservices | Several teams, complex domain | Independent releases and scaling | Distributed complexity |
| Serverless functions | Spiky or occasional workloads | No servers to manage | Cold starts, limits, cost at scale |
| Event-driven | Many systems reacting to events | Loose coupling | Ordering, duplicates, visibility |
| Backend for frontend | Separate web and mobile clients | Client-shaped APIs | Extra layer |
| Static-first with APIs | Content-heavy sites | Speed, simple hosting | Dynamic pages need more work |
| Strangler fig | Replacing legacy systems | Low-risk, gradual migration | Two systems for a while |
How to choose
- Write down the two or three qualities that matter most (time to market, cost, reliability, scale) before discussing patterns.
- Count the teams. One team rarely needs independently deployable services.
- Find the slow or failure-prone work and put it behind a queue, whatever else you choose.
- List the systems that must react to your business events; several suggests events, one or two suggests direct calls.
- Check your operations capacity: who will run the monitoring, deployments and incident response the pattern needs?
- Revisit the decision as the product grows; an architecture review every year or two is cheaper than a forced rewrite. See software architecture reviews.
Conclusion
Most business web applications are best served by a modular monolith with a queue and workers, a static-first public site, and events where other systems need to react. Microservices, serverless and BFFs solve real problems, but each adds cost that should be justified by a specific need. If you are deciding what to build in the first place, start with the types of web application businesses build.
Sources
Microsoft Azure Architecture Center, architecture styles (N-tier, Web-Queue-Worker, microservices, event-driven), updated September 2025. Martin Fowler, MonolithFirst (2015) and StranglerFigApplication. Accessed 28 October 2026.
Common questions.
There is no single best one. For most new business applications, a well-structured monolith or modular monolith with a background job queue is the simplest thing that works. Other patterns earn their place when a specific problem, such as independent team releases, spiky workloads or real-time event processing, justifies their extra cost.