Software Architecture

Modern Web Architectures: Part 1

Monoliths, microservices and serverless. What each one buys you, what it costs, and how to pick without cargo-culting whatever the last conference talk recommended.

Monolith, microservices and serverless architectures compared

The short version

  • Web application architecture is the blueprint that determines whether your product can absorb growth or has to be rebuilt to survive it.
  • Microservices buy independent deployability and team autonomy, and charge you in operational complexity. Start with a monolith and split along business capabilities, not layers.
  • Serverless buys elasticity and shrinks your attack surface, and charges you in cold starts, vendor coupling and awkward storage.
  • Neither is a default. Both are answers to specific problems you should be able to name before you adopt them.

Web application architecture is the framework of relationships and interactions between an application’s components — middleware, user interfaces, databases, web servers, load balancers. In plain terms, it is the pattern by which the pieces talk to each other.

It matters because it is the blueprint for supporting future growth. That growth might come from increased demand, from new interoperability requirements, or from reliability expectations that were not on the table when you shipped version one. Architecture is what determines whether meeting those requirements is a sprint or a rewrite.

As technology evolves, so do the prevailing patterns. Service-oriented designs put most of the application behind HTTP APIs, so one part of the system can call another that happens to be running on a different machine entirely. Single-page applications push the interface into a rich JavaScript client that persists in the browser across many interactions, using AJAX or WebSockets to talk to the server without a full page load.

The architectures currently worth understanding are:

  • Microservices
  • Serverless architectures
  • Single-page applications
  • Progressive web applications
  • API-first design

This article covers the first two. Part 2 takes on the rest.

Microservices architecture

The “micro” implies small applications. That is occasionally true, but the better framing is that each service should be only as big as it needs to be to do one particular thing or solve one specific problem.

Microservices means structuring an application as a collection of autonomous services that communicate through relatively stable APIs. As Microsoft puts it, microservice architectures should be designed around business capabilities, not horizontal layers such as data access. The consequence is that the core functionality of an individual service can be upgraded without disturbing the rest of the system.

This ties directly into how teams practising DevOps want to work. If the functions of a broader application are segmented into discrete, independently operating pieces, continuous integration and continuous delivery become genuinely achievable rather than aspirational. Well-defined APIs also make services straightforward to test automatically.

A monolithic application compared against the same functionality split into independent microservices
The same application as a single deployable unit and as a set of independently deployable services.

How to build microservices

  1. Start with a monolith. If you do not have users yet, your business requirements are going to change no matter how promptly you build your MVP. That is simply the nature of software development and the feedback cycle you need in order to discover which capabilities your system actually has to offer. Microservices work well once you have a firm grip on what those services are. Begin by separating your web UI from the logic behind it, and confirm they talk over a RESTful HTTP API.
  2. Organise your teams. So far this may have felt like a purely technical exercise: split a codebase, choose patterns for failing gracefully and recovering from network partitions, handle data consistency, monitor service load. It is not. Service boundaries that do not match team boundaries produce services that cannot be changed independently, which defeats the point.
  3. Split the monolith. Once you know where your service boundaries are, and your teams are shaped around capabilities rather than layers, you can start carving. Keep inter-service communication simple with RESTful APIs. Divide the data structures deliberately. Design for failure from the outset. Invest in monitoring, because it is what makes testing a distributed system tractable. And lean on continuous delivery to keep deployment friction low.

When to reach for microservices

  • Migrating a monolith because you need better scalability, manageability or delivery speed.
  • Re-platforming a legacy application by converting its modules into services one at a time.
  • Rewriting a legacy application onto a modern language or stack to meet current business requirements.
  • Crosscutting services that are genuinely independent — encryption, authentication and similar.
  • Business services reused across multiple channels: payments, search, customer profiles, notifications.
  • Widely shared internal applications, such as time tracking.

The cost is real. Microservices convert a compile-time problem into a runtime one. A method call that used to fail loudly at build time becomes a network call that can time out, retry, partially succeed, or arrive twice. If your team cannot yet operate one service well, ten will not go better.

Serverless architecture

Serverless has attracted enormous attention from both veterans and newcomers — consultations, meetups, blog posts, everywhere. Beneath the hype there is a real proposition: business implementations that are simpler to reason about and often lighter on the budget.

What serverless actually means

Serverless is a cloud execution model in which the provider dynamically handles allocation and provisioning of servers. A serverless application runs in stateless compute containers that are event-triggered, short-lived and fully managed. In practice these are event-driven systems built from a combination of third-party services, client-side logic, and cloud-hosted functions.

Event-driven serverless functions invoked by triggers and managed entirely by the cloud provider
Functions as a service: event in, work done, container discarded.

How to approach serverless development

Before starting, weigh the business case. The economics can be compelling, but they need to be assessed against architectural investments you have already made and against the requirements actually pressing on you.

Blending and migration

Serverless is inherently a cloud phenomenon, so the sensible starting point is what your provider offers. Container technology helps ensure code and applications move cleanly between environments rather than being welded to one.

Security

Serverless removes a great deal of the traditional attack surface. Networks, host operating systems and long-running services all shrink dramatically as targets. What remains still demands vigilance: the function code itself, which services a function is permitted to reach, data access and misuse, and certain classes of denial-of-service attack. The provider is accountable for the underlying infrastructure; everything above it is still yours.

Storage

Storage is typically the riskiest part of a serverless design. Providers offer a range of options, some marketed as serverless, though you are not limited to those. Scalability is the deciding factor, and it is worth remembering that your data model shapes how well a storage system scales as much as the storage engine does. Choose both together.

When to consider serverless

  • Latency-tolerant background work such as media processing and batch data jobs.
  • Client-heavy applications where most of the logic can live on the client.
  • Applications with unpredictable or spiky load.
  • Fast-moving products that need to scale and change features quickly.

A useful test before adopting either. Write down the specific problem you expect the new architecture to solve, and the metric that will tell you it worked. If you cannot fill in both blanks, you are adopting a pattern rather than solving a problem — and you will pay the operational cost either way.

Boolean Solutions experience with architecture

We have built greenfield systems on all of these patterns and, more often, been brought in to untangle applications where the pattern was chosen before the problem was understood. The most common rescue we do is consolidating a premature microservices split back into a well-structured modular monolith, which is rarely what the team expects to hear and almost always what they need.

If you are weighing an architectural decision and want an outside opinion before you commit engineering quarters to it, get in touch.

Further reading

Written by

Udit Mittal

Founder at Boolean Solutions. Twenty years of building and rescuing web, mobile and AI products for SaaS companies and startups — and writing down what actually worked.

Get in touch