Check out v4 of the Fauna CLI

v4 of the Fauna CLI is now in beta.

The new version introduces enhancements to the developer experience, including an improved authentication workflow. To get started, check out the CLI v4 quick start.

Databases and multi-tenancy

In Fauna, a database stores data as documents in one or more collections.

Database model

Fauna’s database model makes it easy to create databases for isolated environments, such as staging and production, and multi-tenant applications:

  • Each Fauna database can have many child databases. You can use child databases as tenants for your application. See Multi-tenancy.

  • All databases, including child databases, are instantly allocated without provisioning or warmup.

  • Each database is logically isolated from its peers with separate access controls. See Isolation and access control.

  • All Fauna resources, except top-level keys, exist as documents within a specific database. This includes collections, user-defined functions, and child databases.

  • Queries run in the context of a single database and can’t access data outside the database. See Scope and routing.

Multi-tenancy

Fauna databases support a hierarchical database structure with top-level and child databases.

Top-level and child databases

Top-level databases exist in an account’s top-level context. All Fauna resources, except top-level keys, exist as documents within a specific database. This includes child databases.

A database can have many child databases, which can also have child databases.

Isolation and access control

You can use Fauna databases to build applications with strong isolation guarantees:

  • Each database is logically isolated from its peers with separate access controls.

  • You can use scoped keys from a parent database to manage and access data in child databases.

  • Child databases can’t access or discover parent or peer databases.

Scope and routing

Each Fauna query is an independently authenticated request to the Query HTTP API endpoint. Each query is a transaction.

Queries run in the context of a single database and can’t access data outside the database.

Queries are routed to a database based on the Query API request’s authentication secret. You can’t use a secret to access a peer or parent database.

Query child databases using scoped keys

A scoped key lets you use a parent database’s admin key to send query requests to its child databases.

For example, if you have an admin key for a parent database and want to connect to a child database named childDB, you can create a scoped key using the following format:

// Scoped key that impersonates an `admin` key for
// the `childDB` child database.
fn...:childDB:admin
See Scoped keys

Database collection

Fauna stores metadata and settings for a database’s child databases as documents in the Database system collection. These documents have the DatabaseDef type. You can use Database collection methods to create and manage databases in FQL.

The Database collection only contains direct child databases of the database scoped to your authentication secret. You can’t use the Database collection to access parent, peer, or other descendant databases.

See Database FQL docs

Global database ID

Each Database document contains an auto-generated, globally unique ID for the database:

{
  name: "ECommerce",
  coll: Database,
  ts: Time("2099-06-24T21:54:38.890Z"),
  // Globally unique id for the `ECommerce` database.
  global_id: "ysjpykbahyyr1",
  priority: 10,
  typechecked: true
}

Applications and external systems can also use this ID to identify a Fauna database.

For example, Fauna access providers use a database’s globally unique ID in the audience URL, which must be included in the aud (audience) claim of JWTs issued by the provider. Fauna uses this URL to authenticate query requests and route them to a specific database.

Create and manage databases

You can create and manage databases using:

Create a database

You can create a database using the Fauna Dashboard or the Fauna CLI's fauna database create command:

# Create a top-level 'my_db' database
# in the 'us' Region Group.
fauna database create \
  --name my_db \
  --database us

# Create a child database named 'child_db'
# directly under 'us/parent_db'.
fauna database create \
  --name child_db \
  --database us/parent_db

You can use Database.create() to programmatically create child databases database using an FQL query:

Database.create({
  name: "ECommerce",
  typechecked: true
})

Using FQL to create or manage top-level databases is not supported.

Manage a database’s schema

You can use schema to control a database’s structure and behavior. You manage schema using the Fauna Dashboard or as .fsl files using the Fauna CLI.

For example, the following fauna schema push command stages a schema change using the CLI:

fauna schema push \
  --database us/my_db

You can also create a CI/CD pipeline to copy and deploy schema across databases.

See Schema

Manage schema for child databases

You can manage schema for child databases using:

Use the Fauna CLI

This procedure uses v4 of the Fauna CLI, which is in beta. For the latest GA version, see v3 of the Fauna 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"

Rename a database

You can rename a database using the Fauna Dashboard. You can also use database.update() to rename a child database in an FQL query:

// Renames the `ECommerce` database to `ECommerceStore`.
Database.byName("ECommerce")!.update({
  name: "ECommerceStore"
})

Renaming a database preserves any inbound references to the database. Data in a renamed database remains accessible using existing keys.

Delete a database

You can delete a database using the Fauna Dashboard or the Fauna CLI's fauna database delete command:

# Delete the top-level 'my_db' database
# in the 'us' Region Group.
fauna database delete \
  --name my_db \
  --database us

# Delete a database named 'child_db' directly
# under 'us/parent_db'.
fauna database delete \
  --name child_db \
  --database us/parent_db

You can also use database.delete() to delete a child database in an FQL query:

// Deletes the `ECommerce` database.
Database.byName("ECommerce")!.delete()

Considerations

When you delete a database, its data becomes inaccessible and is asynchronously deleted. As part of the deletion process, Fauna recursively deletes:

  • Any keys scoped to the database.

  • The database’s child databases, including any nested databases.

Deleting a database with a large number of keys can exceed Transactional Write Ops throughput limits. This can cause throttling errors with a limit_exceeded error code and a 429 HTTP status code.

Deleting a database with a large number of child databases can cause timeout errors with a time_out error code and a 440 HTTP status code.

To avoid throttling or timeouts, incrementally delete all keys and child databases before deleting the database. See delete all keys and delete all child databases.

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!