Quickstart
Five minutes from “what’s an actor” to “I have one running, sending and receiving messages.” This guide assumes no prior actor-model experience.
What you’ll have at the end
Section titled “What you’ll have at the end”A small program that creates an ActorSystem, spawns a single Greeter
actor inside it, sends the actor a message, and shuts down. The same file
runs unchanged under Bun, Node, and Deno — picking the right runtime
backend automatically.
After this guide you’ll know:
- How to define an actor by extending
Actor<T>. - How to spawn it via
system.actorOf(Props.create(...)). - The difference between
tell(fire-and-forget) and the actor’sonReceivehandler. - How to shut the system down without leaking timers or sockets.
Install
Section titled “Install”bun add actor-tsnpm install actor-tsNo install step. Import directly from npm:
import { Actor, ActorSystem, Props } from 'npm:actor-ts';Run with --allow-net (for the TCP cluster transport) and
--allow-read (for reading config files) when you need them.
For a full installation walkthrough — including optional peer dependencies
(better-sqlite3, @hono/node-server, broker clients) — see the
Installation page.
Hello, actor
Section titled “Hello, actor”Create hello.ts and paste:
import { Actor, ActorSystem, Props } from 'actor-ts';
// 1. Define an actor. The type parameter `<string>` constrains what// messages this actor accepts — the type system catches bad sends// at compile time.class Greeter extends Actor<string> { override onReceive(name: string): void { console.log(`hello, ${name}!`); }}
// 2. Create the system. One `ActorSystem` per process is the norm;// everything else lives inside it.const system = ActorSystem.create('hello');
// 3. Spawn the actor. `Props.create(() => new Greeter())` is the// factory; `'greeter'` is the actor's name in the hierarchy.const ref = system.actorOf(Props.create(() => new Greeter()), 'greeter');
// 4. Send a message. `tell` is fire-and-forget — it returns// immediately, the actor processes the message asynchronously on// its own mailbox.ref.tell('world');
// 5. Give the mailbox a tick to drain, then shut down. In a real// app you'd terminate on SIGTERM via `CoordinatedShutdown`; for// this script a short sleep is enough.await new Promise((resolve) => setTimeout(resolve, 20));await system.terminate();Run it:
bun run hello.tsnpx tsx hello.ts# or compile first: tsc hello.ts && node hello.jsdeno run hello.tsYou’ll see:
hello, world!That’s the whole loop: define → spawn → tell → terminate.
What just happened
Section titled “What just happened”The five lines map to the actor model’s five core ideas:
-
class Greeter extends Actor<string>— an actor is a class with a private mailbox and a singleonReceivehandler. The type parameter says “this actor acceptsstringmessages” — sending it a number would be a TypeScript error at compile time. -
ActorSystem.create('hello')— theActorSystemis the runtime container. It owns the dispatcher (which schedules message processing), the supervisor hierarchy (which catches actor failures), the scheduler, the event stream. There’s typically one per process. -
system.actorOf(Props.create(() => new Greeter()))—Propsis actor-ts’s way to defer construction. The system needs to control when the actor instance is created (on its mailbox thread, not on yours), so you hand it a factory rather than a pre-built instance. The returnedActorRefis a handle, not the actor itself — you can pass it across the cluster, store it, hand it to other actors. -
ref.tell('world')—tellis the primary actor verb. It enqueues the message into the actor’s mailbox and returns immediately. The actor processes its mailbox one message at a time on a single logical thread, so you never have to think about locks or races insideonReceive. -
system.terminate()— graceful shutdown. Stops the dispatcher, stops all actors (via the supervisor tree), closes the transports. Returns a promise that resolves when teardown is complete. For real apps, hook this into a SIGTERM handler — see Coordinated shutdown.
Where to next
Section titled “Where to next”You have a running actor. From here the docs branch out depending on what you want to do:
- Send more interesting messages: see Messages
for the conventions (discriminated unions, immutability, the
kindfield) and Pattern matching for thematch().exhaustive()dispatch idiom this codebase uses everywhere. - Get a reply back from the actor: see Ask pattern
— the request/response equivalent of
tell. - Handle failures: see Supervision for how parent actors recover from child crashes.
- Distribute across machines: see the Cluster overview and Sharding overview — the same code you wrote above can run across N nodes with a few extra lines of configuration.
- Persist state across restarts: see PersistentActor for event sourcing and Snapshots for bounded recovery time.
If you want to see the framework’s whole surface area at once, the chat sample is the most-comprehensive end-to-end demonstration — it uses sharding, persistence, distributed pubsub, distributed data, cluster singleton, HTTP routing, six interchangeable frontends, the lot.