Manage schema as .fsl files using the Fauna CLI
A schema controls a database’s structure and behavior. In Fauna, you define schema the using Fauna Schema Language (FSL).
You can manage schemas as .fsl files using the
Fauna CLI.
This page covers how to manage .fsl files using the CLI. Using .fsl files
lets you version control, review, and automate schema changes.
|
To manage |
Set up a schema directory
You typically store .fsl files in a schema directory alongside your
application code. The directory can use any name. schema is a common choice.
For more information about setting up a project using the CLI, see Set up a project using FSL and the Fauna CLI.
Create FSL schema files
An .fsl file can contain schema for multiple resources. You can use multiple
.fsl files to organize your schema. While subject to limits, there
is no performance benefit to splitting .fsl files or storing larger,
individual files.
Valid FSL filenames must use the .fsl extension and can’t start with *.
FSL schema syntax
The following table links to FSL syntax to use when creating .fsl files:
| Resource | FSL Syntax |
|---|---|
Collections, including:
|
|
Common conventions
A common convention is to organize your .fsl files by resource type to
maintain a clear and maintainable schema structure:
schema/
├── collections.fsl # Collection schema
├── functions.fsl # User-defined functions
├── roles.fsl # Role definitions
└── access-providers.fsl # Access provider definitions
When you push .fsl files to Fauna, Fauna retains the filenames and directory
organization. This lets you later pull the same files.
Filenames for generated FSL schema
Schema created using FQL schema methods or the
Fauna Dashboard are stored in the main.fsl
file. After pulling the file locally, you can reorganize the schema into
separate files as desired.
Push schema to Fauna
A project directory includes .fsl files for the project’s database. You can
use the Fauna CLI to push a project’s .fsl files to Fauna.
Run a staged schema change
A staged schema change lets you change one or more collection schema without index downtime due to index builds.
To run a staged schema change, you must use the Fauna CLI or the Fauna Core HTTP API’s Schema endpoints.
You can’t run a staged schema change using FQL schema methods or the Fauna Dashboard.
To run a staged schema change using the Fauna CLI:
-
Make the desired changes to
.fslfiles in your schema directory.You can’t use a staged schema change to delete or rename schema. Instead, delete or rename the schema in a separate unstaged schema change.
-
Use
fauna schema pushto stage the schema changes.fauna schema pushstages schema changes by default:# Replace 'us' with your preferred region group: # 'us' (United States), 'eu' (Europe), or `global`. # Replace 'my_db' with your database's name. fauna schema push \ --database us/my_db \ --dir /path/to/schema/dirA database can have one staged schema change at a time. You can update staged schema using
fauna schema push.When a database has staged schema, any access or updates done using FQL’s schema commands on related system collections interact with the staged schema, not the database’s active schema.
For example, when schema changes are staged,
Collection.all()returnsCollectiondocuments for the staged collection schema, not the database’sCollectiondocuments.If a database has staged schema, you can’t edit the database’s active schema using FQL, the Dashboard, or an unstaged schema change. You must first abandon the staged schema change.
-
Use
fauna schema statusto check the status of the staged schema:fauna schema status \ --database us/my_dbPossible statuses:
Staged status Description pendingChanges are being processed. New indexes are still being built.
readyAll indexes have been built. Changes are ready to commit.
failedThere was an error during the staging process.
-
When the status is
ready, usefauna schema committo apply the staged schema to the database:fauna schema commit \ --database us/my_dbYou can only commit staged schema with a status of
ready.If you no longer wish to apply the staged schema or if the status is
failed, usefauna schema abandonto unstage the schema:fauna schema abandon \ --database us/my_db
Run an unstaged schema change
To immediately commit schema changes without staging, use the --active
option:
fauna schema push \
--database us/my_db \
--active
Schema changes that trigger an index build may result in downtime where the index is not queryable.
You can’t run an unstaged schema change if a database has staged schema. You must abandon the staged schema changes first.
Create and delete schema
Committing a schema to Fauna creates the related resource. For example, committing a collection schema to Fauna creates the collection.
Similarly, you can delete the resource by removing the schema from the FSL files in a project’s schema directory then pushing the changes to Fauna.
Compare local, staged, and active schema
Use fauna schema diff to compare a project’s
local, staged, and active schema.
For example, to compare the local schema to the remote staged schema:
fauna schema diff \
--database us/my_db
|
If there is no staged schema, |
To compare the local schema to the remote active schema:
fauna schema diff \
--database us/my_db \
--active
To compare the remote active schema to the remote staged schema:
fauna schema diff \
--database us/my_db \
--staged
By default, fauna schema diff prints a semantic
summary of the changes. To get a textual diff, use the --text option. For
example:
fauna schema diff \
--database us/my_db \
--text
Pull remote schema from Fauna
Use fauna schema pull to pull a database’s
remote .fsl schema files into a project’s local schema directory:
fauna schema pull \
--database us/my_db
If the database has staged schema, the command pulls the database’s remote staged schema by default.
If the database has no staged schema, the command pulls the database’s remote active schema.
Pull active schema files
Use the fauna schema pull command’s --active
option to pull the database’s remote active schema regardless of whether the
database has staged schema:
fauna schema pull \
--database us/my_db \
--active
Delete local files
The fauna schema pull command overwrites
existing schema files in the local directory.
If wanted, you can use the --delete option to delete local .fsl files that
aren’t part of the remote schema:
fauna schema pull \
--database us/my_db \
--delete
Manage schema with a CI/CD pipeline
You can use schema-related Fauna
CLI commands to manage schema as .fsl files. The following examples show how
you can use a CI/CD pipeline to:
Test schema changes in pull requests
The following GitHub workflow shows how to use the Fauna CLI to start a local Fauna container and test a pull request’s database schema changes. The workflow ensures that the schema changes are:
-
Compatible with your project’s tests
-
Valid and don’t return migration errors that would conflict with the database’s data.
In your project’s .github/workflows/ directory, create a .yml file with the
following contents:
name: Validate database schema changes - Pull request
on:
pull_request:
paths:
# Set this to the path to your schema directory
- 'schema/**'
jobs:
schema_change_valid:
name: Schema Change Valid
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [20.x]
steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install Fauna CLI
run: npm install -g fauna-shell
- name: Test PR schema changes
run: |
# Check out the base branch that the pull request targets.
git fetch origin ${{ github.base_ref }}:${{ github.base_ref }}
git checkout ${{ github.base_ref }}
# Start a local Fauna container and create the 'my_db'
# database. Apply the base branch's schema to the 'my_db'
# database's active schema.
fauna local \
--dir ./path/to/schema/dir \
--database my_db \
--typechecked
# Run a query to seed collection documents in the 'my_db'
# database. Collection documents are required to test
# migration blocks in collection schema. If a collection
# has never contained documents, the collection schema's
# migration block is ignored, if present. This ensure
# the migration block is validated.
fauna query \
--local \
--database my_db \
--input ./path/to/seed-query.fql
# Check out the PR branch.
git fetch origin ${{ github.head_ref }}:${{ github.head_ref }}
git checkout ${{ github.head_ref }}
# Push the PR's schema changes to the local 'my_db' database.
# Fails if the schema changes aren't valid.
fauna schema push --dir ./path/to/schema/dir \
--local \
--database my_db \
--active \
--no-input
# Run tests in the local 'my_db' database.
# Fails if the schema changes are incompatible.
# The command(s) may differ based on your project's setup.
# This example uses 'npm test'.
echo "Running tests ..."
npm test
Automatically stage and deploy schema changes
The following examples show how you can use the Fauna CLI to automatically
stage and deploy .fsl files in a schema directory:
|
You can’t use a staged schema change to delete or rename schema. Instead, delete or rename the schema in a separate unstaged schema change. |
GitHub
In your project’s .github/workflows/ directory, create a .yml file with the
following contents:
name: Main CI
on:
push:
branches: [ main ]
jobs:
ci:
runs-on: ubuntu-latest
env:
FAUNA_SECRET: ${{ secrets.FAUNA_SECRET }}
strategy:
matrix:
node-version: [20.x]
steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install Fauna CLI
run: npm install -g fauna-shell
- name: Stage schema
run: fauna schema push \
--dir ./path/to/schema/dir \
--secret $FAUNA_SECRET \
--no-input
- name: Check schema status
id: schema-check
run: |
attempts=0
max_attempts=60 # 30 minutes with 30-second intervals
while [ $attempts -lt $max_attempts ]; do
STATUS=$(fauna schema status --secret $FAUNA_SECRET | grep -oP '(?<=Staged changes: )\w+')
echo "Current status: $STATUS"
if [ "$STATUS" = "ready" ]; then
echo "Schema is ready"
echo "schema_status=ready" >> $GITHUB_OUTPUT
exit 0
elif [ "$STATUS" = "failed" ]; then
echo "Schema staging failed"
echo "schema_status=failed" >> $GITHUB_OUTPUT
exit 1
fi
echo "Waiting for schema to be ready..."
sleep 30
attempts=$((attempts + 1))
done
echo "Timeout waiting for schema status"
echo "schema_status=timeout" >> $GITHUB_OUTPUT
exit 1
- name: Commit or abandon schema
if: always()
run: |
if [[ "${{ steps.schema-check.outputs.schema_status }}" == "ready" ]]; then
fauna schema commit --secret $FAUNA_SECRET --no-input
else
fauna schema abandon --secret $FAUNA_SECRET --no-input
fi
GitLab
In your project, create a .gitlab-ci.yml file with the following
contents:
stages:
- stage_schema
- commit_or_abandon_schema
variables:
FAUNA_SECRET: $FAUNA_SECRET
default:
image: node:20
stage_schema:
stage: stage_schema
script:
- npm install -g fauna-shell
- fauna schema push --secret $FAUNA_SECRET --no-input --dir ./path/to-schema/dir
- |
attempts=0
max_attempts=60
while [ $attempts -lt $max_attempts ]; do
STATUS=$(fauna schema status --secret $FAUNA_SECRET | grep -oP '(?<=Staged changes: )\w+')
echo "Current status: $STATUS"
if [ "$STATUS" = "ready" ]; then
echo "Schema is ready"
exit 0
elif [ "$STATUS" = "failed" ]; then
echo "Schema staging failed"
exit 1
fi
echo "Waiting for schema to be ready..."
sleep 30
attempts=$((attempts + 1))
done
echo "Timeout waiting for schema status"
exit 1
only:
- main
commit_or_abandon_schema:
stage: commit_or_abandon_schema
script:
- npm install -g fauna-shell
- |
if [ $? -eq 0 ]; then
fauna schema commit --secret $FAUNA_SECRET --no-input
else
fauna schema abandon --secret $FAUNA_SECRET --no-input
exit 1
fi
only:
- main
Manage schema for child databases
Fauna databases support a hierarchical database structure with top-level and child databases. You can manage schema for child databases using:
scoped keys with the CLI or using FQL schema methods.
Use scoped keys with the CLI
The Fauna CLI’s fauna schema commands let you
specify a --database when you use
interactive login or an
account key for authentication. You
can use --database to interact with any child database the related account key
has access to.
# Stage schema changes for the
# 'us/parent_db/child_db' database.
fauna schema push \
--database us/parent_db/child_db \
--dir /path/to/schema/dir
Alternatively, you can use --secret to provide a
scoped key. A scoped key lets you
interact with a child database’s schema using a parent database’s admin key.
For example, with a parent database’s admin key secret, you can access a child database by appending the child database name and role:
# Use a scoped key from a parent database
# to stage schema in the 'child_db' child database.
# The scoped key has `admin` privileges.
fauna schema push \
--secret fn123:child_db:admin \
--dir /path/to/schema/dir
Use FQL schema methods
Fauna stores each schema for a database as an FQL document in a related system collection.
You can use methods for these system collections to programmatically manage the schema of child databases using FQL queries. Use a scoped key to manage a child database’s schema using queries in a parent database.
| FSL schema | FQL system collection |
|---|---|
Use Schema HTTP API endpoints
You can use the Fauna Core HTTP API’s Schema endpoints to perform programmatically perform schema changes, including staged schema changes. Use a scoped key to manage a child database’s schema using a parent database’s key secret.
For example, the following
Update schema
files request uses a scoped key that impersonates a key with the admin role
for the childDb child database. The request starts a staged schema change
for the childDb child database:
curl -X POST "https://db.fauna.com/schema/1/update?staged=true" \
-H "Authorization: Bearer $FAUNA_SECRET:childDb:admin" \
-H "Content-Type: multipart/form-data" \
-F "collections.fsl=@./schema/collections.fsl" \
-F "functions.fsl=@./schema/functions.fsl"