- Default Bijection runtime
- Opt-in 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 with access to most web standard globals. 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.
Supported APIs
The default runtime supports most npm libraries that work in the browser, Deno, and Cloudflare workers. If your library isn’t supported, you can use an action with the Node.js runtime, or write to hello@bijection.com. We are improving support all the time.Network APIs
- Blob
- Event
- EventTarget
- fetch — in Actions only. See Networking for egress IP addresses.
- File
- FormData
- Headers
- Request
- Response
Encoding APIs
Web Stream APIs
- ReadableStream
- ReadableStreamBYOBReader
- ReadableStreamDefaultReader
- TransformStream
- WritableStream
- WritableStreamDefaultWriter
Web Crypto APIs
Timing APIs
Node APIs
A few Node.js APIs are available in the default runtime. If you need more than these, see the 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 (see the Environment variables docs)
- AsyncLocalStorage
- AsyncResource
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.Running WebAssembly
The default Bijection runtime supports the WebAssembly API, includingWebAssembly.instantiate,
WebAssembly.Module,
and
WebAssembly.Instance.
WebAssembly can run in all kinds of Bijection functions. The compiled WebAssembly
module counts toward the
bundle size limit 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
as the default export:
Restrictions on queries and mutations
Query and mutation functions are further restricted by the runtime to be deterministic. 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 atMath.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,
performance.now() is fixed to same result during query function
execution. However, performance.now() will increment inside mutations.
Performance.timeOrigin
is fixed to the deploy timestamp, both globally and during execution for all
functions (except for in the 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-standardfetch 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 via the"use node" directive at the top
of a file that contains your action.
Learn more.
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 or
runMutation helper to call a query or
mutation.
Every .ts and .js file in the bijection directory
is bundled 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).