Entity
Overview
An entity is an object defined by its identity, not by its attributes. Two orders with exactly the same data are different orders if they have different identifiers.
The distinction between an entity and a value object is the first tactical modelling decision, and it comes from the domain — not from technical convenience.
Problem
Not everything you persist is an entity. Treating everything as an entity produces three problems.
Identity where there is none. An address with its own identifier, referenced by other objects, raises the question "is this the same address?" — which has no useful answer in the domain.
Improper mutability. Entities change over time; value objects do not. Making mutable something that should be replaced opens a class of sharing defects.
Wrong comparison. Two entities compare by identity; two value objects, by attributes. Getting that wrong produces subtly incorrect behaviour in collections and caches.
The test that settles it: if two objects with the same attributes can be different to the business, it is an entity.
Core Concepts
The identity belongs to the domain
The entity has identity because the domain distinguishes it over time. A customer remains the same customer after changing address, name and phone number.
That means the identity has to be stable: it never changes while the entity exists.
Choosing the identifier is architectural
One of the system's highest-cost-of-reversal decisions, and frequently taken by whoever writes the first migration. See what is architecture.
| Strategy | Advantage | Cost |
|---|---|---|
| Database sequence | Compact, ordered, efficient index | Only exists after persisting; exposes volume; hard in distributed systems |
| UUID generated in the application | Exists before persisting; no coordination | Larger; worse index locality |
| Time-ordered UUID | No coordination and good locality | Less widely supported |
| Natural domain key | Meaning of its own | Changes when reality changes |
The fourth row deserves attention: natural identifiers — a tax number, a contract number, a product code — look ideal and fail when the business changes the rule. A product code that "never changes" changes at the first catalogue merger.
The practical recommendation: use an artificial identifier as the identity, and treat the natural one as a unique attribute. That separates identity from the business rule that may change.
Generate the identity early
An identifier generated by the database only exists after persistence. That prevents building an object graph in memory before saving, and complicates tests.
Generating in the application — a UUID or equivalent — solves it: the identity exists before the write, the graph is assembled in memory and the test needs no database.
The entity has behaviour
An entity with only fields and accessors is the anemic model. The rules that protect its invariant belong to it. See encapsulation.
When to Use
- The domain distinguishes the object over time, even as attributes change.
- There is a history or lifecycle associated with it.
- Other objects need to reference it stably.
- There are rules that depend on "this specific object".
When Not to Use
When the object is defined by its values. Money, address, period, coordinate. See value object.
When the identity has no meaning in the domain. If nobody asks "which one?", it probably is not an entity.
When the domain does not distinguish two identical occurrences. It is the same axis as the condition above, inverted: immutability decides nothing here — two payments of the same amount, on the same day, by the same person are different payments, and neither of them changes after being created. An immutable entity exists; what does not exist is an entity with no identity.
In supporting or generic subdomains. The ceremony of tactical modelling does not pay off outside the core.
Alternatives
- Value object — when the attributes define it.
- A transparent record — for data with no invariant and no identity.
- A plain identifier — when it is enough to reference without carrying the object.
Trade-offs
| Entity | Value object |
|---|---|
| Stable identity over time | Defined by attributes |
| Mutable | Immutable |
| Comparison by identity | By value |
| Lifecycle and history | Replaced, not altered |
| Persisted with an identifier | Can be embedded |
| Referenced by identifier | Copied where it is used |
Failure Modes
Unstable identity. The identifier changes, and every reference breaks.
A natural identifier that changes. A corrected tax number, a renumbered product code.
Anemic entity. No behaviour; the invariant gets scattered.
Comparison by attributes. Two instances of the same entity treated as different in a collection.
Identity exposed in a public contract. A sequential identifier in an API reveals business volume and allows enumeration.
Common Mistakes
Treating everything as an entity. The most common mistake and the one that most complicates the model.
Using a natural identifier as the identity.
Depending on the database to generate the identity.
Leaving the entity anemic.
Exposing the internal identifier in external contracts. Consider a separate public identifier.
Real-World Example
An equipment rental system modelled Equipment as an entity — with an identifier — and
Contract too.
The delivery Address was also an entity, with its own table and identifier.
The problem appeared on correcting an address: altering the record changed the address on every historical contract that referenced it. A two-year-old contract came to show the customer's current address, not the original delivery one.
That is an auditing defect in a domain with contractual implications.
Remodelling made Address a value object, embedded in each contract. Correcting the
customer's address stopped affecting past contracts, because each one carries the address
that applied at the time.
What revealed the mistake was the test question: are two addresses with the same data the same address? For the domain, yes — and that means it is not an entity.
The counterexample in the same system: Equipment remains an entity, because two drills of
the same model are different pieces of equipment, with their own maintenance and rental
histories.
Related Concepts
- Value Object — the other half of the decision.
- Aggregate — how entities group together.
- Repository — how they are retrieved.
- Encapsulation.
Practical Exercise
List your domain's persisted classes. For each, apply the test: are two objects with the same attributes the same object to the business?
The ones answering "yes" are candidates for becoming value objects.
Then check, for the entities, which identity strategy each uses and what would happen if the identifier had to change.
Interview Questions
- How do you distinguish an entity from a value object?
- What are the risks of using a natural identifier?
- Why generate the identity in the application rather than in the database?
Further Exploration
- Evans, Eric. Domain-Driven Design. Addison-Wesley, 2003.
- Vernon, Vaughn. Implementing Domain-Driven Design. Addison-Wesley, 2013 — the chapter on identity.