Constraints
Control field validation with required, default, unique, and maxLength constraints in Laizy schemas.
Constraints
Constraints control validation and behavior for each field in your schema. They go inside curly braces after the field type and determine how content is validated when created or updated.
Syntax
Constraints use a key-value syntax inside { } blocks after the field type:
fieldName: FieldType {
constraintName: value
}Boolean constraints can omit the value -- just writing the constraint name is equivalent to setting it to true:
// These are equivalent:
title: String { required: true }
title: String { required }Fields without constraints do not need curly braces at all:
model Author {
name: String { required: true }
bio: String
}Available Constraints
required
Makes a field mandatory when creating content. If a required field is not provided, the creation will fail with a validation error.
Applies to: All field types
model BlogPost {
title: String {
required: true
}
content: String {
required: true
}
// Optional field — no curly braces needed
subtitle: String
}Behavior:
- Required fields must have a value when creating content
- Required fields without
defaultgeneratewarningimpact during migrations (existing content needs a value) - In the generated TypeScript client, required fields are non-optional in the
Createinput type - Optional fields (without
required: true) are marked with?in theCreateinput type
Generated TypeScript:
export interface CreateBlogPostInput {
title: string // required — no ?
content: string // required — no ?
subtitle?: string // optional — has ?
}default
Sets a default value that is used when the field is not provided during content creation. Fields with defaults are excluded from the generated Create input type since they always have a fallback value.
Applies to: All field types (value must match the field type)
model BlogPost {
status: String {
default: "draft"
}
viewCount: Int {
default: 0
}
isPublished: Boolean {
default: false
}
}Behavior:
- The default value is applied when content is created without this field
- Fields with defaults are safe to add during migrations (no data loss)
- Default values are used as auto-fill values during migration when making a field required
- The value type must match the field type (strings for
String, numbers forInt/Float, booleans forBoolean)
Fields with default are excluded from the generated CreateInput interface. Since they always have a value, they do not need to be provided by the caller.
Generated TypeScript:
// 'status' has a default, so it's excluded from CreateInput
export interface CreateBlogPostInput {
title: string
content: string
}
// But it still appears in the Update and read interfaces
export interface UpdateBlogPostInput {
title?: string
content?: string
status?: string
}unique
Enforces uniqueness across all content entries of the same model. No two entries can have the same value for a unique field.
Applies to: All field types
model Author {
email: String {
required: true
unique: true
}
}
model BlogPost {
slug: String {
required: true
unique: true
}
}Behavior:
- Attempting to create or update content with a duplicate value will fail
- Unique constraints are enforced at the database level
- Adding a unique constraint to an existing field is a safe migration (unless duplicates already exist)
- Commonly combined with
requiredfor identifiers like slugs, emails, or SKUs
maxLength
Limits the character count for String fields. Content creation or update will fail if the string exceeds this length.
Applies to: String fields only
model BlogPost {
title: String {
required: true
maxLength: 200
}
excerpt: String {
maxLength: 500
}
}Behavior:
- The value must be a positive integer
- Validation happens before content is saved
- Adding or changing
maxLengthis a safe migration (existing content is not modified, only future writes are validated) - Removing
maxLengthis also safe (less restrictive)
maxLength only applies to String fields. Using it on Int, Float, Boolean, or DateTime fields has no effect.
Combining Constraints
Multiple constraints can be applied to a single field. Each constraint goes on its own line inside the curly braces:
model Product {
name: String {
required: true
maxLength: 200
}
sku: String {
required: true
unique: true
maxLength: 50
}
price: Float {
required: true
}
inStock: Boolean {
default: true
}
description: String
}Common Constraint Patterns
Identifier fields (slugs, SKUs, emails):
slug: String {
required: true
unique: true
}Status fields with a default:
status: String {
default: "draft"
}Title fields with length limits:
title: String {
required: true
maxLength: 200
}Counter fields starting at zero:
viewCount: Int {
default: 0
}Toggle fields defaulting to off:
isPublished: Boolean {
default: false
}Constraint Validation Summary
| Constraint | Valid Types | Value Format | Migration Impact |
|---|---|---|---|
required | All | true / false | Warning if adding to existing model (needs default values) |
default | All | Must match field type | Safe (provides fallback value) |
unique | All | true / false | Safe (unless duplicates exist) |
maxLength | String | Positive integer | Safe (only affects future writes) |
Migration Behavior
When you change constraints in your schema and run laizy sync, the migration planner evaluates the safety of each change:
Safe changes (no confirmation needed):
- Adding
defaultto any field - Adding
maxLengthor changing its value - Making a required field optional (removing
required) - Adding or removing
unique
Warning changes (confirmation required):
- Making an optional field required without a default (existing content may have null values)
- Adding a new required field without a default to an existing model
Destructive changes:
- Removing a field entirely (data loss)
- Incompatible type changes
The sync command shows these impacts clearly in the migration plan table before asking for confirmation.
Next Steps
- Field Types -- All available field types and their behaviors
- Migrations -- How the sync command handles schema changes safely
- Schema Syntax -- Full reference for the
.laizyschema language