Skip to content
English

Installation

actor-ts ships as a single npm package. The core has two small runtime dependencies (ts-pattern for exhaustive matching, fastify for the default HTTP backend); everything else — Kafka, Redis, S3, Cassandra, gRPC — is opt-in via peer dependencies you only install when you use the corresponding extension.

RuntimeMinimum versionNotes
Bun1.3Recommended for development — fastest startup, native SQLite via bun:sqlite, native WebSocket server.
Node.js24.0Ships everything natively: WebSocket client, zstd compression, WebCrypto, fetch. SQLite via the built-in node:sqlite, or better-sqlite3 if you install it.
Deno2.2Use the npm: specifier — import { ... } from 'npm:actor-ts'. Run with --allow-net / --allow-read as needed. SQLite needs Deno 2.2 for node:sqlite; everything else works on 2.0.

The framework auto-detects which runtime it’s executing under and picks the right backends transparently — see Runtime overview for the detection algorithm and per-runtime caveats.

Terminal window
bun add actor-ts

Each integration is gated by a peer dep — install only the ones you’ll actually use. Nothing is auto-loaded; the relevant extension throws a clear “missing peer dep” error if you try to use it without the package installed.

PackageEnables
fastify (default)Fastify-based HttpServerBackend — best Bun + Node performance.
expressExpress-based backend, for projects already on Express.
hono + @hono/node-server (Node only)Hono with runtime-aware serve primitives — Bun.serve, @hono/node-server, Deno.serve per runtime.
Terminal window
bun add fastify # or
bun add express # or
bun add hono @hono/node-server # @hono/node-server is Node-only
PackageEnables
(none needed)SQLite journal + snapshot store. Every runtime has a built-in driver: bun:sqlite on Bun, node:sqlite on Node >= 22.13 and Deno >= 2.2.
better-sqlite3 (Node only, optional)Preferred over node:sqlite on Node when installed — slightly faster, and what existing deployments already run.
@libsql/clientlibSQL / Turso journal + snapshot + durable-state store — SQLite over HTTP, so it needs no native binding on any runtime.
pgPostgreSQL journal + snapshot + durable-state store.
mariadbMariaDB / MySQL journal + snapshot + durable-state store.
mssqlMicrosoft SQL Server journal + snapshot + durable-state store. Pure-JavaScript driver (tedious), no native build step.
mongodb (pin ^6)MongoDB journal + snapshot + durable-state store + indexed tag query. Version 7 cannot be imported on Bun — see the MongoDB page.
cassandra-driverCassandra / ScyllaDB journal + tag-index.
@aws-sdk/client-s3S3-compatible object-storage backend (works with MinIO, R2, Backblaze B2).
@aws-sdk/client-dynamodbDynamoDB journal + snapshot + durable-state store.
(none needed)Cloudflare D1 journal + snapshot + durable-state store — spoken over D1’s REST API with the built-in HTTP client.
fzstd (optional)zstd compression for object-storage blobs when no native runtime support is available.
PackageEnables
ioredisRedis-backed Cache.
memjsMemcached-backed Cache.
PackageEnables
kafkajsKafkaActor — producer + consumer.
mqttMqttActor.
amqplibAmqpActor — RabbitMQ + AMQP-compatible brokers.
natsNatsActor — including JetStream subjects.
@grpc/grpc-js + @grpc/proto-loaderGrpcClientActor + GrpcServerActor.
wsServer-side WebSocket upgrades on the Express backend. (WebsocketClientActor uses the runtime’s native WebSocket — no peer dep.)
@fastify/websocketwebsocket() routes on the Fastify backend.
@hono/node-wswebsocket() routes on the Hono backend (Node only — Bun/Deno ship the helpers inside hono).

KubernetesApiSeedProvider and KubernetesLease need no peer dependency — both reach the Kubernetes API over built-in node:https + node:fs, using the in-pod ServiceAccount token by default.

PackageEnables
@kubernetes/client-node (optional)Not required. Optional swap-in for KubernetesApiSeedProvider’s fetchEndpoints hook, if you’d rather use the official client than the built-in HTTPS call.

Add (or verify) the following compiler options in your tsconfig.json:

{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "Bundler",
"strict": true,
"noImplicitOverride": true,
"exactOptionalPropertyTypes": true,
"skipLibCheck": true
}
}

The framework relies on noImplicitOverride to catch lifecycle-method- typo bugs (writing onRecieve instead of onReceive). Drop it if you prefer, but you’ll lose that safety net.

Save this as verify.ts:

import { Actor, ActorSystem } from 'actor-ts';
class Ping extends Actor<'ping'> {
override onReceive(message: 'ping'): void {
console.log('pong');
}
}
const system = ActorSystem.create('verify');
const ref = system.spawnAnonymous(Ping);
ref.tell('ping');
await new Promise((r) => setTimeout(r, 20));
await system.terminate();
console.log('install OK');
Terminal window
bun run verify.ts

Expected output:

pong
install OK

If you see both lines, the install is working. If pong is missing, your runtime is below the minimum version (see the table at the top of this page) — bump it and re-run.

  • Quickstart — five minutes to a running actor.
  • Why actors? — the philosophy behind the framework.
  • Learning path — suggested reading order based on what you want to build.