Overview

This guide provides an overview of Fauna and its key features.

What is Fauna?

Fauna is a fully-managed serverless document database. Features include:

  • ACID-compliant transactions

  • Relational modeling and queries

  • Scalable, secure multi-tenancy

  • Dynamic attribute-based access control (ABAC)

  • High availability and global distribution

You access Fauna through a client driver or directly through an HTTP API.

Data model

You add data to Fauna as JSON-like objects called documents. Documents are stored in collections, which group related data.

See: Data model

Indexes

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.

You create indexes at the collection level. Fauna indexes support non-scalar data types, such as arrays or nested objects, and non-ID scalar fields.

See: Filter and sort with indexes

Multi-tenancy

A Fauna database can have multiple child databases. Child databases can have their own child databases.

Databases are instantly allocated. You can quickly and programmatically create databases using queries or the Fauna CLI.

Each database is logically isolated from its peers, with separate access controls. Transactions run in the context of a single database and can’t access data outside the database. This simplifies the process of building multi-tenant applications with strong isolation guarantees.

You can copy and deploy schema across databases using the Fauna CLI and a CI/CD pipeline.

High availability

Fauna is a highly available, globally distributed service. Your data is unaffected by regional outages and is always recoverable from disasters.

Connect to Fauna

You can interact with Fauna through a client driver or directly through its HTTP API. Any client that can send and receive HTTP requests can connect to Fauna.

See: HTTP API user guide

Fauna drivers

Fauna has official client drivers for popular programming languages, such as JavaScript, Python, and Go.

Each driver is a lightweight, open-source wrapper for the HTTP API. The drivers are small enough for use in serverless functions, edge networks, and other resource-constrained environments.

See: Client drivers

Fauna CLI and Dashboard

You manage Fauna using the Fauna CLI or the Fauna Dashboard UI. Use the CLI or Dashboard to:

  • Create and delete databases

  • Define and manage schemas

  • Run queries in an interactive shell

See: Get started with Fauna CLI, Fauna Dashboard

Manage schemas with FSL

Fauna uses Fauna Schema Language (FSL) to define schemas. Schemas determine the structure and behavior of your database.

You define FSL schemas for collections, security roles, server-side user-defined functions (UDFs), and more.

Example: Customer collection schema

The following schema defines the Customer collection:

collection Customer {
  unique [.email]

  index byEmail {
    terms [.email]
  }
}

The schema includes:

  • A unique constraint that ensures every Customer document has a unique email field value.

  • A byEmail index definition. You use the index to run exact match searches for Customer documents based on email values.

You can manage FSL 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: Get started with schema management

Query data with FQL

Fauna Query Language (FQL) is a TypeScript-like language used to read and write data. You typically compose an FQL query by chaining methods to one or more collections. Expressions are evaluated from left to right.

Example
// Gets the first customer with
// an email of "jane.doe@example.com".
let customer = Customer.byEmail("jane.doe@example.com").first()

// Gets orders for the customer.
Order.byCustomer(customer)
  .order(desc(.orderDate)) {
    user:    .customer.name,
    ordered: .orderDate,
    total:   .total
  }

The query declares a customer variable. To set the customer variable’s value, the query:

  • Calls the byEmail() index as a method on the Customer collection.

  • Calls the first() method on the results of the byEmail() call.

The query then:

  • Calls the byCustomer() index as a method on the Order collection. The query passes the customer variable to the index call.

  • Calls the order() method on the results of the byCustomer() call.

  • Projects the query results to a user-defined structure. This also resolves document references in the customer field.

See: FQL language reference

Static typing

FQL is statically typed. Every expression has a data type that’s checked before evaluation.

Type checking helps catch errors early and consistently, saving you time during development. You can turn off type checking for any query.

See: Static typing

Relationships

Fauna supports one-to-one, one-to-many, and many-to-many relationships between documents in different collections.

You create relationships by including a reference to a document in another document. This lets you model complex data structures without duplicating data across collections.

Projection lets you return only the specific fields you want from queries. You can project results to dynamically resolve document relationships. This lets you traverse multiple deeply nested relationships in a single query.

See: Define relationships

Event Streaming

Fauna supports Event Streaming. An event stream sends your application a real-time update when changes occur in a database. You can configure streams to only track specific collections, fields, or documents.

Fauna’s drivers provide methods for creating and connecting to streams.

See: Event Streaming

Security

Fauna prioritizes security and compliance. All Fauna connections use HTTPS. Fauna is compliant with GDPR and SOC2 Type II. Fauna can be configured to meet HIPAA requirements.

See: Security

Authentication

You authenticate with Fauna using secrets that are passed to the HTTP API as bearer tokens.

Secrets are also used for authorization. Each secret has one or more roles that control access to a database’s data.

Identity-based authentication

Fauna supports two methods for end-user authentication:

  • Credentials: A credential associates an end-user password with a document representing a user, system, or other identity. This document is called an identity document.

    Once created, you use the credential to generate a token you can use as a Fauna secret. The token is associated with the identity document and can have multiple roles.

    See: Credentials
  • Access providers: Configure an external identity provider (IdP), like Amazon Cognito or Auth0, as an access provider in your Fauna database.

    When a user logs in, the access provider passes a JSON Web Token (JWT) to your application. You can use the JWT as a Fauna secret. The JWT is associated with the user and can have multiple roles.

    See: External identity providers

Anonymous authentication

You can also create keys that can be used as Fauna secrets. Unlike tokens and JWTs, keys are not associated with an identity and only have one role.

See: Keys

Access control

Fauna supports dynamic attribute-based access control (ABAC), which extends traditional role-based access control (RBAC).

In Fauna, you define roles and their privileges as FSL schemas. You can conditionally grant or limit a privilege using a predicate.

Privilege predicates

Predicates are anonymous, read-only FQL functions that evaluate to true or false. They have access to FQL methods, collections, and server-side UDFs. Privilege predicates can also access the current token’s identity document.

Fauna evaluates privilege predicates at query time for each query. This lets you dynamically change privileges based on current state. For example, you can change access based on:

  • The user’s current location, status, or recent activity.

  • The accessed document’s current status or other attributes.

  • Date or time of day

Example

The following schema defines the customer role and includes several predicates:

role customer {
  ...
  privileges Order {
    // If the predicate is `true`,
    // grant read access to the `Order` collection.
    read {
      predicate (doc =>
        // Check the order's `status` field.
        doc.status != "Deleted" &&
        // Check that the order belongs to the customer.
        Query.identity() == doc.customer
      )
    }
    // If the predicate is `true`,
    // grant write access to the `Order` collection.
    write {
      predicate ((oldDoc, newDoc) =>
        // Check the existing order's status.
        oldDoc.status != "Deleted" &&
        // Check that the existing order belongs to the customer.
        Query.identity() == oldDoc.customer &&
        // Check that customer isn't changed by the write.
        oldDoc.customer == newDoc.customer &&
        // Check that the user has a positive balance
        // using the user-defined `hasFunds` function.
        hasFunds(Query.identity()?.balance) &&
        // Check the current time.
        // Allow access after 07:00 (7 AM).
        Time.now().hour > 7 &&
        // Disallow access after 20:00 (8 PM).
        Time.now().hour < 20
      )
    }
    ...
  }
  ...
}
See: Attribute-based access control (ABAC)

Dynamic role assignment

Fauna assigns roles to tokens based on their identity document’s collection and the role’s membership property.

Example

Tokens for Customer documents have the customer role:

role customer {
  membership Customer
  ...
}

You can use membership predicates to dynamically assign roles based on current state. Like privilege predicates, Fauna evaluates membership predicates at query time for each query.

Example

Limit the customer role to Customer users with an active status:

role customer {
  membership Customer {
    predicate ((user) => user.status == "active")
  }
  ...
}
See: Attribute-based access control (ABAC)

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!