website/src/content/docs/general/runtime-modes.mdx
import imgServerless from "./runtime-modes/serverless.png"; import imgRunners from "./runtime-modes/runners.png";
Serverless is the default and recommended mode. Rivet sends HTTP requests to your backend to run actor logic, allowing your infrastructure to scale automatically.
import { actor, setup } from "rivetkit";
const myActor = actor({ state: {}, actions: {} });
const registry = setup({ use: { myActor } });
export default registry.serve();
import { Hono } from "hono";
import { actor, setup } from "rivetkit";
const myActor = actor({ state: {}, actions: {} });
const registry = setup({ use: { myActor } });
const app = new Hono();
app.all("/api/rivet/*", (c) => registry.handler(c.req.raw));
export default app;
See Server Setup for more configuration options.
When a client creates an actor, it sends a request to the Rivet Engine. The engine then calls GET /api/rivet/start on your serverless backend to run the actor.
Rivet exposes the following endpoints:
GET /api/rivet/metadata: Validates configurationGET /api/rivet/start: Runs an actorYou should never call these endpoints yourself, this is included purely for comprehension of how Rivet works under the hood.
Serverless platforms like Vercel have function timeouts. Rivet handles this automatically by migrating actors between function invocations, preserving state through ctx.state. Write your code as if it runs forever, Rivet handles the rest.
Read more about how we handle timeouts.
Each serverless request has a configurable lifespan (requestLifespan, default: 15 minutes). Set this to match your platform's function timeout (e.g. requestLifespan: 300 for Vercel Pro).
When the request nears its lifespan, the engine reserves a grace period (serverless_drain_grace_period, default: 10 seconds) at the end to gracefully stop actors. For example, with a 300-second lifespan, actors begin stopping at 290 seconds. After the full lifespan elapses, the connection is forcibly closed and any remaining actors are rescheduled.
See Limits for configuration details.
Runners run actors as long-running background processes without exposing an HTTP endpoint.
import { actor, setup } from "rivetkit";
const myActor = actor({ state: {}, actions: {} });
const registry = setup({ use: { myActor } });
registry.startRunner();
The runner runs in the background, ready to run actors.
On startup, your backend calls registry.startRunner() which opens a persistent connection to the Rivet Engine. When a client creates an actor, the engine sends a command through this connection to start the actor on your backend.
Use RIVET_RUNNER to assign runners to a pool. This lets you control which runners handle specific actors.
RIVET_RUNNER=gpu-workers
import { actor, setup } from "rivetkit";
const myActor = actor({ state: {}, actions: {} });
const registry = setup({
use: { myActor },
runner: {
runnerName: "gpu-workers",
},
});
| Mode | Method | Use Case |
|---|---|---|
| Auto | registry.start() | Simplest setup. Starts server, serves static files, and runs actors. |
| Serverless | registry.serve() | Fetch handler for serverless platforms |
| Serverless | registry.handler() | Integrating with existing routers (Hono, Elysia, etc.) |
| Runner | registry.startRunner() | Long-running processes without HTTP endpoints |