- Preface
- Who Should Read This Book
- Why I Wrote This Book
- What’s Changed Since the First Edition?
- Navigating This Book
- Part I, Foundation
- Part II, Implementation
- Part III, People
- Conventions Used in This Book
- O’Reilly Online Learning
- How to Contact Us
- Acknowledgments
- I. Foundation
- 1. What Are Microservices?
- Microservices at a Glance
- Key Concepts of Microservices
- Independent Deployability
- Modeled Around a Business Domain
- Owning Their Own State
- Size
- Flexibility
- Alignment of Architecture and Organization
- The Monolith
- The Single-Process Monolith
- The Modular Monolith
- The Distributed Monolith
- Monoliths and Delivery Contention
- Advantages of Monoliths
- Enabling Technology
- Log Aggregation and Distributed Tracing
- Containers and Kubernetes
- Streaming
- Public Cloud and Serverless
- Advantages of Microservices
- Technology Heterogeneity
- Robustness
- Scaling
- Ease of Deployment
- Organizational Alignment
- Composability
- Microservice Pain Points
- Developer Experience
- Technology Overload
- Cost
- Reporting
- Monitoring and Troubleshooting
- Security
- Testing
- Latency
- Data Consistency
- Should I Use Microservices?
- Whom They Might Not Work For
- Where They Work Well
- Summary
- 2. How to Model Microservices
- Introducing MusicCorp
- What Makes a Good Microservice Boundary?
- Information Hiding
- Cohesion
- Coupling
- The Interplay of Coupling and Cohesion
- Types of Coupling
- Domain Coupling
- Pass-Through Coupling
- Common Coupling
- Content Coupling
- Just Enough Domain-Driven Design
- Ubiquitous Language
- Aggregate
- Bounded Context
- Mapping Aggregates and Bounded Contexts to Microservices
- Event Storming
- The Case for Domain-Driven Design for Microservices
- Alternatives to Business Domain Boundaries
- Volatility
- Data
- Technology
- Organizational
- Mixing Models and Exceptions
- Summary
- 3. Splitting the Monolith
- Have a Goal
- Incremental Migration
- The Monolith Is Rarely the Enemy
- The Dangers of Premature Decomposition
- What to Split First?
- Decomposition by Layer
- Code First
- Data First
- Useful Decompositional Patterns
- Strangler Fig Pattern
- Parallel Run
- Feature Toggle
- Data Decomposition Concerns
- Performance
- Data Integrity
- Transactions
- Tooling
- Reporting Database
- Summary
- 4. Microservice Communication Styles
- From In-Process to Inter-Process
- Performance
- Changing Interfaces
- Error Handling
- Technology for Inter-Process Communication:
So Many Choices
- Styles of Microservice Communication
- Mix and Match
- Pattern: Synchronous Blocking
- Advantages
- Disadvantages
- Where to Use It
- Pattern: Asynchronous Nonblocking
- Advantages
- Disadvantages
- Where to Use It
- Pattern: Communication Through Common Data
- Implementation
- Advantages
- Disadvantages
- Where to Use It
- Pattern: Request-Response Communication
- Implementation: Synchronous Versus Asynchronous
- Where to Use It
- Pattern: Event-Driven Communication
- Implementation
- What’s in an Event?
- Where to Use It
- Proceed with Caution
- Summary
- II. Implementation
- 5. Implementing Microservice Communication
- Looking for the Ideal Technology
- Make Backward Compatibility Easy
- Make Your Interface Explicit
- Keep Your APIs Technology Agnostic
- Make Your Service Simple for Consumers
- Hide Internal Implementation Detail
- Technology Choices
- Remote Procedure Calls
- REST
- GraphQL
- Message Brokers
- Serialization Formats
- Textual Formats
- Binary Formats
- Schemas
- Structural Versus Semantic Contract Breakages
- Should You Use Schemas?
- Handling Change Between Microservices
- Avoiding Breaking Changes
- Expansion Changes
- Tolerant Reader
- Right Technology
- Explicit Interface
- Catch Accidental Breaking Changes Early
- Managing Breaking Changes
- Lockstep Deployment
- Coexist Incompatible Microservice Versions
- Emulate the Old Interface
- Which Approach Do I Prefer?
- The Social Contract
- Tracking Usage
- Extreme Measures
- DRY and the Perils of Code Reuse in a Microservice World
- Sharing Code via Libraries
- Service Discovery
- Domain Name System (DNS)
- Dynamic Service Registries
- Don’t Forget the Humans!
- Service Meshes and API Gateways
- API Gateways
- Service Meshes
- What About Other Protocols?
- Documenting Services
- Explicit Schemas
- The Self-Describing System
- Summary
- 6. Workflow
- Database Transactions
- ACID Transactions
- Still ACID, but Lacking Atomicity?
- Distributed Transactions—Two-Phase Commits
- Distributed Transactions—Just Say No
- Sagas
- Saga Failure Modes
- Implementing Sagas
- Sagas Versus Distributed Transactions
- Summary
- 7. Build
- A Brief Introduction to Continuous Integration
- Are You Really Doing CI?
- Branching Models
- Build Pipelines and Continuous Delivery
- Tooling
- Trade-Offs and Environments
- Artifact Creation
- Mapping Source Code and Builds to Microservices
- One Giant Repo, One Giant Build
- Pattern: One Repository per Microservice (aka Multirepo)
- Pattern: Monorepo
- Which Approach Would I Use?
- Summary
- 8. Deployment
- From Logical to Physical
- Multiple Instances
- The Database
- Environments
- Principles of Microservice Deployment
- Isolated Execution
- Focus on Automation
- Infrastructure as Code (IAC)
- Zero-Downtime Deployment
- Desired State Management
- Deployment Options
- Physical Machines
- Virtual Machines
- Containers
- Application Containers
- Platform as a Service (PaaS)
- Function as a Service (FaaS)
- Which Deployment Option Is Right for You?
- Kubernetes and Container Orchestration
- The Case for Container Orchestration
- A Simplified View of Kubernetes Concepts
- Multitenancy and Federation
- The Cloud Native Computing Federation
- Platforms and Portability
- Helm, Operators, and CRDs, Oh My!
- And Knative
- The Future
- Should You Use It?
- Progressive Delivery
- Separating Deployment from Release
- On to Progressive Delivery
- Feature Toggles
- Canary Release
- Parallel Run
- Summary
- 9. Testing
- Types of Tests
- Test Scope
- Unit Tests
- Service Tests
- End-to-End Tests
- Trade-Offs
- Implementing Service Tests
- Mocking or Stubbing
- A Smarter Stub Service
- Implementing (Those Tricky) End-to-End Tests
- Flaky and Brittle Tests
- Who Writes These End-to-End Tests?
- How Long Should End-to-End Tests Run?
- The Great Pile-Up
- The Metaversion
- Lack of Independent Testability
- Should You Avoid End-to-End Tests?
- Contract Tests and Consumer-Driven Contracts (CDCs)
- The Final Word
- Developer Experience
- From Preproduction to In-Production Testing
- Types of In-Production Testing
- Making Testing in Production Safe
- Mean Time to Repair over Mean Time Between Failures?
- Cross-Functional Testing
- Performance Tests
- Robustness Tests
- Summary
- 10. From Monitoring to Observability
- Disruption, Panic, and Confusion
- Single Microservice, Single Server
- Single Microservice, Multiple Servers
- Multiple Services, Multiple Servers
- Observability Versus Monitoring
- The Pillars of Observability? Not So Fast
- Building Blocks for Observability
- Log Aggregation
- Metrics Aggregation
- Distributed Tracing
- Are We Doing OK?
- Alerting
- Semantic Monitoring
- Testing in Production
- Standardization
- Selecting Tools
- Democratic
- Easy to Integrate
- Provide Context
- Real-Time
- Suitable for Your Scale
- The Expert in the Machine
- Getting Started
- Summary
- 11. Security
- Core Principles
- Principle of Least Privilege
- Defense in Depth
- Automation
- Build Security into the Delivery Process
- The Five Functions of Cybersecurity
- Identify
- Protect
- Detect
- Respond
- Recover
- Foundations of Application Security
- Credentials
- Patching
- Backups
- Rebuild
- Implicit Trust Versus Zero Trust
- Implicit Trust
- Zero Trust
- It’s a Spectrum
- Securing Data
- Data in Transit
- Data at Rest
- Authentication and Authorization
- Service-to-Service Authentication
- Human Authentication
- Common Single Sign-On Implementations
- Single Sign-On Gateway
- Fine-Grained Authorization
- The Confused Deputy Problem
- Centralized, Upstream Authorization
- Decentralizing Authorization
- JSON Web Tokens
- Summary
- 12. Resiliency
- What Is Resiliency?
- Robustness
- Rebound
- Graceful Extensibility
- Sustained Adaptability
- And Microservice Architecture
- Failure Is Everywhere
- How Much Is Too Much?
- Degrading Functionality
- Stability Patterns
- Time-Outs
- Retries
- Bulkheads
- Circuit Breakers
- Isolation
- Redundancy
- Middleware
- Idempotency
- Spreading Your Risk
- CAP Theorem
- Sacrificing Consistency
- Sacrificing Availability
- Sacrificing Partition Tolerance?
- AP or CP?
- It’s Not All or Nothing
- And the Real World
- Chaos Engineering
- Game Days
- Production Experiments
- From Robustness to Beyond
- Blame
- Summary
- 13. Scaling
- The Four Axes of Scaling
- Vertical Scaling
- Horizontal Duplication
- Data Partitioning
- Functional Decomposition
- Combining Models
- Start Small
- Caching
- For Performance
- For Scale
- For Robustness
- Where to Cache
- Invalidation
- The Golden Rule of Caching
- Freshness Versus Optimization
- Cache Poisoning: A Cautionary Tale
- Autoscaling
- Starting Again
- Summary
- III. People
- 14. User Interfaces
- Toward Digital
- Ownership Models
- Drivers for Dedicated Frontend Teams
- Toward Stream-Aligned Teams
- Sharing Specialists
- Ensuring Consistency
- Working Through Technical Challenges
- Pattern: Monolithic Frontend
- When to Use It
- Pattern: Micro Frontends
- Implementation
- When to Use It
- Pattern: Page-Based Decomposition
- Where to Use It
- Pattern: Widget-Based Decomposition
- Implementation
- When to Use It
- Constraints
- Pattern: Central Aggregating Gateway
- Ownership
- Different Types of User Interfaces
- Multiple Concerns
- When to Use It
- Pattern: Backend for Frontend (BFF)
- How Many BFFs?
- Reuse and BFFs
- BFFs for Desktop Web and Beyond
- When to Use
- GraphQL
- A Hybrid Approach
- Summary
- 15. Organizational Structures
- Loosely Coupled Organizations
- Conway’s Law
- Evidence
- Team Size
- Understanding Conway’s Law
- Small Teams, Large Organization
- On Autonomy
- Strong Versus Collective Ownership
- Strong Ownership
- Collective Ownership
- At a Team Level Versus an Organizational Level
- Balancing Models
- Enabling Teams
- Communities of Practice
- The Platform
- Shared Microservices
- Too Hard to Split
- Cross-Cutting Changes
- Delivery Bottlenecks
- Internal Open Source
- Role of the Core Committers
- Maturity
- Tooling
- Pluggable, Modular Microservices
- Change Reviews
- The Orphaned Service
- Case Study: realestate.com.au
- Geographical Distribution
- Conway’s Law in Reverse
- People
- Summary
- 16. The Evolutionary Architect
- What’s in a Name?
- What Is Software Architecture?
- Making Change Possible
- An Evolutionary Vision for the Architect
- Defining System Boundaries
- A Social Construct
- Habitability
- A Principled Approach
- Strategic Goals
- Principles
- Practices
- Combining Principles and Practices
- A Real-World Example
- Guiding an Evolutionary Architecture
- Architecture in a Stream-Aligned Organization
- Building a Team
- The Required Standard
- Monitoring
- Interfaces
- Architectural Safety
- Governance and the Paved Road
- Exemplars
- Tailored Microservice Template
- The Paved Road at Scale
- Technical Debt
- Exception Handling
- Summary
- Afterword: Bringing It All Together
- What Are Microservices?
- Moving to Microservices
- Communication Styles
- Workflow
- Build
- Deployment
- Testing
- Monitoring and Observability
- Security
- Resiliency
- Scaling
- User Interfaces
- Organization
- Architecture
- Further Reading
- Looking Forward
- Final Words
- Bibliography
- Glossary
- Index