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.

Query best practices

This guide covers best practices for querying data in Fauna.

Use indexes for commonly accessed data

Indexes are the most important and effective tool to increase performance and reduce the cost of your queries.

Avoid uncovered queries whenever possible. To reduce document reads, include any frequently queried fields in indexes.

See Indexes

Use index terms for exact match searches

For the best performance, especially on large datasets, use an index with terms to filter collection documents based on an exact field value.

collection.where() and collection.firstWhere() require a scan of the entire collection and aren’t performant on large collections.

Avoid using frequently updated fields as index terms. See Avoid using frequently updated fields as index terms.

See Index terms

Avoid using frequently updated fields as index terms

Internally, Fauna partitions indexes based on its terms, if present. Frequent updates to term field values trigger updates to these partitions.

If you need to filter or run an exact match search on a frequently updated field, consider adding the field as an index value instead:

collection Product {
  ...
  // Defines the `sortedByName()` index.
  // The index includes the `name` field as an index value.
  // `name` is a frequently updated field.
  index sortedByName {
    values [.name, .description, .price]
  }
}

Then use the index to run a range search on the index value:

// Uses the `sortedByName()` index to run a range search
// on `name` field values. The query only retrieves `Product`
// collection documents with a `name` of `limes`. The query
// is covered and avoids document reads.
Product.sortedByName({ from: "limes", to: "limes" }) {
  name,
  description,
  price
}

Use index values for sorting and range searches

For large collections, use index values instead of set.order() to sort a collection’s documents. Reserve set.order() for small, ad-hoc sorting on Sets of one page or less.

Similarly, avoid using collection.where() to perform range searches on large collections. Instead, run a range search on index values.

See Index values

Use projection to only retrieve fields you need

Projection lets you select the fields to return from a document or Set.

For the best performance and costs, use an index and only project fields covered as an index term or value. This lets you read data from the index rather than the underlying documents.

To reduce unneeded compute operations, use projection to only fetch computed fields when needed. Computed fields aren’t persistently stored as part of the document. Instead, the field’s value is computed on each read.

See Projection and field aliasing

Return null on document writes

Methods that create or write to a document, such as Collection.create() or document.update(), typically return the document.

An FQL query only returns the result of its last statement. If you don’t use the returned document, you can add a null statement to the end of the query to return null instead. This can lower egress costs.

For example:

// The `update()` call writes to a `Product` collection document.
// `update()` returns the updated document.
Product.byId("111")
  ?.update({ price: 75 })

// FQL queries return the result of the last statement.
// The `null` statement ensures the query returns `null`.
null

Use pageSize() for pagination

In most cases, you should use set.pageSize(), not set.paginate(), to control the page size of paginated results. Unlike pageSize(), paginate():

  • Uses eager loading and fetches results instantly, even if the results aren’t returned or used. This can produce slower and more wasteful queries.

  • Is not compatible with Fauna client driver pagination methods.

See Pagination

Create UDFs for complex queries and workflows

A user-defined function (UDF) is a Set of one or more FQL statements stored as a reusable resource in a Fauna database.

UDFs are composable, letting you combine multiple UDFs to create more complex functions or workflows.

In most cases, a query that’s rewritten in multiple places or that involves complex logic should be stored as a UDF.

See User-defined functions (UDFs)

Use Fauna Logs to monitor query performance

You can use Fauna Logs to monitor the performance of your Fauna queries and diagnose issues.

Instrument your queries with query tags and traceparent identifiers. You can then aggregate the logs to identify trends or visualize the logs in an observability platform, such as Datadog.

See Fauna Logs

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!