- [[#Core Question|Core Question]] - [[#The Three Pillars|The Three Pillars]] - [[#The Three Pillars#1. Information Hiding|1. Information Hiding]] - [[#The Three Pillars#2. Cohesion|2. Cohesion]] - [[#The Three Pillars#3. Coupling|3. Coupling]] - [[#Types of Coupling (Loose → Tight)|Types of Coupling (Loose → Tight)]] - [[#Types of Coupling (Loose → Tight)#Domain Coupling (Acceptable)|Domain Coupling (Acceptable)]] - [[#Types of Coupling (Loose → Tight)#Temporal Coupling (Be Aware)|Temporal Coupling (Be Aware)]] - [[#Types of Coupling (Loose → Tight)#Pass-Through Coupling (Problematic)|Pass-Through Coupling (Problematic)]] - [[#Types of Coupling (Loose → Tight)#Common Coupling (Often Problematic)|Common Coupling (Often Problematic)]] - [[#Types of Coupling (Loose → Tight)#Content Coupling (Avoid!)|Content Coupling (Avoid!)]] - [[#Domain-Driven Design (DDD) for Microservices|Domain-Driven Design (DDD) for Microservices]] - [[#Domain-Driven Design (DDD) for Microservices#Ubiquitous Language|Ubiquitous Language]] - [[#Domain-Driven Design (DDD) for Microservices#Aggregates|Aggregates]] - [[#Domain-Driven Design (DDD) for Microservices#Bounded Contexts|Bounded Contexts]] - [[#Domain-Driven Design (DDD) for Microservices#Mapping to Microservices|Mapping to Microservices]] - [[#Domain-Driven Design (DDD) for Microservices#Event Storming|Event Storming]] - [[#Why DDD Works for Microservices|Why DDD Works for Microservices]] - [[#Alternatives to Business Domain Boundaries|Alternatives to Business Domain Boundaries]] - [[#Alternatives to Business Domain Boundaries#Volatility|Volatility]] - [[#Alternatives to Business Domain Boundaries#Data|Data]] - [[#Alternatives to Business Domain Boundaries#Technology|Technology]] - [[#Alternatives to Business Domain Boundaries#Organizational|Organizational]] - [[#Mixing Models|Mixing Models]] - [[#Key Warnings|Key Warnings]] - [[#Discussion Questions|Discussion Questions]] ## Core Question **How do we draw boundaries around microservices?** The goal: microservices that can be changed and deployed independently. This chapter explores the foundational concepts that help us get boundaries right. --- ## The Three Pillars ### 1. Information Hiding From David Parnas's work on modular software. Hide as many details as possible behind a module boundary. **Benefits of proper information hiding:** | Benefit | Description | |---------|-------------| | **Improved development time** | Modules developed independently; more parallel work | | **Comprehensibility** | Each module understood in isolation | | **Flexibility** | Change one module without changing others | > "The connections between modules are the assumptions which the modules make about each other." Fewer assumptions = looser coupling = easier changes. ### 2. Cohesion > "The code that changes together, stays together." - Related behavior should sit together - Unrelated behavior should sit elsewhere - If functionality is spread across the system, cohesion is **weak** - We want **strong cohesion** within microservice boundaries ### 3. Coupling When services are loosely coupled, a change to one should not require a change to another. **Constantine's Law:** > "A structure is stable if cohesion is strong and coupling is low." Coupling and cohesion are two sides of the same coin: - **Cohesion** = relationship between things *inside* a boundary - **Coupling** = relationship between things *across* boundaries --- ## Types of Coupling (Loose → Tight) ### Domain Coupling (Acceptable) One microservice uses functionality from another. ``` Order Processor → Warehouse (reserve stock) Order Processor → Payment (take payment) ``` - Largely unavoidable in microservice architectures - Still want to minimize it - Watch out for services that call *many* downstream services (might be doing too much) ### Temporal Coupling (Be Aware) Both services must be available *at the same time* for an operation to complete. - Synchronous HTTP calls are temporally coupled - Not always bad, just something to watch - Can avoid with async communication (message brokers) ### Pass-Through Coupling (Problematic) One microservice passes data through purely because a *downstream* service needs it. **Example:** ``` Order Processor → Warehouse → Shipping (passes Shipping Manifest through) ``` **Problem:** Changes downstream ripple upstream. **Solutions:** 1. Have caller talk directly to downstream service 2. Have intermediary construct the required data locally (hide the downstream requirement) 3. Treat passed data as an opaque blob (intermediary doesn't parse it) ### Common Coupling (Often Problematic) Multiple microservices use a shared set of data (shared database, filesystem, etc.). **Example:** Multiple services reading from a shared "Countries" reference table. - Less problematic if data is read-only and rarely changes - Very problematic if multiple services read *and write* to same data - Creates resource contention issues - Makes it hard to reason about valid state transitions **Solution:** Single microservice owns the data; others send *requests* to change it. ### Content Coupling (Avoid!) An upstream service reaches into the *internals* of a downstream service and changes its state directly. **Example:** Warehouse service directly updating Order service's database table, bypassing Order service's API. Also called **pathological coupling**. > "If you allow an outside party to directly access your database, the database in effect becomes part of that external contract." Problems: - Can't reason about what can/cannot be changed - Information hiding is gone - Duplication of business logic - Inconsistent state transitions --- ## Domain-Driven Design (DDD) for Microservices ### Ubiquitous Language Use the same terms in code as users use in the business domain. **Anti-example:** A bank using a generic "arrangement" data model instead of domain terms like "haircuts" and "end-of-day sweeps." Benefits: - Easier communication between tech and business - Developers understand the domain - Shared vocabulary for APIs and events ### Aggregates A collection of objects managed as a single entity, representing a real-world concept. **Examples:** Order, Invoice, Stock Item, Customer Key properties: - Has state, identity, and a life cycle - Managed as a state machine - One aggregate = one microservice owner (though one microservice can own multiple aggregates) - Outside requests can be *rejected* if invalid **Relationships between aggregates:** - Within same microservice: foreign keys, etc. - Across microservices: store explicit references (URIs, pseudo-URIs like `soundcloud:tracks:123`) ### Bounded Contexts A larger organizational boundary with explicit responsibilities. **Example:** Warehouse vs. Finance department at MusicCorp - Contains one or more aggregates - Some aggregates exposed externally; others hidden - Internal details (forklift trucks) hidden from outside world - Shared concepts (Customer) may have different names/meanings in different contexts **Hidden models:** Stock Item inside Warehouse has shelf locations; the *shared* representation only exposes total count. **Shared models:** "Customer" in Finance vs. "Recipient" in Warehouse—same person, different roles and data. ### Mapping to Microservices | DDD Concept | Microservice Mapping | |-------------|---------------------| | **Bounded Context** | Good starting point for service boundary | | **Aggregate** | Don't split across services; one service can own many | **Start coarse:** Target entire bounded contexts first, then subdivide later. **Nested contexts:** Bounded contexts can contain smaller bounded contexts (Warehouse → Inventory + Shipping). You can hide this decomposition from external consumers. ### Event Storming Collaborative brainstorming to surface a domain model. **Process:** 1. Identify **domain events** (things that happen): "Order Placed", "Payment Received" 2. Identify **commands** (human decisions that cause events) 3. Identify **aggregates** (nouns from events become candidates) 4. Group aggregates into **bounded contexts** Key: Get technical and non-technical stakeholders in the same room. --- ## Why DDD Works for Microservices 1. **Bounded contexts are inherently about information hiding** 2. **Ubiquitous language** gives shared vocabulary for APIs 3. **Business domain changes** are isolated to single boundaries 4. **Aligns tech architecture with organizational structure** --- ## Alternatives to Business Domain Boundaries ### Volatility Extract frequently-changing functionality into its own service. - Useful when speed of delivery is the main driver - Not helpful if scaling is the main concern - Avoid "bimodal IT" thinking (Mode 1 slow / Mode 2 fast) ### Data Nature of data can drive decomposition. **Example:** PaymentCo segregating PCI-compliant "red zone" (credit card data) from "green zone" (everything else) to limit audit scope. ### Technology Different runtime requirements may force boundaries. - Need Rust for performance? That's a forcing function. - But be careful: pure technology layering (3-tier) is often suboptimal ### Organizational Conway's Law: org structure drives architecture. - Don't define service boundaries that cut across multiple teams - Consider changing org structure to support desired architecture - Shared ownership of microservices is "a fraught affair" **Anti-pattern:** "Onion architecture"—splitting along technical layers (frontend team / backend team) rather than vertical business slices. "Lots of layers and made me cry when we had to cut through it." --- ## Mixing Models Don't be dogmatic. Multiple factors often come into play: - Domain-oriented boundaries as starting point - But technology constraints may force further splits - Volatility matters if speed is the goal - Data sensitivity may require segregation - Organizational realities must be considered > "If someone says 'The only way to do this is X!' they are likely just selling you more dogma." --- ## Key Warnings | Warning | Explanation | |---------|-------------| | CRUD wrappers | A microservice that's just a thin wrapper around database CRUD = weak cohesion, tight coupling | | Chatty communication | Too many calls between services = potential tight coupling | | Shared databases | Avoid unless absolutely necessary | | Horizontal slicing | Technical layers as boundaries usually worse than vertical business slices | --- ## Discussion Questions 1. What's the relationship between coupling and cohesion? How are they "two sides of the same coin"? 2. Why is domain coupling considered acceptable while content coupling is "pathological"? 3. What's the difference between common coupling and content coupling? 4. How does the concept of an "aggregate" help you think about microservice boundaries? 5. What's the difference between a bounded context and an aggregate? 6. Why might a "Customer" be called "Recipient" in a different bounded context? 7. How does event storming help surface domain models? 8. When would volatility-based decomposition be the right choice? 9. What was wrong with the "onion architecture" example (California/Brazil teams)? 10. Why does the author warn against microservices that are "just CRUD wrappers"? 11. How would you handle the PaymentCo example—segregating PCI-compliant data into a "red zone"? 12. The chapter says requests to aggregates should be "things that can be rejected." Why is this important?