Relationship Best Practices
Pair unique: true with preflight when callers need feedback
unique: true silently ignores duplicate edges — no error, no duplicate row. That is correct for idempotent retries but wrong if the API should return ALREADY_FOLLOWING.
Add an explicit preflight reject when duplicate attempts should fail visibly.
Always project relationship events for queries
The relationship store is not exposed to the query service. Subscribe a projection to emit_events types and build a table with upsert / delete mutations.
Use relationships for edges, not cross-entity field updates
You cannot mutate another entity’s balance or counters in core. Use relationship_create for graph semantics; use op: submit in side_effects for cross-stream state changes.
Common mistakes
Expecting unique: true to return an error on duplicates. It does not. Add preflight reject if the caller should know.
Writing cross-stream state mutations in core instead of relationship_create. Use relationships for edges; use submit for other streams.
Not projecting relationship events. Without a projection, you cannot join relationship data in named queries.
Relying on emit_events for custom payload fields. The engine emits relationship metadata. For fields like followed_at, emit explicitly in side_effects instead.
Next steps
- Examples — full concert-app YAML
- Projection Examples —
user_followingtable - Idempotency — retry-safe edge creation