Define relationships between your models for powerful data querying and type-safe nested operations.
Relations define how models connect to each other. They create foreign key constraints in the database and enable type-safe queries with nested data loading in your Rust code.
User ↔ Profile
User → Posts[]
Posts[] ↔ Tags[]
A one-to-one relation means each record in one model has exactly one related record in another model.
The foreign key field must have a @unique constraint.
Tip: Use one-to-one relations to split large models or when optional extended data is only needed in certain contexts.
The most common relation type. One record can have many related records, but each related record belongs to exactly one parent.
Many-to-many relations allow records in both models to have multiple related records. Prax can manage the join table automatically, or you can define it explicitly.
When to use explicit join tables: When you need additional data on the relationship (timestamps, ordering, metadata) or need more control over the join table structure.
Self-relations allow a model to relate to itself. Common for hierarchical data like comments with replies, organizational structures, or social graphs.
When models have multiple relations, use the name
argument in @relation to distinguish them.
Control what happens to related records when a parent record is deleted or updated.
| Action | On Delete | On Update |
|---|---|---|
Cascade |
Delete related records | Update foreign key values |
Restrict |
Prevent deletion if related records exist | Prevent update if related records exist |
SetNull |
Set foreign key to NULL | Set foreign key to NULL |
SetDefault |
Set foreign key to default value | Set foreign key to default value |
NoAction |
Database default (usually error) | Database default |
Relations can reference multiple fields for composite primary keys:
Load related data with include()
and filter by related records:
Create, connect, and disconnect related records in a single operation:
Add @@index([foreignKeyField])
to improve JOIN and filter query performance.
Use Cascade for child records that make no sense without the parent.
Use Restrict for important data that shouldn't be accidentally deleted.
Always use the name argument when models have multiple relations
to clearly distinguish their purpose.
| Argument | Required | Description |
|---|---|---|
fields |
Yes* | Foreign key field(s) on this model |
references |
Yes* | Referenced field(s) on the related model |
name |
No | Relation name (required for multiple relations) |
onDelete |
No | Action when parent is deleted |
onUpdate |
No | Action when parent key is updated |
* Required on the side of the relation that holds the foreign key