WASM vs Native SDK
RivetKit runs your actors on a native or a WebAssembly runtime depending on your platform.
RivetKit ships two runtimes for executing actor logic. Most projects use the native runtime automatically. Edge and serverless platforms that cannot run native binaries use the WebAssembly runtime.
- Native: Default. Runs on Node.js and Bun via native bindings. Best performance.
- WebAssembly (wasm): Runs anywhere a
WebAssembly.Modulecan be instantiated, including Cloudflare Workers, Supabase Edge Functions, and Deno Deploy.
Native runtime
The native runtime is the default and requires no configuration. It loads platform-specific native bindings for the best performance and full feature support on Node.js and Bun.
import { actor, setup } from "rivetkit";
const counter = actor({ state: { count: 0 }, actions: {} });
const registry = setup({ use: { counter } });
WebAssembly runtime
Edge platforms run on isolates (V8, Deno) that cannot load native binaries, so
RivetKit provides a WebAssembly build of its core runtime in the
@rivetkit/rivetkit-wasm package. You select it with runtime: "wasm" and pass
the wasm bindings and binary through the wasm option.
Recommended: use a platform package
For supported platforms, use the dedicated package instead of wiring the wasm runtime by hand. They install the wasm runtime, load the binary, and (on Cloudflare) provide the outbound WebSocket the engine tunnel needs.
- Cloudflare Workers:
@rivetkit/cloudflare-workers - Supabase Edge Functions:
@rivetkit/supabase
// Cloudflare Workers
import { actor } from "rivetkit";
import { createHandler } from "@rivetkit/cloudflare-workers";
const counter = actor({ state: { count: 0 }, actions: {} });
export default createHandler({ use: { counter } });
Manual configuration
For platforms without a dedicated package, configure the wasm runtime directly.
Pass the bindings from @rivetkit/rivetkit-wasm and the wasm binary as
initInput. initInput accepts a Uint8Array, URL, Response, or a
WebAssembly.Module.
import { actor, setup } from "rivetkit";
import * as wasmBindings from "@rivetkit/rivetkit-wasm";
import wasmModule from "@rivetkit/rivetkit-wasm/rivetkit_wasm_bg.wasm";
const counter = actor({ state: { count: 0 }, actions: {} });
const registry = setup({
runtime: "wasm",
wasm: { bindings: wasmBindings, initInput: wasmModule },
use: { counter },
});
On platforms without an outbound new WebSocket(url) constructor (such as
Cloudflare Workers), you must also install a fetch-based globalThis.WebSocket
shim so the actor can open its tunnel to the engine. The platform packages handle
this for you, which is why they are recommended.