Skip to content

Add Rules and Behavior

DDD CQRS ES

Protean provides several mechanisms to define validation rules, enforce business invariants, mutate aggregate state safely, and communicate state changes through domain events. This section covers each of these capabilities.

For the conceptual foundation, see Building Blocks.

What's in This Section

Validations

Validations ensure that data meets basic requirements before it can be processed. In Protean, validations can be applied at multiple levels:

  • Field-level restrictions - Define type constraints, required fields, uniqueness
  • Built-in validators - Leverage pre-defined validators for common validation patterns
  • Custom validators - Create domain-specific validation logic

Learn more about validations →

Invariants

Invariants are business rules that must always hold true within your domain model. They preserve the consistency and integrity of your domain objects:

  • Always valid - Invariants are conditions that must hold true at all times
  • Domain-driven - Invariants stem from business rules and policies
  • Immediate validation - Triggered automatically during initialization and state changes

Learn more about invariants →

Status Transitions

Most aggregates are state machines. The Status field makes lifecycle rules explicit and automatically enforced:

  • Declarative transitions - Define allowed state-to-state moves in the field declaration
  • Automatic enforcement - Illegal transitions raise ValidationError
  • Terminal states - States with no outgoing transitions are implicit
  • Programmatic checking - can_transition_to() checks without raising

Learn more about status transitions →

Aggregate Mutation

Aggregates encapsulate the state and behavior of your domain. Mutating their state is how you implement business operations:

  • State change methods - Well-defined methods for modifying aggregate state
  • Invariant enforcement - All state changes are validated against defined invariants
  • Explicit behavior - Business operations are expressed as meaningful methods

Learn more about aggregate mutation →

Raising Events

Domain events record significant state changes and enable communication between different parts of your system:

  • Delta events - Generated when aggregates mutate to record state changes
  • Entity events - Any entity in an aggregate cluster can raise events
  • Event dispatching - Events are automatically dispatched or can be manually published

Learn more about raising events →

Message Tracing & Enrichment

Protean automatically tracks causal chains across commands and events, and lets you attach custom metadata to every message:

  • Correlation & causation IDs - Automatically propagated through command → event chains
  • Causation chain API - Walk up to the root command, down to all effects, or build a full causation tree programmatically
  • Message enrichment hooks - Register callables that add custom metadata (user context, tenant ID, audit data) to every event and command
  • Extensions metadata - A user-space metadata.extensions dict persisted in the event store

Learn more about message tracing →  |  Learn more about message enrichment →

Domain Services

Domain services encapsulate business logic that doesn't naturally fit within any single aggregate:

  • Stateless operations - Pure functions that operate on multiple aggregates
  • Complex workflows - Coordinate operations that span multiple aggregates
  • Business rules - Enforce constraints that involve multiple objects

Learn more about domain services →

Error Handling

Raise, propagate, and handle domain exceptions -- from aggregate invariants through command handlers to HTTP responses.

Learn more about error handling →

See also

For design guidance and trade-offs, see the Patterns & Recipes section -- particularly Encapsulate State Changes, Validation Layering, and Thin Handlers, Rich Domain.