Aggregate
A cluster of domain objects treated as a single unit for data changes, with a root entity that controls all access and enforces invariants.
Also known as: Aggregate Root, DDD Aggregate, Aggregate Pattern
Category: Software Development
Tags: domain-driven-design, software-design, patterns, architecture, modeling
Explanation
An Aggregate is a tactical pattern in Domain-Driven Design (DDD) that defines a cluster of closely related domain objects—entities and value objects—that are treated as a single unit for the purpose of data changes. Every aggregate has a root entity (the Aggregate Root) that serves as the sole entry point for external access and is responsible for enforcing all business rules (invariants) within the cluster.
**Core rules:**
- **Single root**: Each aggregate has exactly one root entity with a globally unique identity
- **External references**: Outside objects may only hold references to the aggregate root, never to internal objects
- **Transactional boundary**: All changes within an aggregate must be committed atomically in a single transaction
- **Invariant enforcement**: The aggregate root ensures that all business rules are satisfied before and after any operation
- **Internal object access**: Internal entities and value objects are accessed only through the root
**Why aggregates matter:**
- **Consistency boundaries**: They define where strong consistency is required, simplifying reasoning about correctness
- **Concurrency control**: By limiting the scope of transactions to a single aggregate, you reduce contention and improve scalability
- **Encapsulation**: Business logic is concentrated in the aggregate, preventing domain rules from leaking across the system
- **Design guidance**: They force you to think carefully about which objects truly belong together
**Design guidelines:**
- **Keep them small**: Large aggregates create performance and concurrency problems. Prefer small aggregates with just the root entity and essential value objects
- **Reference by identity**: Aggregates should reference other aggregates by ID, not by direct object reference
- **One aggregate per transaction**: Modify only one aggregate per transaction. Use domain events and eventual consistency for cross-aggregate coordination
- **Design around invariants**: The aggregate boundary should enclose exactly the objects needed to enforce a business rule
**Common examples:**
- **Order aggregate**: Order (root) contains OrderLines (internal entities) and ShippingAddress (value object). Adding an item goes through the Order root, which enforces rules like minimum order value
- **Account aggregate**: BankAccount (root) contains Transaction history. All deposits and withdrawals go through the account, which enforces balance invariants
Related Concepts
← Back to all concepts