Skip to main content

Rivet Actors Give an AI Agent State That Survives Between Tool Calls — What a Container-Only PaaS Is Missing

8 min readDora NodaDora Noda
Share
On this page

An AI coding agent mid-session doesn't remember anything on its own. Every tool call it makes lands in a fresh container invocation with no memory of the last one, so the conversation history, the running list of files it's touched, the count of retries on a flaky test — all of it has to round-trip to a database just to answer the next prompt. That's not a bug in any specific platform; it's the default shape of a request/response container, stateless by design, the same shape a git-push PaaS has used for web services since Heroku. It works fine for a web request. It's the wrong primitive for something that's supposed to remember the last twenty minutes of its own thinking.

Rivet Actors is a two-year-old open-source project's answer to that gap: a stateful compute primitive, explicitly pitched at "AI agents, collaborative apps, and durable execution," where an actor's state lives in the same process as its compute — no database round trip to remember what happened last turn. It's also explicitly not proprietary the way its closest analog, Cloudflare Durable Objects, is. Here's what the primitive actually gives an agent workload, what running it costs against Cloudflare's version, and what it means for a Cluster-API-based platform that has never had an actor primitive of its own.

What a Rivet Actor Actually Is

The unit is simple: one actor per agent, per session, or per user, holding its own state, storage, and networking. In code, it looks like this:

ts
import { actor } from "rivetkit";
 
const agentSession = actor({
  state: { messages: [], toolCallCount: 0 },
 
  actions: {
    addMessage: (c, message) => {
      c.state.messages.push(message);
      c.state.toolCallCount += 1;
    },
    getHistory: (c) => c.state.messages,
  },
});

Mutating c.state persists automatically — batched on a roughly one-second throttle by default — so an agent's running conversation, tool-call count, or working scratchpad survives a restart or a redeploy without an explicit save() call anywhere. Small values live in memory; anything larger goes into a SQLite database built into each actor, so state and compute never leave the same machine. When the agent goes quiet, the actor sleeps: it stops consuming compute entirely, then wakes on the next request, message, or scheduled alarm with its state exactly as it left it.

Rivet's own benchmarks make the gap concrete:

Rivet ActorKubernetes podVM
Cold start~20ms~6s~30s
Memory footprint~0.6KB~50MB~512MB
State read latency0ms (co-located)DB round tripDB round trip

Actors run as TypeScript/JavaScript on Node.js, Bun, or Deno today, with a Rust SDK in preview — and, notably, the framework also supports Docker-compatible containers as an actor's runtime, not just V8 isolates, for workloads that need a real Linux process (a Godot server, a video transcode job) rather than a JS sandbox.

It's Actually Self-Hostable — That's the Whole Point

The comparison every Rivet doc invites is Cloudflare Durable Objects, and the useful difference isn't a feature list, it's a deployment target list. Durable Objects run on Cloudflare's infrastructure, full stop; there's no self-hosted path at any price. Rivet Actors is Apache 2.0 licensed, and the Rivet Engine — the orchestration service that schedules and routes to actors — ships with real self-hosting guides for Docker, Docker Compose, Kubernetes, Railway, Render, AWS Fargate, and Google Cloud Run, with Hetzner and bare-metal/VM guides marked "coming soon" in the docs as of this writing.

The storage layer underneath is a real choice, not a checkbox:

BackendRivet's own guidance
File systemRecommended for smaller, single-node deployments today
PostgreSQLRecommended for multi-node deployments, but still experimental
FoundationDBBest scalability and production performance — requires an enterprise license

That's an honest maturity ladder, not marketing: single-node file-backed Rivet is fine for a side project, Postgres-backed multi-node is the real path for anything running today, and FoundationDB is the eventual destination once a fleet actually needs distributed transactional guarantees — gated behind a license the way most "open core" storage layers eventually are. The deployment architecture itself is three plain pieces — your backend (fronted by an Envoy proxy), the Rivet Engine, and that storage layer — which means the whole stack is just a handful of containers a Cluster-API-provisioned Kubernetes cluster can run like any other workload, with no Cloudflare account required anywhere in the chain.

What Rivet Compute Actually Shipped

On June 17, 2026, Rivet added a managed hosting layer on top of the open-source core: Rivet Compute, "a serverless platform for hosting your actors," deployed with one command:

text
npx @rivetkit/cli deploy

That resolves the project from an auth token, builds and pushes a Docker image to Rivet's own registry, provisions a managed pool, and prints a live deployment URL once it's ready — plus npx @rivetkit/cli setup-ci to generate a GitHub Actions workflow for redeploying on every push. It's a managed convenience layer sitting on top of the same open-source engine, not a replacement for it, and it shipped as general availability immediately — no waitlist, no preview list.

What It Actually Costs Against Cloudflare

Rivet Cloud's plans are worth reading against Cloudflare's own Durable Objects pricing, because the two converge in a way that looks deliberate:

Rivet Cloud (Hobby, $20/mo + usage)Cloudflare Durable Objects (Workers Paid, $5/mo)
Reads included25 billion/month25 billion/month
Writes included50 million/month50 million/month
Storage included5GB5GB
Read overage$0.20/million$0.001/million
Write overage$1.00/million$1.00/million
Storage overage$0.40/GB-month$0.20/GB-month
Egress$0.15/GB (1TB included)Free (no egress fees anywhere on Cloudflare)

The included quotas aren't roughly similar — they're identical numbers, down to the billion. Write overage matches exactly too. Where they diverge is read overage, and it's not subtle: Rivet charges 200x more per read once an app blows past the 25-billion-reads-a-month allowance both platforms hand out for free. Storage overage runs Rivet 2x Cloudflare's rate, and Cloudflare doesn't charge for egress at all, anywhere on its platform, while Rivet meters it like every other cloud vendor does.

The honest caveat on that 200x number: 25 billion reads a month works out to roughly 9,645 reads per second, sustained, all month — a workload most teams building an AI agent's session memory will never come close to. At the scale a typical agent product actually runs at, neither platform's usage bill is the decision that matters; both round to "cheap."

The number that actually matters is the one no pricing table shows: Cloudflare Durable Objects has no exit. There's no self-hosted Durable Objects at any price, at any scale — you're on Cloudflare's meter permanently, for as long as the app runs, with parity pricing today being no guarantee of parity pricing in five years (a lesson this list has already drawn from Vercel's and Fly.io's own repeated post-launch repricing). Rivet's identical-today numbers come with an actual escape hatch: the same Apache-2.0 engine that Rivet Cloud runs is the one you can point at your own Postgres and your own machines the day the calculus changes.

What This Means for a Container-Only PaaS

bex's own model — a container per tenant service, deployed onto a Cluster-API-provisioned Kubernetes fleet — has never had an actor primitive. Today, an AI agent operating through bex's deploy API that needs to remember something between tool calls has exactly one option: stand up its own Postgres or Redis instance as a separate service and pay the round-trip cost on every read, the same as any other stateless container workload. That's a real gap next to what Rivet Actors (or Durable Objects, if you're willing to live inside Cloudflare's walls) gives an agent for free: state that's already sitting in the same process as the code touching it.

The question this raises for bex's own roadmap isn't whether that gap is real — it is — it's whether closing it means building a native actor primitive into the platform's control plane, the way Cloudflare built Durable Objects into Workers. It doesn't. The Rivet Engine's own architecture answers this directly: it's an Envoy proxy, an orchestration service, and a storage backend — three containers with a documented Kubernetes deployment path, not a primitive that has to be wired into etcd or the API server to exist. That means the whole stack is just another workload a tenant (or bex itself, as a first-party template) can deploy onto an existing Cluster-API fleet exactly the way they'd deploy Postgres today — no new scheduler, no new CRD, no change to how bex's control plane thinks about a "service."

The right move is a Helm chart or one-click template for self-hosted Rivet Engine on a bex-managed cluster, not a competing implementation of actor semantics in bex's own API — the same non-goal bex already holds for managed databases, applied to the same reasoning: a workload a tenant runs, not a primitive the platform has to own and operate forever.

Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own, with a Cluster-API-managed Kubernetes cluster underneath ready to run whatever stateful primitive an agent workload actually needs. Star the repo on GitHub or deploy your first app today.

Related articles

Run this on infrastructure you own

bex is the open-source, AI-native Render alternative — push a git repo and get a running HTTPS service on your own machines.

Get started with bex