Skip to main content
Blog

Introducing the Rust SDK for Rivet Actors

A native, typed Rust SDK for Rivet Actors. Same fearless concurrency, a lot more machines.

Introducing the Rust SDK for Rivet Actors

Today we’re releasing the RivetKit Rust SDK (beta): a native, typed Rust SDK for Rivet Actors.

Same Fearless Concurrency, a Lot More Machines

Actors without Rivet

You can already write the actor pattern in plain async Rust: a Tokio task that owns state behind a channel is a lightweight actor. One owner, message passing, no locks.

// State lives in the task; reach it over a channel.
let (tx, mut rx) = mpsc::channel(32);
tokio::spawn(async move {
	let mut count = 0;
	while let Some(amount) = rx.recv().await {
		count += amount;
	}
});

It’s fearless concurrency, but it never leaves the process. The handle works in-process only, and the in-memory state dies with the task.

flowchart LR caller["Caller"] subgraph proc["Single Machine"] t1["Actor A"] t2["Actor B"] end caller -->|"messages"| t1 caller -->|"messages"| t2 classDef envoy fill:#bfdbfe,stroke:#3b82f6,color:#000 class t1,t2 envoy

Actors with Rivet

A Rivet Actor keeps that exact shape but makes it stateful and distributed (the virtual actor pattern):

  • Stateful: Like a long-lived task, it stays alive between calls and holds its state in memory instead of rebuilding it on every request.
  • Durable: State is persisted and outlives the process instead of dying with the task.
  • Addressable: You reach it by key from anywhere, not through an in-process handle.
  • Distributed: The runtime spreads thousands across machines instead of pinning one.
  • Fault tolerant: It restarts on failure with state preserved, instead of vanishing when the task or process dies.

That same architecture, distributed across machines by Rivet, looks like this:

flowchart LR caller["Caller"] subgraph m1["Machine 1"] a1["Actor A"] a2["Actor B"] end subgraph m2["Machine 2"] a3["Actor C"] a4["Actor D"] end caller -->|"messages"| a1 caller -->|"messages"| a2 caller -->|"messages"| a3 caller -->|"messages"| a4 a1 --> storage[("Durable Storage")] a2 --> storage a3 --> storage a4 --> storage classDef envoy fill:#bfdbfe,stroke:#3b82f6,color:#000 classDef storageNode fill:#fecaca,stroke:#ef4444,color:#000 class a1,a2,a3,a4 envoy class storage storageNode

See the crash course for an introduction to Actors.

Show Me The Code

The Full Actor Toolbox

Features of Rivet Actors

Every actor includes:

  • Networking (docs): Each actor is its own HTTP server, answering plain HTTP or raw WebSocket connections directly through the engine, with no separate gateway.
  • SQLite (docs): Each actor gets its own embedded, co-located database.
  • Actions (docs): A typed RPC surface, checked from caller to handler.
  • Events (docs): Broadcast to connected clients over WebSockets, with no external pub/sub.
  • Queues (docs): Durable background work pushed from any handler.
  • Actor-to-actor calls (docs): Address and call another actor by key, fully typed.
  • Scheduling and alarms (docs): Run an action later, or wake a sleeping actor at a timestamp.
  • Lifecycle (docs): Idle actors hibernate and wake on demand, with hooks to stay up around critical work.
  • Global distribution (docs): Optionally spread actors across regions so each one runs close to its users.
  • Observability (docs): A live dashboard to inspect running actors, their state, and events, with no instrumentation in your code.

An SDK Crafted with Care

  • Full-stack type safety: Action payloads and return types are checked at compile time, all the way from the caller to the handler.
  • Serde-native: State, actions, and events are ordinary Serialize / Deserialize types. No bespoke schema layer to learn.
  • No DSL or codegen: Actors are plain Rust traits, structs, and impl blocks. No build step and no actor macros.
  • Observable out of the box: Fully wired for OpenTelemetry and debuggable with tokio-console.

Polyglot Apps

RivetKit isn’t one isolated runtime per language. Every SDK talks to the same engine and resolves actors by name, so languages mix freely on both sides of a call.

  • Mix actors across languages: Rust and TypeScript actors run side by side in one app and call each other’s actions, neither side knowing the other’s language. Keep your product surface in TypeScript and move CPU-bound actors to Rust.
  • Mix clients across languages: The same actor answers a Rust client, a TypeScript client, React hooks, or plain HTTP, because names resolve at runtime.
  • One core under the hood: Every SDK is a thin binding over rivetkit-core, so each language gets the same semantics. The Rust SDK calls it directly with no bridge and zero FFI overhead.

Deploying

  • Rivet Cloud, BYOC, or fully on-prem: Run it fully managed, bring your own cloud (Railway, Render, Lambda, and more), or self-host the whole stack.
  • Local dev with no compromises: The full Rivet featureset runs on your machine, with no SaaS dependencies.
  • Containers or serverless: Serverless scales to zero between bursts; containers give you flexible deployment options.

See the deployment guides for the full platform list.

Get Started

cargo add rivetkit