> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bijection.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Runtimes

> Learn the differences between the Bijection and Node.js runtimes for functions

Bijection functions can run in two runtimes:

* Default [Bijection runtime](#default-bijection-runtime)
* Opt-in [Node.js runtime](#node-js-runtime)

## Default Bijection runtime

All Bijection backend functions are written in JavaScript or TypeScript. By default
all functions run in a custom JavaScript runtime very similar to the
[Cloudflare Workers runtime](https://blog.cloudflare.com/cloud-computing-without-containers/)
with access to most
[web standard globals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects).

The default runtime has many advantages including:

* **No cold starts**. The runtime is always up, and ready to handle any function
  at a moments notice.
* **Latest web JavaScript standards**. The runtime is based on V8 that also
  powers Google Chrome. This ensures it provides an interface very similar to
  your frontend code, allowing further simplification to your code.
* **Low overhead access to your data**. The runtime is designed to have low
  overhead access to your data via query & mutation functions, allowing you to
  access your database via a simple
  [JavaScript interface](/database/reading-data/reading-data).

### Supported APIs

The default runtime supports most npm libraries that work in the browser,
[Deno](https://deno.com/), and
[Cloudflare workers](https://developers.cloudflare.com/workers/). If your
library isn't supported, you can use an action with the
[Node.js runtime](#node-js-runtime), or write to
[hello@bijection.com](mailto:hello@bijection.com). We are improving support all the time.

#### Network APIs

* [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob)
* [Event](https://developer.mozilla.org/en-US/docs/Web/API/Event)
* [EventTarget](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget)
* [fetch](https://developer.mozilla.org/en-US/docs/Web/API/fetch) — in
  [Actions](#actions) only. See [Networking](/production/networking) for
  egress IP addresses.
* [File](https://developer.mozilla.org/en-US/docs/Web/API/File)
* [FormData](https://developer.mozilla.org/en-US/docs/Web/API/FormData)
* [Headers](https://developer.mozilla.org/en-US/docs/Web/API/Headers)
* [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request)
* [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response)

#### Encoding APIs

* [TextDecoder](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder)
* [TextEncoder](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder)
* [atob](https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/atob)
* [btoa](https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/btoa)

#### Web Stream APIs

* [ReadableStream](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream)
* [ReadableStreamBYOBReader](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamBYOBReader)
* [ReadableStreamDefaultReader](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamDefaultReader)
* [TransformStream](https://developer.mozilla.org/en-US/docs/Web/API/TransformStream)
* [WritableStream](https://developer.mozilla.org/en-US/docs/Web/API/WritableStream)
* [WritableStreamDefaultWriter](https://developer.mozilla.org/en-US/docs/Web/API/WritableStreamDefaultWriter)

#### Web Crypto APIs

* [crypto](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API)
* [CryptoKey](https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey)
* [SubtleCrypto](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto)

#### Timing APIs

* [`performance.now()`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now)
* [Performance](https://developer.mozilla.org/en-US/docs/Web/API/Performance)
* [PerformanceEntry](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceEntry)
* [PerformanceMark](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceMark)
* [PerformanceMeasure](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceMeasure)

<Warning>
  Note that there are additional
  [restrictions](#using-randomness-and-time-in-queries-and-mutations) on the
  Performance API when used in queries.
</Warning>

#### Node APIs

A few Node.js APIs are available in the default runtime. If you need more than
these, see the [Node.js runtime](#node-js-runtime).

If you are using TypeScript, you may need to add a dev dependency on
`@types/node` to access these APIs. For TypeScript 6+ you'll also need to add
`"types": ["node"]` to your `bijection/tsconfig.json` file (if not already
present).

* [process.env](https://nodejs.org/api/process.html#processenv) (see the
  [Environment variables](/production/environment-variables) docs)
* [AsyncLocalStorage](https://nodejs.org/api/async_context.html#class-asynclocalstorage)
* [AsyncResource](https://nodejs.org/api/async_context.html#class-asyncresource)

<Note>
  Data in `AsyncLocalStorage` does not propagate into calls to `ctx.runMutation`,
  `ctx.runQuery` or `ctx.runAction`. If you want values to propagate into those
  calls, you'll need to manually pass them as arguments.
</Note>

### Running WebAssembly

The default Bijection runtime supports the
[WebAssembly API](https://developer.mozilla.org/en-US/docs/WebAssembly),
including
[`WebAssembly.instantiate`](https://developer.mozilla.org/en-US/docs/WebAssembly/Reference/JavaScript_interface/instantiate_static),
[`WebAssembly.Module`](https://developer.mozilla.org/en-US/docs/WebAssembly/Reference/JavaScript_interface/Module),
and
[`WebAssembly.Instance`](https://developer.mozilla.org/en-US/docs/WebAssembly/Reference/JavaScript_interface/Instance).
WebAssembly can run in all kinds of Bijection functions. The compiled WebAssembly
module counts toward the
[bundle size limit](/functions/bundling#code-size-limits) for your `bijection/`
directory.

You can instantiate a module from bytes at runtime, but the simplest way to get
a module is to import a `.wasm` file directly. The bundler compiles it and gives
you a
[`WebAssembly.Module`](https://developer.mozilla.org/en-US/docs/WebAssembly/Reference/JavaScript_interface/Module)
as the default export:

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
import wasmModule from "./add.wasm"; // a compiled WebAssembly.Module

const instance = await WebAssembly.instantiate(wasmModule, {});
const add = instance.exports.add as (a: number, b: number) => number;
add(1, 2); // 3
```

To import WebAssembly files from TypeScript, you will need to add an ambient
declaration so the import typechecks:

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
// bijection/wasm.d.ts
declare module "*.wasm" {
  const mod: WebAssembly.Module;
  export default mod;
}
```

### Restrictions on queries and mutations

Query and mutation functions are further **restricted by the runtime to be
[deterministic](https://en.wikipedia.org/wiki/Deterministic_algorithm)**. This
allows Bijection to automatically retry them by the system as necessary.

Determinism means that no matter how many times your function is run, as long as
it is given the same arguments, it will have identical side effects and return
the same value.

You don't have to think all that much about maintaining these properties of
determinism when you write your Bijection functions. Bijection will provide helpful
error messages as you go, so you can't *accidentally* do something forbidden.

#### Using randomness and time in queries and mutations

Bijection provides a "seeded" strong pseudo-random number generator
at `Math.random()` so that it can guarantee the determinism of your function.
The random number generator's seed is an implicit parameter to your function.
Multiple calls to `Math.random()` in one function call will return different
random values. However, a call to `Math.random()` stored in a global variable
will not change between function runs, because during import-time, the random
number generator's seed is fixed to a value set at the most recent deployment.

To ensure the logic within your function is reproducible, the system time used
globally (outside of any function) is "frozen" at deploy time, while the system
time during Bijection function execution is "frozen" when the function
begins. `Date.now()` will return the same result for the entirety of your
function's execution. For example,

```javascript theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
const globalRand = Math.random(); // `globalRand` does not change between runs.
const globalNow = Date.now(); // `globalNow` is the time when Bijection functions were deployed.

export const updateSomething = mutation({
  args: {},
  handler: () => {
    const now1 = Date.now(); // `now1` is the time when the function execution started.
    const rand1 = Math.random(); // `rand1` has a new value for each function run.
    // implementation
    const now2 = Date.now(); // `now2` === `now1`
    const rand2 = Math.random(); // `rand1` !== `rand2`
  },
});
```

Likewise, `performance.now()` is fixed to same result during query function
execution. However, `performance.now()` will increment inside mutations.
[`Performance.timeOrigin`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/timeOrigin)
is fixed to the deploy timestamp, both globally and during execution for all
functions (except for in the [Node.js runtime](#node-js-runtime)).

### Actions

Actions are unrestricted by the same rules of determinism as query and mutation
functions. Notably actions are allowed to call third-party HTTP endpoints via
the browser-standard
[`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) function.

By default actions also run in Bijection’s custom JavaScript runtime with all of
its advantages including no cold starts and a browser-like API environment. They
can also live in the same file as your query and mutation functions.

## Node.js runtime

Some JavaScript and TypeScript libraries use features that are not included in
the default Bijection runtime. Bijection actions provide an escape hatch to
[Node.js](https://nodejs.org/en/about) via the `"use node"` directive at the top
of a file that contains your action.
[Learn more](/functions/actions#choosing-the-runtime-use-node).

Use of the Node.js environment is restricted to **action functions only**. If
you want to use a library designed for Node.js and interact with the Bijection
database, you need to call the Node.js library from an action, and use
[`runQuery`](/functions/actions#action-context) or
[`runMutation`](/functions/actions#action-context) helper to call a query or
mutation.

Every `.ts` and `.js` file in the bijection directory
[is bundled](/functions/bundling) either for the default Bijection JavaScript
runtime or Node.js, along with any code it imports.

Files with the `"use node"` directive should not contain any Bijection queries or
mutations since they cannot be run in the Node.js runtime. Additionally, files
without the `"use node"` directive should not import any files with the
`"use node"` directive. Files that contain no Bijection functions, like a
`bijection/utils.ts` file, also need the "use node" directive if they use
Node.js-specific libraries.

If you encounter bundling errors about Node.js-specific imports like `fs` /
`node:fs` not being available when deploying bijection functions, running
`bijection dev --once --debug-node-apis` gives more information about these. It
uses a slower bundling method to track the train of imports, narrowing down
which import is responsible for the error.

Note that argument size limits are lower (5MiB instead of 16MiB).

### Node.js version configuration

By default, all actions ran in the Node.js environment are executed in
Node.js 20. This version is configurable in the
[bijection.json](/config/bijection-json#configuring-the-node-js-version) file. We
currently support Node.js 20, 22, and 24.

When pushing a new Node.js version to the server, the new code for your
functions may be executed in the old Node.js version for up a few minutes.

Note: This configuration is not supported when running the self-hosted Bijection
backend. The node version that is specified in the
.nvmrc will be
used instead.
