JavaScript client driver for Fauna

Version: 2.0.1 Repository: fauna/fauna-js

Fauna’s JavaScript client driver lets you run FQL queries from JavaScript or TypeScript applications.

This guide shows how to set up the driver and use it to run FQL queries. The examples use Fauna’s demo data.

This driver can only be used with FQL v10. It’s not compatible with earlier versions of FQL. To use earlier FQL versions, use the faunadb package.

Supported runtimes

The driver supports the following runtime environments.

Server-side

  • Current - v20

  • LTS - v18

Cloud providers

  • Cloudflare Workers

  • AWS Lambda

  • Netlify

  • Vercel

Browsers

Stable versions of:

  • Chrome 69+

  • Firefox 62+

  • Safari 12.1+

  • Edge 79+

Installation

The driver is available on npm. Install it using your preferred package manager:

npm install fauna

Browsers can import the driver using a CDN link:

<script type="module">
  import * as fauna from "https://cdn.jsdelivr.net/npm/fauna@latest/dist/browser/index.js";
</script>

Basic usage

The following application:

  • Initializes a client instance to connect to Fauna

  • Composes a basic FQL query using an fql template

  • Runs the query using query()

import { Client, fql, FaunaError } from "fauna";
// Use `require` for CommonJS:
// const { Client, fql, FaunaError } = require('fauna');

// Initialize the client to connect to Fauna
const client = new Client({
    secret: 'YOUR_FAUNA_SECRET'
});

try {
  // Compose a query
  const query = fql`
    Product.sortedByPriceLowToHigh() {
      name,
      description,
      price
    }`;

  // Run the query
  const response = await client.query(query);
  console.log(response.data);

} catch (error) {
  if (error instanceof FaunaError) {
    console.log(error);
  }
} finally {
  // Clean up any remaining resources
  client.close();
}

Connect to Fauna

To connect to Fauna, initialize a Client instance using a Fauna key, access token, or JWT:

const client = new Client({
  secret: 'YOUR_FAUNA_SECRET' // Your key, access token, or JWT
});

If not specified, secret defaults to the FAUNA_SECRET environment variable. For other configuration options, see Client configuration.

Multiple connections

You can use a single client instance to run multiple asynchronous queries at once. The driver manages HTTP connections as needed. Your app doesn’t need to implement connection pools or other connection management strategies.

You can create multiple client instances to connect to Fauna using different credentials or client configurations.

Run FQL queries

Use fql templates to compose FQL queries. Run the queries using query():

const query = fql`Product.sortedByPriceLowToHigh()`;
client.query(query)

By default, query() uses query options from the Client configuration. You can pass options to query() to override these defaults. See Query options.

Variable interpolation

Use ${} to pass native JavaScript variables to fql queries:

// Create a native JS var
const collectionName = "Product";

// Pass the var to an FQL query
const query = fql`
  let collection = Collection(${collectionName})
  collection.sortedByPriceLowToHigh()`;

client.query(query);

Passed variables are encoded to an appropriate type and passed to Fauna’s HTTP API. This helps prevent injection attacks.

Subqueries

You can use native variables to pass an FQL query to another FQL query. This lets you create reusable subqueries:

// Create a reusable FQL subquery
const getProduct = name => {
  return fql`Product.byName(${name}).first()`
}

// Use the subquery in another FQL query
const query = fql`
  let product = ${getProduct("pizza")}
  product?.update({
    name: "pizza pie"
  })`;

client.query(query);

Pagination

Use paginate() to iterate a set that contains more than one page of results. paginate() accepts the same Query options as query().

// Adjust `pageSize()` size as needed.
const query = fql`
  Product.sortedByPriceLowToHigh()
    .pageSize(2)`;

const pages = client.paginate(query);

for await (const products of pages) {
  for (const product of products) {
    console.log(product)
    // ...
  }
}

Use flatten() to get paginated results as a single, flat array:

const pages = client.paginate(query);

for await (const product of pages.flatten()) {
  console.log(product)
}

Query statistics

Successful query responses and ServiceError errors include query statistics:

try {
  const response = await client.query(fql`"Hello world"`);
  console.log(response.stats);

} catch (error) {
  if (error instanceof ServiceError) {
    const info = error.queryInfo;
    const stats = info.stats;
  }
}

Output:

{
  compute_ops: 1,
  read_ops: 0,
  write_ops: 0,
  query_time_ms: 0,
  contention_retries: 0,
  storage_bytes_read: 0,
  storage_bytes_write: 0,
  rate_limits_hit: [],
  attempts: 1
}

TypeScript support

The driver supports TypeScript. For example, you can apply a type parameter to your FQL query results:

import { fql, Client, type QuerySuccess } from "fauna";

const client = new Client();

type User = {
  name: string;
  email: string;
};

const query = fql`{
  name: "Alice",
  email: "alice@site.example",
}`;

const response: QuerySuccess<User> = await client.query<User>(query);
const user_doc: User = response.data;

console.assert(user_doc.name === "Alice");
console.assert(user_doc.email === "alice@site.example");

.d.ts files for Fauna type definitions are available in the fauna package’s /dist folder.

Client configuration

The Client instance comes with reasonable configuration defaults. We recommend using the defaults in most cases.

If needed, you can configure the client to override the defaults. This also lets you set default Query options.

import { Client, endpoints } from "fauna";

const config = {
  // Configure the client
  client_timeout_buffer_ms: 5000,
  endpoint: endpoints.default,
  fetch_keepalive: false,
  http2_max_streams: 100,
  http2_session_idle_ms: 5000,
  secret: "YOUR_FAUNA_SECRET",

  // Set default query options
  format: "tagged",
  linearized: false,
  long_type: "number",
  max_attempts: 3,
  max_backoff: 20,
  max_contention_retries: 5,
  query_tags: { name: "hello world query" },
  query_timeout_ms: 60_000,
  traceparent: "00-750efa5fb6a131eb2cf4db39f28366cb-000000000000000b-00",
  typecheck: true,
};

const client = new Client(config);

The following table outlines supported properties for the configuration object and their defaults. In TypeScript, this object uses the ClientConfiguration type.

Property Type Required Description

client_timeout_buffer_ms

number

Additional time, in milliseconds, beyond the query timeout for the driver to abort if no response is received. Used to account for network latency. Defaults to 5000 (5 seconds).

If a client timeout occurs, the driver throws an instance of NetworkError.

endpoint

string

URL for the Fauna endpoint. Defaults to the FAUNA_ENDPOINT environment variable. If FAUNA_ENDPOINT is not set, defaults to endpoints.default (https://db.fauna.com).

fetch_keepalive

boolean

If true, requests from the client include the HTTP Keep-Alive header. Defaults to false.

http2_max_streams

number

Maximum number of concurrent HTTP/2 streams per session. Defaults to 100.

http2_session_idle_ms

number

Maximum amount of time, in milliseconds, an idle HTTP/2 connection remains open before closing. Defaults to 5000 (5 seconds).

This setting only applies to clients using HTTP/2, such as the default client for Node.js runtimes.

Do not set http2_session_idle_ms to a small value. This can lead to a race condition where requests can’t be transmitted before the session is closed, causing ERR_HTTP2_GOAWAY_SESSION errors. Instead, call close() in your application code after all requests complete.

secret

string

Yes

Fauna key, access token, or JWT used to authorize requests. Defaults to the FAUNA_SECRET environment variable.

format

string

Format used to encode and parse Fauna values in requests and responses. Accepts tagged and simple. Defaults to tagged.

Except in rare cases, you should use tagged. See Value encoding.

Maps to the x-format HTTP header.

linearized

boolean

If true, queries from the client are linearized, ensuring strict serialization of reads and writes. Defaults to false.

long_type

string

JavaScript data type used to deserialize Long numbers from Fauna. Accepts number and bigint. Defaults to number.

max_attempts

number

Maximum number of retry attempts for a query. Defaults to 3, including the initial attempt.

To disable retries, pass a max_attempts argument of 1 or less.

max_backoff

number

Maximum time, in seconds, to wait before retrying a query if the request returns a 429 HTTP status code. Defaults to 20 (20 seconds).

max_contention_retries

number

Maximum number of times Fauna retries a query after a contention error. These are server-side retries. Defaults to 0 (no retries).

query_tags

object

Key-value tags used to identify the query.

Query tags are included in query logs and the response body for successful queries. The tags are typically used for monitoring.

query_timeout_ms

number

Maximum amount of time, in milliseconds, Fauna runs a query before returning a 503 Timeout error. Defaults to 5000 (5 seconds).

If a query timeout occurs, the driver throws an instance of QueryTimeoutError.

traceparent

string

W3C-compliant traceparent ID for the request. If you provide an invalid traceparent ID, Fauna generates a valid one. Defaults to null (none).

The traceparent ID is included in query logs. Traceparent IDs are typically used for monitoring.

typecheck

boolean

If true, enables type checking for queries. Defaults to the database’s type checking setting.

If true, type checking must be enabled on the database.

Environment variables

By default, secret and endpoint default to the respective FAUNA_SECRET and FAUNA_ENDPOINT environment variables.

For example, if you set the following environment variables:

export FAUNA_SECRET=YOUR_FAUNA_SECRET
export FAUNA_ENDPOINT=https://db.fauna.com/

You can initialize the client with a default configuration:

const client = new Client();

Retries

By default, the client automatically retries a query if the request returns a 429 HTTP status code. Retries use an exponential backoff.

Use the Client configuration's max_backoff property to set the maximum time between retries. Similarly, use max_attempts to set the maximum number of retry attempts.

Query options

The Client configuration sets default query options for the following methods:

  • query()

  • paginate()

You can pass an options object to override these defaults:

const options = {
  arguments: { name: "Alice" },
  format: "tagged",
  linearized: false,
  long_type: "number",
  max_contention_retries: 5,
  query_tags: { name: "hello world query" },
  query_timeout_ms: 60_000,
  traceparent: "00-750efa5fb6a131eb2cf4db39f28366cb-000000000000000b-00",
  typecheck: true,
};

client.query(fql`"Hello, #{name}!"`, options);

The following table outlines supported properties for the query options object. In TypeScript, this object uses the QueryOptions type.

Property Type Required Description

arguments

object

Arguments to pass to the query for variable interpolation.

format

string

Format used to encode and parse Fauna values in requests and responses. Accepts tagged and simple. Defaults to tagged.

Except in rare cases, you should use tagged. See Value encoding.

Maps to the x-format HTTP header.

linearized

boolean

If true, queries from the client are linearized, ensuring strict serialization of reads and writes.

long_type

string

JavaScript data type used to deserialize Long numbers from Fauna. Accepts number and bigint.

max_contention_retries

number

Maximum number of times Fauna retries a query after a contention error. These are server-side retries.

query_tags

object

Key-value tags used to identify the query.

Query tags are included in query logs and the response body for successful queries. The tags are typically used for monitoring.

query_timeout_ms

number

Maximum amount of time, in milliseconds, Fauna runs a query before returning a 503 Timeout error. Defaults to 5000 (5 seconds).

If a query timeout occurs, the driver throws an instance of QueryTimeoutError.

traceparent

string

W3C-compliant traceparent ID for the request. If you provide an invalid traceparent ID, Fauna generates a valid one. Defaults to null (none).

The traceparent ID is included in query logs. Traceparent IDs are typically used for monitoring.

typecheck

boolean

If true, enables type checking for queries. Defaults to the database’s type checking setting.

If true, type checking must be enabled on the database.

Event Streaming

The driver supports Event Streaming.

Start a stream

To get a stream token, append toStream() or changesOn() to a set from a supported source.

To start and subscribe to the stream, pass the stream token to stream():

const response = await client.query(fql`
  let set = Product.all()

  {
    initialPage: set.pageSize(10),
    streamToken: set.toStream()
  }
`);
const { initialPage, streamToken } = response.data;

client.stream(streamToken)

You can also pass a query that produces a stream token directly to stream():

const query = fql`Product.all().changesOn(.price, .quantity)`

client.stream(query)

Iterate on a stream

You can iterate on the stream using an async loop:

try {
  for await (const event of stream) {
    switch (event.type) {
      case "update":
      case "add":
      case "remove":
        console.log("Stream event:", event);
        // ...
        break;
    }
  }
} catch (error) {
  // An error will be handled here if Fauna returns a terminal, "error" event, or
  // if Fauna returns a non-200 response when trying to connect, or
  // if the max number of retries on network errors is reached.

  // ... handle fatal error
}

Or you can use a callback function:

stream.start(
  function onEvent(event) {
    switch (event.type) {
      case "update":
      case "add":
      case "remove":
        console.log("Stream event:", event);
        // ...
        break;
    }
  },
  function onFatalError(error) {
    // An error will be handled here if Fauna returns a terminal, "error" event, or
    // if Fauna returns a non-200 response when trying to connect, or
    // if the max number of retries on network errors is reached.

    // ... handle fatal error
  }
);

Close a stream

Use close() to close a stream:

const stream = await client.stream(fql`Product.all().toStream()`)

let count = 0;
for await (const event of stream) {
  console.log("Stream event:", event);
  // ...
  count++;

  // Close the stream after 2 events
  if (count === 2) {
    stream.close()
    break;
  }
}

Stream options

The Client configuration sets default options for the stream() method.

You can pass an options object to override these defaults:

const options = {
  long_type: "number",
  max_attempts: 5,
  max_backoff: 1000,
  secret: "YOUR_FAUNA_SECRET",
  status_events: true,
};

client.stream(fql`Product.all().toStream()`, options)

The following table outlines supported properties for the stream options object. In TypeScript, this object uses the StreamClientConfiguration type.

Property Type Required Description

long_type

string

JavaScript data type used to deserialize Long numbers from Fauna. Accepts number and bigint.

max_attempts

number

Maximum number of retry attempts for a query. Defaults to 3, including the initial attempt.

To disable retries, pass a max_attempts argument of 1 or less.

max_backoff

number

Maximum time, in seconds, to wait before retrying a query if the request returns a 429 HTTP status code. Defaults to 20 (20 seconds).

secret

string

Fauna key, access token, or JWT used to authorize requests.

status_events

boolean

If true, the stream includes periodic status events. These events are sent when a stream starts or reconnects. They’re also periodically sent to:

  • Keep the client connection open.

  • Send stats on operations consumed by event processing, including discarded events that aren’t sent.

Defaults to false.

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!