Model or dataset
rivet-dev/actors avatar
rivet-dev/actors

Rivet Actors: stateful workloads as long-running processes

Rivet Actors are the primitive for stateful workloads. Built for AI agents, collaborative apps, and durable execution.

6,207 stars260 forksRustApache-2.0

At a glance

What is it?
Rivet Actors is an Apache-2.0 Rust project that turns stateful workloads into long-running, lightweight processes with in-memory state, queues, WebSockets and workflows. The design is coherent, the documentation is thinner than the feature list, and the comparison table deserves scrutiny.
Who is it for?
Reach for Rivet Actors when you are building AI agents, collaborative documents, chat rooms or per-tenant state and you want one primitive instead of a queue, a cache and a database stitched together. Skip it if you need a stable 1.0 API contract, if your team has no Rust or TypeScript experience, or if a single Postgres instance already handles your concurrency.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem Rivet Actors solves, and who it is for

Most stateful backends end up as three systems pretending to be one. A queue holds the work, Redis or Postgres holds the state, and a WebSocket layer pushes changes to clients. Each boundary is a place where state can diverge from the work in flight. Rivet Actors collapses that into a single primitive: a long-running process that owns its state in memory, persists it automatically, and can broadcast to connected clients.

The README states the target plainly: one actor per agent, per session, or per user. The use cases it lists are AI agents with persistent context, sandbox orchestration, multi-step workflows, collaborative documents, per-tenant databases and chat rooms. Those workloads share a shape. They are long-lived, they are bursty, and they need low-latency reads of state that was just written.

The audience is narrower than the feature list suggests. The repository is a Rust workspace with TypeScript, Python, Swift and Rust actor SDKs under rivetkit-typescript, rivetkit-python, rivetkit-swift and rivetkit-rust. This is aimed at teams comfortable running a multi-language build and a self-hosted engine, not at someone who wants a single npm install and a hosted dashboard.

How an actor holds state, queues and WebSocket clients

The README's backend example is the clearest description of the mechanism. You declare an actor with a state object and a run function. The state is described as in-memory and persisted. The run function is a long-running process, and inside it the README shows a loop over c.queue.iter(), which yields incoming messages. Each message is appended to c.state.messages, passed to a model call, and the streaming deltas are pushed out with c.broadcast("token", delta). The client side connects with client.agent.getOrCreate("agent-123").connect(), subscribes with agent.on("token", ...), and sends work with agent.queue.send(...).

That data flow is the whole architecture in miniature. The queue is the ingress, the in-memory state is the working set, the broadcast is the egress, and persistence happens underneath without the run loop managing it. The README also states that actors hibernate when idle and run indefinitely when active, which is what makes the per-user or per-session granularity affordable.

The repository layout backs this up. There is an engine/ directory with packages named pegboard, gasoline, depot, guard and runtime, plus a container-runner/ member and a self-host/ directory. The Cargo.toml workspace lists these explicitly. What the README does not document is the persistence format, the failure semantics of a queue message that is delivered but not acknowledged, or what happens to in-flight broadcasts when an actor hibernates mid-stream. Those are the questions I would want answered before putting a chat room on it.

Installing Rivet Actors and running a first actor

The README does not include install commands. It points to https://www.rivet.dev/docs for the quickstart and https://www.rivet.dev/docs/actors for actor documentation, so that is where setup instructions live. What the repository does give you is the workspace tooling and the self-host path.

The root package.json declares pnpm as the package manager and requires Node 20 or newer. The start script runs a Turbo watch build:

bash
pnpm install
pnpm start

The justfile holds the Docker recipes for the engine. The docker-build recipe builds engine/docker/universal/Dockerfile with the engine-full target and tags it rivetdev/engine:local for linux/x86_64. The docker-run recipe starts it:

bash
docker run -p 6420:6420 -e RIVET__AUTH__ADMIN_TOKEN=dev -e RUST_LOG=debug rivetdev/engine:local

That exposes the engine on port 6420 with an admin token set to dev and debug logging enabled. The justfile also has docker-build-frontend, which passes BUILD_FRONTEND=true as a build argument if you want the frontend bundle included. Note that the docker-stop recipe in the justfile is a copy of docker-run, so it starts a second container rather than stopping one. Use docker stop against the container ID instead.

Once the engine is up, the actor code from the README is the first thing to write. The backend declares state and a run loop; the client connects, subscribes and sends:

typescript
const agent = actor({
  state: { messages: [] as Message[] },
  run: async (c) => {
    for await (const msg of c.queue.iter()) {
      c.state.messages.push({ role: "user", content: msg.body.text });
    }
  },
});
typescript
const agent = client.agent.getOrCreate("agent-123").connect();
agent.on("token", delta => process.stdout.write(delta));
await agent.queue.send("how many r's in strawberry?");

The README also mentions an Inspector with a SQLite viewer and workflow state inspection for local development through production. If the inspector ships with the engine image, it should be reachable once port 6420 is mapped.

Where Rivet Actors is the wrong tool

The README's comparison table is the part to read skeptically. It claims roughly 20ms cold start, about 0.6KB of memory per instance, zero idle cost, infinite horizontal scale and 0ms read latency, against Kubernetes pods, virtual machines, Redis and Postgres. The methodology is disclosed in a collapsed section, which is more than most projects do, but the numbers are measured on the project's own harness with Node.js and FoundationDB, and the "infinite" scale figure is a design property rather than a measured ceiling.

The real limitation is different. An actor model is a poor fit when your workload is a small number of high-throughput request handlers with no per-entity state. Spinning up an actor per request to run a stateless query adds a lifecycle you do not need. It is also a poor fit when your state must be queried relationally across entities. The README offers per-tenant databases and says you can persist with SQLite or bring your own database, but cross-actor queries are not something the README describes.

The operational cost is another boundary. The repository is a large Rust workspace with a container runner, a self-host directory and dozens of engine packages. If your team cannot build and operate that, the managed path at rivet.dev is the realistic option, and then you are depending on a hosted service rather than the Apache-2.0 code. The README does not document rollback, migration between engine versions, or what happens to persisted actor state during an upgrade.

Rivet Actors compared with Cloudflare Durable Objects

The repository topics list cloudflare and cloudflare-durable-objects, so the comparison is invited. The approaches differ in where the runtime lives and who operates it. Durable Objects are a Cloudflare product: the object runtime, storage and routing are part of Cloudflare's platform, and you deploy Workers. Rivet Actors is Apache-2.0 code in this repository, with a self-host directory and an engine Dockerfile you can build yourself, and the README describes a global edge network as a deployment option rather than a requirement.

That difference cuts both ways. Self-hosting means you own the engine, the FoundationDB or SQLite persistence layer, the container runner and the upgrades. It also means your actor state is not tied to one vendor's account, and you can run in a specific legal jurisdiction, which the README calls out as a feature. Cloudflare's version gives you less to operate and less to control.

The programming model is close enough that porting is plausible but not free. The README's actor shape (state, run, queue, broadcast, connect, on) is its own API, and the repository ships separate SDKs per language, so the surface you write against is Rivet's, not Cloudflare's.

Licence, release cadence and upgrade cost

The repository is licensed Apache-2.0, with the LICENSE file at the top level. That permits commercial use, modification and redistribution, and it includes a patent grant. It does not give legal advice, and if you are embedding the engine in a product you should read the file and the NOTICE requirements yourself rather than take this paragraph as counsel.

Release cadence is fast. The most recent releases are v2.3.16 on 2026-09-09, preceded by v2.3.16-rc.3 and v2.3.16-rc.2 on the same day, and the last push to main was on 2026-09-10. A 2.3.x line with release candidates published hours before the final tag tells you the project moves quickly and that pinning a version matters. The repository includes CHANGELOG.md at the top level, and the README links to https://www.rivet.dev/changelog as well. Read one of those before upgrading, because the README does not describe a migration tool for persisted actor state.

The upgrade cost has two parts. The engine is a Rust workspace with many internal packages, so rebuilding and redeploying is a real operation, not a restart. The SDKs are versioned alongside it, and the root package.json resolves rivetkit, @rivetkit/react, @rivetkit/next-js, @rivetkit/cloudflare-workers, @rivetkit/supabase and @rivetkit/db as workspace dependencies, which means an engine upgrade can pull SDK changes with it.

Editorial conclusion

Reach for Rivet Actors when you are building AI agents, collaborative documents, chat rooms or per-tenant state and you want one primitive instead of a queue, a cache and a database stitched together. Skip it if you need a stable 1.0 API contract, if your team has no Rust or TypeScript experience, or if a single Postgres instance already handles your concurrency. Before committing, verify two things: whether the self-host path in self-host/ and the engine Dockerfile at engine/docker/universal/Dockerfile are production-grade for your deployment, and whether the actor runtime you depend on (rivetkit-typescript, rivetkit-rust, rivetkit-python or rivetkit-swift) is the one the docs cover in depth. The repository pushes frequently and releases on a 2.3.x line, so pin a version and read CHANGELOG.md before upgrading rather than tracking main.

Frequently asked questions

What is Rivet Actors?

Rivet Actors is a primitive for stateful workloads, described in the README as long-running, lightweight processes where state lives in memory with automatic persistence. It is built for AI agents, collaborative apps and durable execution, and it ships as an Apache-2.0 Rust workspace with actor SDKs for TypeScript, Rust, Python and Swift.

How do you set up Rivet Actors?

The README does not include install steps; it points to https://www.rivet.dev/docs for the quickstart. The repository provides the self-host path through the justfile, where docker-build builds engine/docker/universal/Dockerfile with the engine-full target and docker-run starts it on port 6420 with RIVET__AUTH__ADMIN_TOKEN=dev.

How do you work with Rivet Actors queues and WebSocket clients?

The README's example declares an actor with a state object and a run function, loops over c.queue.iter() to process incoming messages, and pushes updates to clients with c.broadcast("token", delta). Clients connect with client.agent.getOrCreate("agent-123").connect(), listen with agent.on("token", ...) and send work with agent.queue.send(...).

Official sources

  1. License: Apache-2.0
  2. Project website
  3. README
  4. Releases
  5. rivet-dev/actors on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/rivet-dev-actors.svg)](https://hysenlabs.com/projects/rivet-dev-actors)