Cerial
DecoratorsRelation

@model

The @model decorator declares which model a relation points to.

Declares which model a relation points to. Used on both PK (forward) and non-PK (reverse) relations to specify the target model.

Syntax

@model(ModelName)

The ModelName must be a valid model defined in the schema (same file or cross-file reference).

PK Side (Forward Relations)

On the PK side, @model() is paired with @field() to form a complete forward relation:

model Post {
  id Record @id
  title String
  authorId Record                                  // FK storage field
  author Relation @field(authorId) @model(User)    // Forward relation
}
  • @model(User) — tells Cerial this relation points to the User model.
  • Combined with @field(authorId), it creates a complete forward relation.

Non-PK Side (Reverse Relations)

On the non-PK side, @model() is the only relation decorator needed — no @field:

model User {
  id Record @id
  name String
  posts Relation[] @model(Post)                    // Reverse relation
}

Cerial automatically resolves the reverse relation by finding the matching forward relation on the Post model.

1
Example

model User {
  id Record @id
  name String
  profile Relation? @model(Profile)                // Reverse: optional 1:1
}

model Profile {
  id Record @id
  bio String
  userId Record                                    // FK storage
  user Relation @field(userId) @model(User)        // Forward: required 1:1
}
// Include the profile when querying a user
const user = await client.db.User.findOne({
  where: { id: userId },
  include: { profile: true },
});
// user.profile: Profile | null

1
Example

model User {
  id Record @id
  name String
  posts Relation[] @model(Post)                    // Reverse: array of posts
}

model Post {
  id Record @id
  title String
  authorId Record                                  // FK storage
  author Relation @field(authorId) @model(User)    // Forward: required
}
// Include related posts when querying a user
const user = await client.db.User.findOne({
  where: { id: userId },
  include: { posts: true },
});
// user.posts: Post[]

N
Example

In many-to-many relations, both sides use @model() alongside @field():

model Student {
  id Record @id
  name String
  courseIds Record[]
  courses Relation[] @field(courseIds) @model(Course)
}

model Course {
  id Record @id
  title String
  studentIds Record[]
  students Relation[] @field(studentIds) @model(Student)
}
// Both sides reflect the relationship
const student = await client.db.Student.findOne({
  where: { id: studentId },
  include: { courses: true },
});
// student.courses: Course[]

Cardinality Summary

SchemaDirectionCardinality
Relation @field(fk) @model(X)Forward (PK)One-to-one (required)
Relation? @field(fk) @model(X)Forward (PK)One-to-one (optional)
Relation? @model(X)Reverse (non-PK)One-to-one (optional)
Relation[] @model(X)Reverse (non-PK)One-to-many
Relation[] @field(fkArr) @model(X)Forward (PK, N
)
Many-to-many

Allowed On

ConstructAllowed
Relation / Relation? / Relation[] fields
Record fields— (validation error)
Object fields
Tuple elements

@model is strictly for Relation fields. Placing it on a Record field produces a validation error — Record fields store data, while Relation fields define the virtual relationship.

Rules

  • Every Relation with @field() must also have @model().
  • Reverse relations (Relation[] or Relation? without @field) only need @model().
  • If multiple relations exist between the same two models, use @key to disambiguate.

See Also

  • @field — specifies which Record field stores the FK
  • @key — disambiguates multiple relations between the same models
  • @onDelete — controls cascade behavior when related records are deleted

On this page