--- name: system-decomposition description: "Knowledge contract for splitting systems into services or modules, defining boundaries, data ownership, and dependency direction. Referenced by design-architecture when designing service boundaries." --- This is a knowledge contract, not a workflow skill. It is referenced by `design-architecture` when the architect is designing service boundaries and system decomposition. ## Core Principles - Each service or module must have a single, well-defined responsibility - Data ownership must be clear: each piece of data belongs to exactly one service - Dependencies must flow in one direction; cyclic dependencies are forbidden - Boundaries must be drawn around domain responsibilities, not technical layers ## Decomposition Decisions ### Modular Monolith vs Microservices Choose modular monolith when: - Team size is small (fewer than 5-8 engineers per service boundary) - Domain boundaries are still evolving - Deployment simplicity is a priority - Inter-service communication overhead would exceed in-process call overhead - The PRD does not require independent scaling of individual services Choose microservices when: - Individual services have different scaling requirements stated in the PRD - Team ownership aligns with service boundaries - Domain boundaries are stable and well-understood - Independent deployment of services is required - The PRD explicitly requires isolation for reliability or security Do not choose microservices solely because they are fashionable or because the team might need them someday. YAGNI applies. ### Domain Boundaries Identify domain boundaries by looking for: - Entities that change together - Business rules that are cohesive - Data that is accessed together - User workflows that span a consistent context A good boundary: - Has high internal cohesion (related logic stays together) - Has low external coupling (minimal cross-boundary calls) - Can be understood independently - Can be deployed independently if needed A bad boundary: - Requires frequent cross-boundary calls to complete a workflow - Splits closely related entities across services - Exists because of technical layering rather than domain logic - Requires distributed transactions to maintain consistency ### Coupling vs Cohesion Favor high cohesion within a boundary: - Related business rules live together - Related data is owned by the same service - Related workflows are handled end-to-end Minimize coupling between boundaries: - Communicate via well-defined contracts (APIs, events) - Avoid sharing database tables between services - Avoid synchronous call chains longer than 2 services deep when possible - Prefer eventual consistency for cross-boundary state updates ### State Ownership Each piece of state must have exactly one owner: - The owning service is the single source of truth - Other services access that state via the owner's API or events - No service reads directly from another service's database - If data is needed in multiple places, replicate via events with a clear source of truth ## Communication Patterns ### Synchronous - Use when the caller needs an immediate response - Use for queries and command validation - Avoid for long-running operations - Consider timeouts and circuit breakers ### Asynchronous - Use when the caller does not need an immediate response - Use for events, notifications, and eventual consistency - Use when decoupling producer and consumer is valuable - Consider ordering, retry, and DLQ requirements ### Event-Driven - Use when multiple consumers need to react to state changes - Use for cross-boundary consistency (eventual) - Define event schemas explicitly - Consider event versioning and backward compatibility ## Anti-Patterns - Distributed monolith: microservices that must be deployed together - Shared database: multiple services reading/writing the same tables - Synchronous chain: 3+ services in a synchronous call chain - Leaky domain: business rules that require data from other services directly instead of via APIs or events - Premature decomposition: splitting before boundaries are understood