Relationships — Concept
A relationship is a typed edge from one entity instance to another. Causet manages the edge store; you declare the shape and optionally wire emit_events so projections can materialize queryable join tables.
Why relationships exist
Not every connection between entities belongs on a single entity’s snapshot. A user follows dozens of artists — storing following: [] on the user works, but so does a first-class edge with uniqueness enforced by the engine.
Relationships give you:
- Engine-level uniqueness —
unique: truededuplicates(from_id, to_id)at storage time - Optional automatic events —
emit_events.created/removedwithout a separateop: emit - Cross-stream writes in core —
relationship_createis allowed incore(unlike mutating another entity’s fields)
Relationships vs entity state vs projections
| Mechanism | Best for |
|---|---|
Entity state (push on /following) | Small lists owned by one entity |
| Relationship | Graph edges with cardinality and uniqueness |
| Projection | Queryable read models (join tables, feeds) |
Typical pattern: relationship + emit_events → projection listens to those events → query joins projection tables.
Cardinality mental model
many_to_many— users follow artists; artists have many followersone_to_many— one owner, many owned records (eachtohas at most onefrom)
Next steps
- Defining Relationships — syntax reference
- Examples — concert-app patterns
- Listeners — synchronous cross-entity updates as an alternative