Chapter 1: Escaping Monolithic Hell

Why monolithic applications become painful at scale, how the microservice architecture helps, and the pattern language that guides adoption.

73 Concepts 42 Patterns 11 Definitions 7 Problems 5 Tradeoffs 7 Principles 1 Technology

Table of Contents

  1. 1.1 The slow march toward monolithic hell
    1. The architecture of the FTGO application
    2. The benefits of the monolithic architecture
    3. Living in monolithic hell
  2. 1.2 Why this book is relevant to you
  3. 1.3 What you'll learn in this book
  4. 1.4 Microservice architecture to the rescue
    1. Scale cube and microservices
    2. Microservices as a form of modularity
    3. Each service has its own database
    4. The FTGO microservice architecture
    5. Comparing the microservice architecture and SOA
  5. 1.5 Benefits and drawbacks of the microservice architecture
    1. Benefits of the microservice architecture
    2. Drawbacks of the microservice architecture
  6. 1.6 The Microservice architecture pattern language
    1. Microservice architecture is not a silver bullet
    2. Patterns and pattern languages
    3. Overview of the Microservice architecture pattern language
  7. 1.7 Beyond microservices: Process and organization
    1. Software development and delivery organization
    2. Software development and delivery process
    3. The human side of adopting microservices

1.1 The slow march toward monolithic hell

Many successful applications start as a single, unified codebase. Over time, this codebase grows large and hard to manage. This section explains how that happens.

The architecture of the FTGO application

FTGO is an online food-delivery platform. It began as a monolithic application — one deployable unit containing all the business logic. The server-side code handles REST API requests, web pages, and integration with external services such as payment and messaging.

At its core, the FTGO monolith has a hexagonal architecture. Business logic sits in the center, surrounded by adapters that connect it to the outside world (databases, message brokers, REST clients).

Monolithic Architecture

Structure: All functionality lives inside a single deployable unit.
Example: One WAR file that contains order management, delivery, billing, and restaurant logic together.

The benefits of the monolithic architecture

When an application is small, the monolithic architecture has clear advantages:

Key point: Startups should begin with a monolithic architecture. It lets you move fast when the codebase is still small and the team is still learning the domain.

Living in monolithic hell

As the application grows over months and years, the codebase becomes very large. Development slows down. Teams step on each other's code. Deployments become risky. The application becomes difficult to understand, and fixing a bug in one area can break something in another. This state is called monolithic hell.

Problem — Monolithic Hell: The codebase is too large for any one person to understand. Building, testing, and deploying takes too long. Scaling is limited because all modules share the same resources, even if only one module needs more power.

Analogy: Think of a small restaurant where one chef cooks everything. It works when there are few orders. But if the restaurant gets hundreds of orders per hour, one chef cannot scale — you need a team of specialized cooks, each handling a different part of the menu.

1.2 Why this book is relevant to you

Whether you are a developer, architect, CTO, or VP of Engineering, monolithic hell is a problem you will likely face. This book provides a structured approach — a pattern language — to adopt the microservice architecture successfully.

Even if you are already working with microservices, the patterns help you solve recurring design problems in communication, data management, and deployment.

1.3 What you'll learn in this book

The book covers a broad set of topics needed to design, build, and operate microservices:

1.4 Microservice architecture to the rescue

The microservice architecture structures an application as a set of small, loosely coupled services. Each service is independently deployable and focuses on one business capability.

Core decision: Monolithic Architecture and Microservice Architecture are alternatives. Monolithic hell is the problem that motivates the move to microservices.

Scale cube and microservices

The Scale Cube is a three-dimensional model for scaling applications. Each axis represents a different strategy.

Axis Strategy What it does
X-axis Horizontal cloning Run multiple identical copies of the application behind a load balancer. Improves capacity but does not reduce complexity.
Y-axis Functional decomposition Split the application into separate services by function. This is what defines the microservice architecture.
Z-axis Data partitioning Each instance handles a subset of data (e.g., by customer ID). Complements X and Y axes.

Key point: Y-axis scaling (functional decomposition) is the axis that defines microservices. X-axis scaling helps with load but does not reduce code complexity. Z-axis scaling helps partition data across instances.

Microservices as a form of modularity

In a monolith, modularity is enforced by code conventions and packages — but nothing stops a developer from breaking module boundaries. In a microservice architecture, each service is a separate process with a well-defined API. You cannot accidentally call another service's internal code. This hard boundary enforces modularity much better than code conventions alone.

Each service has its own database

In a microservice architecture, each service owns its private database. No other service can access it directly. This is the Database per Service pattern.

Database per Service

What: Each service has its own private datastore.
Why: Prevents tight coupling through shared tables. Services can evolve their schemas independently.
Tradeoff: Querying and maintaining consistency across services becomes harder.

Because services cannot share a database, you need new patterns for consistency and querying:

Analogy: Imagine each department in a company keeps its own filing cabinet. No department can open another's cabinet. If you need information from two departments, you must ask each one separately and combine the answers yourself.

The FTGO microservice architecture

In the microservice version of FTGO, the monolith is split into services such as Order Service, Restaurant Service, Delivery Service, Kitchen Service, and Accounting Service. Each service owns its data and exposes a REST or messaging API.

An API Gateway sits in front of all services. It routes requests from external clients (web, mobile) to the correct internal service. A related pattern, Backend for Frontend (BFF), creates a separate gateway for each client type.

Comparing the microservice architecture and SOA

Service-Oriented Architecture (SOA) and the microservice architecture both organize applications into services. However, they differ in important ways.

Aspect SOA Microservices
Communication Heavy protocols (ESB, WS-*, SOAP) Lightweight protocols (REST, gRPC, messaging)
Data Shared global database is common Database per service
Service size Larger, enterprise-wide services Smaller services focused on one capability

1.5 Benefits and drawbacks of the microservice architecture

Benefits of the microservice architecture

Drawbacks of the microservice architecture

Warning — Distributed Monolith: If you decompose incorrectly, services stay tightly coupled. Every change still requires coordinating multiple teams and deploying multiple services together. This is called a distributed monolith, and it is worse than a regular monolith because you also pay the cost of network communication.

Aspect Monolithic Microservices
Simplicity Simple to develop, test, deploy early on More moving parts from the start
Scalability Scale entire app (wasteful) Scale individual services
Team autonomy Teams share the same codebase Teams own independent services
Data consistency Single database transaction (ACID) Requires Sagas for cross-service consistency
Deployment One unit to deploy Many units; needs automation
Fault isolation One bug can crash everything Failures contained per service

1.6 The Microservice architecture pattern language

A pattern language is an organized collection of patterns that solve related problems. The microservice architecture pattern language groups patterns into several categories that cover the full lifecycle of building microservices.

Microservice architecture is not a silver bullet

Microservices solve many problems, but they also introduce new ones. There is no single correct answer — every decision involves tradeoffs. The pattern language helps you navigate these tradeoffs by showing which patterns solve which problems, and what new issues each pattern may create.

Adoption timing dilemma: Startups should begin with a monolith because the overhead of microservices is too high for a small team. As the application and team grow, you migrate to microservices when the pain of the monolith outweighs the cost of migration.

Patterns and pattern languages

A pattern is a reusable solution to a problem that occurs in a specific context. Each pattern describes the problem, the forces at play, the solution, and the resulting consequences (both positive and negative). Patterns often have relationships: one pattern's consequence may be a problem solved by another pattern.

A pattern language groups these patterns into a structured collection. It shows alternatives, dependencies, and chains of patterns that work together.

Overview of the Microservice architecture pattern language

The pattern language is organized into the following groups. Each group addresses a different concern.

Decomposition patterns

These patterns decide how to split an application into services.

Decompose by Business Capability

What: Define services around what the business does (e.g., Order Management, Delivery).
Alternative: Decompose by Subdomain (DDD).

Decompose by Subdomain (DDD)

What: Use Domain-Driven Design to identify bounded contexts and create one service per subdomain.
Alternative: Decompose by Business Capability.

Communication patterns

Services need to talk to each other. Two main styles exist.

Messaging

What: Services communicate asynchronously by sending messages through a broker.
Alternative: Remote Procedure Invocation (REST / gRPC).

Remote Procedure Invocation (REST / gRPC)

What: A service calls another service's API directly and waits for a response.
Alternative: Messaging.

Reliable communication also requires handling failures:

Circuit Breaker

What: Stops calling a failing service after repeated failures. Prevents cascading failures across the system.
Why: Provides reliability for inter-service calls.

Service discovery patterns

Services need to find each other on the network. A Service Registry is a database of service instance locations.

Pattern How it works
Client-side Discovery The client queries the Service Registry and picks an instance to call.
Server-side Discovery The client sends a request to a router/load balancer, which queries the registry.
Self Registration Each service registers itself in the registry on startup.
3rd-party Registration An external component (e.g., deployment platform) registers services in the registry.

External API patterns

API Gateway / Backend for Frontend (BFF)

What: A single entry point that routes external API requests to internal services.
BFF variant: A separate gateway per client type (web, mobile, third-party).

Data management patterns

The Database per Service pattern creates challenges for consistency and querying.

Saga

What: A sequence of local transactions across services, with compensating transactions to undo work on failure.
Supports: Domain Event, Event Sourcing, Aggregate.

API Composition

What: A query that calls multiple services and combines the results in memory.
Alternative: CQRS.

CQRS (Command Query Responsibility Segregation)

What: Maintain a separate read-optimized view that is updated by subscribing to domain events from multiple services.
Alternative: API Composition.

To reliably publish domain events from a service's database, you can use:

Transactional Outbox

What: Store events in an outbox table as part of the database transaction, then publish them asynchronously.
Publishing: Polling Publisher (polls the outbox table) or Transaction Log Tailing (reads the database's transaction log).

Deployment patterns

Pattern Description
Single Service per Host Each service instance runs on its own host. Variants: Service-per-Container, Service-per-VM.
Multiple Services per Host Several service instances share one host. Simpler but less isolated.
Serverless Deployment Deploy service code as functions. The platform handles scaling and infrastructure.
Service Deployment Platform An automated platform (e.g., Kubernetes) that manages all deployment patterns.

Observability patterns

With many services running, you need visibility into the system. Observability patterns work together to give you that visibility.

Testing patterns

Testing microservices in isolation requires new approaches.

Cross-cutting and security patterns

Microservice Chassis

What: A framework or template that bundles common concerns so each service doesn't reinvent them.
Bundles: Externalized Configuration, Observability, Service Discovery.

Access Token (JWT)

What: The API Gateway authenticates the user and passes a signed token (e.g., JWT) to internal services.
Why: Services can verify the user's identity and permissions without contacting the auth service again.

1.7 Beyond microservices: Process and organization

Technology alone is not enough. You also need the right team structure and development process to succeed with microservices.

Software development and delivery organization

The microservice architecture enables small, autonomous teams — often called two-pizza teams (small enough to be fed by two pizzas). Each team owns one or more services end-to-end: development, testing, deployment, and operations.

Conway's Law: Organizations tend to produce systems whose structure mirrors their communication structure. If your teams are organized by technology layer (frontend team, backend team, DBA team), your services will likely be coupled in the same way.

Reverse Conway Maneuver: Instead of letting your organization shape the architecture, reorganize your teams to mirror the service architecture you want. Structure teams around business capabilities so that each team can own its service independently.

Software development and delivery process

Autonomous two-pizza teams enable Continuous Delivery and Deployment (DevOps). Each team can push changes to production frequently and safely because they only deploy their own service, not the entire application.

Key chain: Microservice Architecture enables autonomous Two-Pizza Teams, which in turn enable Continuous Delivery/Deployment.

The human side of adopting microservices

Moving from a monolith to microservices is not just a technical change — it is also an emotional transition for people. Roles change, responsibilities shift, and familiar workflows disappear.

Bridges' Transition Model

What: A framework for managing the human emotions during organizational change.
Phases: Ending (letting go of the old), Neutral Zone (uncertainty), New Beginning (embracing the new way).
Why: Ignoring the emotional side of adoption leads to resistance and failure, even if the technology is right.

Concept relationship map

The concepts in this chapter connect to each other in chains. Understanding these relationships helps you see how patterns depend on one another.

Core chain: Monolithic Hell (problem) → motivates Microservice Architecture (solution) → requires Database per Service → creates need for Saga (consistency), API Composition / CQRS (querying).

Event chain: Domain Event + Event Sourcing + Aggregate support Saga execution. Transactional Outbox ensures reliable event publishing via Polling Publisher or Transaction Log Tailing.

Organization chain: Microservice Architecture → enables Two-Pizza Teams → enables Continuous Delivery/Deployment. Conway's Law + Reverse Conway Maneuver: your org structure should mirror your service architecture.

Key Takeaways — Chapter 1