opencode-workflow/skills/system-decomposition/SKILL.md

4.0 KiB

name description
system-decomposition 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