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

Rivet Actors: a stateful actor runtime that hibernates when idle

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

6,133 stars247 forksRustApache-2.0

At a glance

What is it?
Rivet Actors packages in-memory state, durable queues, workflows and WebSockets into one long-lived process per agent, session or tenant. The pitch is real, but the interesting parts are the storage choice and the cold-start caveat.
Who is it for?
Rivet Actors suits teams building per-agent, per-session or per-tenant stateful services in TypeScript or Rust who want queues and WebSockets without assembling Redis, Postgres and a workflow engine themselves. It is the wrong tool if you need sub-millisecond state reads across many actors on one machine, or if you cannot run FoundationDB, since the README's benchmark numbers assume it.
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 last received commits 1 day ago.
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 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The gap Rivet Actors fills: state that outlives the request

Most serverless runtimes throw away process memory between invocations. That is fine for a stateless HTTP handler and painful for anything that needs to remember a conversation. The usual workaround is to bolt on Redis for hot state and Postgres for durable state, then write the glue that keeps them consistent. Rivet Actors takes the opposite position: state lives in memory inside a long-running process, and persistence happens underneath it. The README describes actors as "long-running, lightweight processes designed for stateful workloads" with state that is "in-memory with automatic persistence". The stated unit of deployment is one actor per agent, per session, per user or per tenant. That framing tells you who this is for. If you are building an AI agent that accumulates message history, a collaborative document that broadcasts edits, or a per-tenant data store that needs low-latency reads, the actor model maps onto your problem without a translation layer. If you are building a stateless API gateway, it does not.

How the actor loop actually works in the TypeScript example

The README's backend example is short enough to read in one pass, and it shows the whole mechanism. An actor is declared with an object containing a state field and a run function. The state field is typed, in the example an array of messages. The run function receives a context object and, in the sample, enters a for-await loop over c.queue.iter(). Each iteration pulls one message off a durable queue. The handler appends the user message to c.state.messages, calls a streaming model, and for each token in the response calls c.broadcast("token", delta). Broadcast pushes a realtime event to every connected client. When the stream ends, the assistant reply is appended to the same in-memory array. The client side mirrors this: client.agent.getOrCreate("agent-123").connect() obtains a handle, agent.on("token", ...) subscribes to the stream, and agent.queue.send(...) enqueues work. Two things are worth noting. First, the queue is the entry point for all work, so the actor loop is a consumer, not an RPC handler; ordering and backpressure are properties of the queue. Second, state mutation and broadcast happen in the same loop iteration, so the persistence boundary is not visible in application code. The README does not specify when the in-memory state is flushed to SQLite, which is the single most important thing to pin down before trusting this with data you cannot lose.

Running it: what the README actually gives you

This is where the supplied material runs thin. The README links to a Quickstart at rivet.dev/docs and points at the documentation site, but it does not inline install commands, a CLI invocation, a config file format or environment variable names. The only runnable artifacts shown are the two TypeScript snippets: the actor definition and the client connection. What can be confirmed from the repository metadata is the shape of the release process and the licence. The project is Apache-2.0 licensed, written primarily in Rust, with the default branch on main and a homepage at rivet.dev. Releases are frequent and follow a two-track pattern: v2.3.16 shipped on 2026-09-09, preceded the same evening by v2.3.16-rc.3 and v2.3.16-rc.2. That cadence suggests release candidates are cut and promoted within hours, which is normal for a project shipping often, but it also means you should read the changelog before pinning a version. For setup steps, the honest answer is that you need the docs site; nothing in the README is sufficient to get a process running.

The cold-start number has a caveat worth reading twice

The comparison table puts Rivet Actor cold start at roughly 20ms against about 6s for a Kubernetes pod and about 30s for a VM. The benchmark details are more interesting than the headline. The 20ms figure is described as including durable state initialization, measured with Node.js and FoundationDB, and explicitly "no actor key, so no cross-region locking". That last clause is doing a lot of work. If your actor has a key that must be resolved across regions, the measurement does not cover that path, and the real latency will be higher. The memory figure of about 0.6KB per instance comes from spawning 10,000 actors in Node.js v24 on Linux x86 and dividing the RSS delta by actor count. That is a reasonable methodology for marginal per-actor memory, but it is a marginal cost, not a floor: the runtime itself still occupies memory. The read latency of 0ms is explained as co-located SQLite or KV storage with no network round trip, which is true by construction rather than a benchmark result. None of this makes the numbers wrong. It makes them conditional, and the conditions are stated in the details block rather than the table.

Where the actor model stops being the right answer

The design assumes one actor owns its state and processes its queue sequentially. That is a good fit for per-user or per-session workloads and a poor fit for anything that needs a global view. If you need to query across all actors, for example to compute a leaderboard or run an aggregate report, you are outside the model; the README lists no cross-actor query mechanism. The persistence layer is described as SQLite or bring-your-own database, so the durability guarantee is whatever your storage choice provides, and the README does not document the write path. Hibernation is the other edge. Actors "sleep when idle", which is what makes the $0 idle cost claim possible, but a sleeping actor must be woken, and the wake path is exactly the cross-region locking case the benchmark excludes. The Infrastructure table also assumes a serverless platform for the $0 idle figure, and the README does not name one. Finally, the project is Rust-first with a TypeScript surface shown in the examples. If your team is neither, the examples will not carry over.

Rivet Actors against Cloudflare Durable Objects

The repository topics list cloudflare-durable-objects alongside durable-objects and foundationdb, so the comparison is invited. The two share a premise: a single-addressability unit with co-located state that scales to zero. The difference is the substrate. Durable Objects run on Cloudflare's network and store state in Cloudflare's storage, which means you get the operational simplicity and accept the platform lock-in and its runtime constraints. Rivet is Apache-2.0 and self-describable, with storage backed by SQLite or your own database and the benchmark measured against FoundationDB. That means you can run it on your own infrastructure or in a specific legal jurisdiction, which the README calls out as a feature under the global edge network bullet. The trade is that you now operate the storage layer. If your reason for considering Durable Objects was to avoid running a database, Rivet removes that reason. If your reason was jurisdiction or portability, Rivet addresses it directly.

Observability and the maintenance bill

The README advertises a built-in inspector with a SQLite viewer that lets you browse and query an actor's database in real time, plus a workflow state view. For a system where state is the whole point, having a viewer that reads the live database rather than a replica is a genuine debugging advantage, and it is the kind of tool that is usually missing from actor frameworks. On maintenance, the material supports a few concrete observations. The release cadence is high, with multiple candidates per stable version, so upgrade cost is a real line item: you will want to track the changelog rather than update opportunistically. The licence is Apache-2.0, which permits commercial use and modification and includes an express patent grant; it does not include the trademark rights, and if you fork and redistribute you should read the notice requirements rather than take this paragraph as legal advice. Since the project is Rust with a TypeScript API, expect to follow both ecosystems. The README does not describe a migration or upgrade tool, so version bumps may require manual work on actor state.

Editorial conclusion

Rivet Actors suits teams building per-agent, per-session or per-tenant stateful services in TypeScript or Rust who want queues and WebSockets without assembling Redis, Postgres and a workflow engine themselves. It is the wrong tool if you need sub-millisecond state reads across many actors on one machine, or if you cannot run FoundationDB, since the README's benchmark numbers assume it. Before adopting, verify three things against your own workload: the cold-start figure with your actor key in play, whether SQLite persistence matches your durability requirements, and which deployment target you will use given the README does not name a hosted control plane.

Official sources

  1. License: Apache-2.0
  2. Project website
  3. README
  4. Releases
  5. rivet-dev/actors on GitHub
Community notes

Community notes