Schema

Schemas control your database’s structure and behavior.

Fauna Schema Language

In Fauna, you define schemas using Fauna Schema Language (FSL). You use FSL to create and update schemas for:

Manage schemas as FSL files

You can manage schemas as FSL files and use the Fauna CLI to push changes to Fauna. This lets you version control, review, and automate schema changes.

See Fauna CLI

Collection schema

Reference: Collection schema

A collection schema defines the structure and behavior of a collection and its documents. It can include:

You create and manage collection schemas in FSL:

collection Product {
  // Field definitions.
  // Define the structure of the collection's documents.
  name: String?
  description: String?
  price: Double = 0.00
  quantity: Int = 0
  creationTime: Time = Time.now()
  creationTimeEpoch: Int?
  typeConflicts: { *: Any }?

  // Wildcard constraint.
  // Allows or disallows arbitrary ad hoc fields.
  *: Any

  // Migrations block.
  // Used for schema migrations.
  // Instructs Fauna how to handle updates to a collection's
  // field definitions and wildcard constraint.
  // Contains imperative migration statements.
  migrations {
    add .typeConflicts
    add .quantity
    backfill .quantity = 0
    drop .internalDesc
    move_conflicts .typeConflicts
    move .desc -> .description
    split .creationTime -> .creationTime, .creationTimeEpoch
  }

  // Index definition.
  // You use indexes to filter and sort documents
  // in a performant way.
  index byName {
    terms [.name]
    values [desc(.quantity), desc(mva(.categories))]
  }

  // Unique constraint.
  // Ensures a field value or combination of field values
  // is unique for each document in the collection.
  // Supports multivalue attribute (`mva`) fields, such as arrays.
  unique [.name, .description, mva(.categories)]

  // Check constraint.
  // Ensures a field value meets provided criteria
  // before writes. Written as FQL predicate functions.
  check posQuantity ((doc) => doc.quantity >= 0)

  // Computed field.
  // A document field that derives its value from a
  // user-defined, read-only FQL function that runs on every read.
  compute InventoryValue: Number = (.quantity * .price)

  // Controls whether you can write to the `ttl` field for collection
  // documents. If the collection schema doesn't contain field
  // definitions, `document_ttls` defaults to `true`. Otherwise,
  // `document_ttls` defaults to `false`.
  document_ttls true

  // Sets the default `ttl` for documents in days from their creation
  // timestamp. Ignored if `document_ttls` is false. You can override
  // the default ttl` during document creation.
  ttl_days 5

  // Controls document history retention.
  history_days 3
}

Document type definitions

A collection’s schema can include a document type definition. The definition controls what fields are accepted in a collection’s documents. You define a document’s type using:

Field definitions and schema migrations are in beta.

A schema migration is required to change a collection’s field definitions or wildcard constraint. By performing a schema migration, you automatically opt-in to the beta.

During beta, schema migrations triggers a rebuild of all of a collection’s indexes. This can make large indexes unusable for extended periods.

To register for the beta and sign up for production support, go to https://go.fauna.com/schemabetaproductionsupport.

Field definitions

Reference: Field definitions

Field definitions define fields for a collection’s documents. A field definition consists of:

  • A field name

  • Accepted data types for the field’s values

  • An optional default value

You can use field definitions to:

  • Ensure each document in a collection contains a specific field

  • Limit a field’s values to specific types

  • Set a default value for documents missing a field

  • Enumerate accepted values

collection Product {
  // `name` is optional (nullable).
  // Accepts `String` or `null` values.
  name: String?  // Equivalent to `name: String | Null`

  // `price` is optional (nullable).
  // Accepts `Double` or `null` values.
  price: Double?

  // `quantity` is non-nullable.
  // Accepts only `Int` values.
  // If the field is missing on create, defaults to `0`.
  quantity: Int = 0

  // `creationTime` is non-nullable.
  // Accepts only `Time` or `Number` values.
  // If `null` or missing, defaults to the current time.
  creationTime: Time | Number = Time.now()

  // `category` is non-nullable.
  // Accepts only the enumerated "grocery",
  // "pharmacy", or "home goods" values.
  // If `null` or missing, defaults to "grocery".
  category: "grocery" | "pharmacy" | "home goods" = "grocery"
}

Wildcard constraint

Reference: Wildcard constraints

An ad hoc field is an arbitrary document field that doesn’t have a field definition.

You can use a collection schema’s wildcard constraint to allow or disallow ad hoc fields in the collection’s documents.

collection Product {
  name: String?  // Equivalent to `name: String | Null`
  ...

  // Wildcard constraint.
  // This example accepts ad hoc fields of any type.
  *: Any
}

Computed fields

Reference: Computed field definitions

Computed fields derive their field value from a provided function. They let you create new fields based on existing data or calculations.

You can use a computed field to:

  • Combine or transform other field values

  • Assign a value based on an if ... else expression

  • Assign a value based on one or more ranges

Computed fields aren’t part of the original document or persistently stored. Instead, the field’s value is computed on each read.

Document type enforcement

Fauna rejects attempts to write documents that don’t conform to a collection’s field definitions and wildcard constraint.

You can use the collection’s field definitions and wildcard constraint to adjust how strictly you enforce a predefined structure on collection documents:

Strategy Description Field definitions Wildcard constraint

Schemaless

Accepts ad hoc fields of any type. No fields are predefined.

No field definitions

No wildcard constraint
OR
A wildcard constraint of
*: Any

Permissive

Accepts ad hoc fields and predefined fields. Fields must conform to the structure of their definitions.

One or more field definitions

A wildcard constraint

Strict

Only accepts predefined fields

One or more field definitions

No wildcard constraint

Schemaless by default

If a collection has no field definitions, it’s schemaless by default. It implicitly accepts ad hoc fields of any type.

Progressive enforcement

Using permissive document types is often helpful earlier in an application’s development. Allowing ad hoc fields lets you add fields as needed.

As your data evolves, you can use zero-downtime migrations to add field definitions for ad hoc fields and normalize field values. This lets you move from a permissive document type to strict one (or the reverse).

Tutorial: Progressively enforce a document type

Zero-downtime migrations

A schema migration is an update to a collection schema’s field definitions or wildcard constraint. Schema migrations require no downtime or locks on your database. Changes are immediately visible in subsequent queries.

Migrations block

Reference: Migrations block

To handle migrations, you include a migrations block in the collection schema. The block contains one or more imperative migration statements.

The statements instruct Fauna on how to migrate from the collection’s current field definitions and wildcard constraint to the new ones.

collection Product {
  ...
  *: Any

  migrations {
    // Applied 2099-05-06
    add .typeConflicts
    add .quantity
    move_conflicts .typeConflicts
    backfill .quantity = 0
    drop .internalDesc
    move .desc -> .description
    split .creationTime -> .creationTime, .creationTimeEpoch

    // Applied 2099-05-20
    // Make `price` a required field.
    split .price -> .price, .tempPrice
    drop .tempPrice
    backfill .price = 10.00
  }
}

Run a schema migration

A typical schema migration involves three steps:

  1. Update the field definitions and wildcard constraint in the collection schema.

  2. Add one or more related migration statements to the collection schema’s migrations block. Include comments to group and annotate statements related to the same migration.

  3. Submit the updated collection schema to Fauna using the Fauna CLI or the Fauna Dashboard.

Fauna runs each new migration statement sequentially from top to bottom. Fauna ignores unchanged migration statements from previous migrations.

Changes from the migration are immediately visible in any subsequent queries.

Migration errors

When you submit a collection schema, Fauna checks the schema’s field definitions and migration statements for potential conflicts.

If a change could conflict with the collection’s data, Fauna rejects the schema with an error message. The check doesn’t require a read or scan of the collection’s documents.

Index definitions

An index stores, or covers, specific document field values for quick retrieval. Using indexes can significantly improve query performance and reduce costs, especially for large datasets.

See Indexes

Unique constraints

Reference: Unique constraints

Unique constraints ensures a field value or combination of field values is unique for each document in a collection. Fauna rejects document writes that don’t meet the constraint.

Check constraints

Reference: Check constraints

Check constraints ensure field values meet a pre-defined rule. For example, you can check that field value is in an allowed range.

You define a check constraint as a read-only FQL predicate. Fauna only allows document writes if the predicate evaluates to true`.

Document retention

A document can include an optional ttl (time-to-live) field that contains the document’s expiration timestamp. After the ttl timestamp passes, Fauna permanently deletes the document.

You can use a collection schema’s ttl_days field to set a default ttl for collection documents. See Set a default ttl.

You can use a collection schema’s document_ttls field to control whether you can write to the ttl field for collection documents. See Enable or disable ttl writes.

See Document removal

Document history

Fauna stores snapshots of each document’s history. Fauna creates these snapshots each time the document receives a write.

You can use a collection schema’s history_days field to set how many days of document history Fauna retains for a collection’s documents.

See Document history

Protected mode

Protected mode is a database setting that prohibits destructive operations on a database’s collections.

When you create a database in the Fauna Dashboard, you select one of the following Protected Mode options:

Option Description

Disabled

Default. No operations are prohibited.

Enabled

Prohibits destructive operations. See Prohibited operations.

Inherit

Sets the database’s Protected Mode setting to the nearest ancestor’s Protected Mode setting that is not Inherit. This option is only available for child databases.

Prohibited operations

When Protected Mode is Enabled, the following operations are prohibited:

Resource or field Prohibited operations

Delete

Change
Remove

Decrease
Remove

Decrease
Add

Change
Remove

Is this article helpful? 

Tell Fauna how the article can be improved:
Visit Fauna's forums or email docs@fauna.com

Thank you for your feedback!