Architecture

Architectural Patterns for Web Applications: When Each Pays Off

Monolith, services, microservices, edge functions — each pattern has a context where it pays off and a context where it costs more than it returns. An analysis of when each pattern is the right choice.

On this page 9 sections
  1. 1 The monolith
  2. 2 The modular monolith
  3. 3 Services architecture
  4. 4 Microservices
  5. 5 Edge functions and serverless
  6. 6 The decision framework
  7. 7 The most-common mistake
  8. 8 The takeaway
  9. 9 Source notes

Architectural pattern selection in web applications is one of the most-consequential and most-frequently-misapplied engineering decisions. Patterns that pay off for large teams cost small teams dearly; patterns that suit small teams break down at scale. The right choice depends on team size, organizational structure, scale, and operational maturity. This article documents the contexts where each major pattern produces value and where it produces overhead without return.

The monolith

A single deployable application containing all business logic, often with a shared database. The simplest pattern, frequently dismissed as outdated, frequently the correct choice.

Pays off when:

  • Team size is under approximately 15 engineers working on the codebase
  • Deployment frequency is reasonable (daily to weekly), not extreme
  • The product domain is reasonably cohesive (not many independent capabilities)
  • Operational tooling investment is limited

Costs more than it returns when:

  • Team grows past the size where everyone can hold the system in mind
  • Deployment frequency requires team independence that the shared codebase prevents
  • Performance characteristics of one capability (e.g., search) are bottlenecked by another (e.g., reporting)

The default for most projects. Most web applications never reach the scale where moving away from a monolith pays off. The pattern is undervalued by mid-career engineers and overvalued by engineers who haven't felt the operational cost of distributed systems.

The modular monolith

A monolith with strong internal module boundaries — each module has its own data ownership, internal API, and team responsibility. Single deployable, multiple internal teams.

Pays off when:

  • Team size is 15-50 engineers across multiple sub-domains
  • The product has natural module boundaries (auth, billing, content, etc.)
  • Operational complexity of true services is not yet justified
  • You want to preserve future optionality to extract services if needed

Costs more than it returns when:

  • Modules don't actually have natural boundaries (forced module structure becomes overhead)
  • Module owners can't resist sharing data or calling into each other's internals
  • Build and deploy times become unmanageable due to total codebase size

The pragmatic mid-stage architecture. Often the right step before "real" services. Allows team independence within a single deployable; defers the operational complexity of distributed systems.

Services architecture

A small number of independently-deployable services (3-10), each owned by a team, communicating via well-defined APIs. Not microservices — services with meaningful scope.

Pays off when:

  • Team size is 50+ engineers across multiple product areas
  • Different services have different technical requirements (latency, scaling, language fit)
  • Organizational independence between teams is meaningful
  • Operational tooling for distributed systems is mature (observability, deployment, debugging)

Costs more than it returns when:

  • Team size doesn't justify the coordination overhead
  • Service boundaries don't align with team boundaries
  • Operational maturity is missing (you'll spend more time debugging distributed failures than building features)
  • Latency requirements are tight (network calls add up)

The intermediate-scale architecture. Right for many large companies, wrong for many small ones that adopt it prematurely. The "I want to be Netflix" architecture is mostly the wrong architecture for not-Netflix companies.

Microservices

Many small services (10+, sometimes hundreds), each focused on a specific capability. Often associated with container orchestration, service meshes, and elaborate operational tooling.

Pays off when:

  • Engineering organization is 100+ across many teams
  • Services have genuinely independent scaling, deployment, and ownership
  • Operational excellence is built (observability, on-call rotations, incident response)
  • The business benefit of independent service evolution exceeds the operational cost

Costs more than it returns when:

  • Team size doesn't support the coordination complexity
  • Service boundaries are wrong, requiring frequent multi-service changes for single features
  • Operational maturity is missing (most failures, both organizationally)
  • "Distributed monolith" pattern emerges (services that must deploy together, share state, etc.)

The architecture you should be very confident about before adopting. The cost of premature microservices is large; the cost of late adoption is recoverable. Default toward later adoption.

Edge functions and serverless

Functions deployed to a global edge network, scaled per-request, no persistent servers. The relatively new pattern that suits specific workloads well.

Pays off when:

  • Workload is bursty or unpredictable (no idle servers needed)
  • Latency to global users matters (edge proximity)
  • Operational simplicity matters more than runtime efficiency
  • The work fits the function model (stateless, short-running, event-driven)

Costs more than it returns when:

  • Workload requires persistent connections or long-running processes
  • Cold-start latency is unacceptable for the use case
  • Per-request pricing exceeds reserved-capacity pricing at your scale
  • Vendor lock-in is a strategic concern

The complement to traditional architectures, not the replacement. Edge functions excel at API endpoints, transforms, and request handling. They're weak for long-running workloads or stateful systems.

The decision framework

For any architectural pattern selection:

  1. Start with the smallest pattern that supports your team size and scale. Default toward simplicity; add complexity when forced by real constraints.
  2. Don't adopt patterns aspirationally. "We'll grow into it" usually means "we'll pay coordination costs we don't need to pay yet."
  3. Match the pattern to organizational reality. Service boundaries should align with team boundaries; if they don't, the architecture works against the organization.
  4. Build operational maturity before adopting distributed patterns. Microservices without observability is a nightmare; observability without microservices is just good engineering.
  5. Plan for evolution. Architectures that lock you out of future changes are expensive. Patterns that preserve optionality (modular monolith, well-bounded services) generally serve better than patterns that constrain it.

The most-common mistake

Adopting an architecture appropriate for a much larger company. Microservices for a 10-person team. Service mesh for a system with 4 services. Event-sourcing for an application with simple CRUD requirements. Each of these is a real pattern that solves real problems at real scale; deployed at the wrong scale, each becomes pure overhead.

Match the architecture to your actual context, not your aspirational one.

The takeaway

Architectural pattern selection is fundamentally a constraint-satisfaction problem: what serves your team size, scale, organizational structure, and operational maturity? The right answer for a 10-person team is rarely the right answer for a 100-person team, and vice versa.

Default toward the simplest pattern that supports your actual situation. Add complexity only when forced by genuine constraints. The companies that ship reliably at scale are usually the ones that resisted architectural sophistication longer than their peers.

Source notes

Pattern descriptions draw on the published architectural literature (Sam Newman's Building Microservices, Mark Richards' architectural pattern catalog) and aggregated post-mortem analysis from engineering blog publishing 2020-2025. Specific scale thresholds based on industry reports including the State of DevOps reports.