little-durable-objects
A small, provider-neutral durable-object runtime. Modal is the first sandbox provider; immutable actor-state snapshots live in regional GCS buckets, while placement and each actor's current state head live in Postgres.
Install
Install the TypeScript API in actor and workflow projects:
Install the Rust runtime from crates.io:
Container builds can copy the binary from us-central1-docker.pkg.dev/fluid-analogy-473415-c2/public/little-durable-objects:latest. The image is a runtime base, not a complete actor sandbox: actor images also need Node.js, the project code, and little-durable-objects in the project's dependencies.
Quickstart
-
Create a Postgres database and one GCS
STANDARDbucket. Give the service account inGOOGLE_APPLICATION_CREDENTIALSobject access to the bucket. -
Build the Rust runtime and TypeScript package:
-
Start the control plane. Its HTTP origin serves the public REST API and the internal host gRPC API, so it must be reachable from Modal with HTTP/2 enabled.
-
Export actors from
src/durable-objects.tsin your project:import { Actor } from "little-durable-objects" export class Counter extends Actor { count = 0 async increment(): Promise<number> { return ++this.count } } -
From your trusted backend, call the JSON API using
Authorization: Bearer $DURABLE_OBJECT_ADMIN_TOKEN:PUT /v1/namespaces/{namespaceId}/deployment POST /v1/namespaces/{namespaceId}/workflow-tokensThe deployment call atomically ensures the namespace and registers its active deployment. When it replaces an existing deployment, the control plane terminates that revision's cached actor hosts in every configured region before returning; actor state and placement remain durable for reactivation on the new revision. Its body is
{ "codeRevision", "imageRef", "workingDirectory", "actorEntrypoint", "warmRegion" };warmRegionis optional and starts a disposable background sandbox to warm the image cache without delaying or failing registration. The workflow-token body is{ "executionId", "deadlineUnixMs", "storageRegion" }.storageRegionselects the home region only when an actor is first created. Later invocations resolve the actor's existing host region.image_refis a Modal image containing Node.js, your built project, its dependencies, andlittle-durable-objectsat/usr/local/bin/little-durable-objects. -
Give the issued project token to the workflow and call the actor. The package resolves a short-lived actor target through the control plane, caches it, and invokes the regional host directly over gRPC:
import { configureDurableObjects } from "little-durable-objects" import { Counter } from "./durable-objects.js" configureDurableObjects({ token: process.env.DURABLE_OBJECT_TOKEN!, namespaceId: "my-project", controlPlaneUrl: "https://objects.example.com", }) await Counter.get("account-1").increment()
Actors leave memory after 60 seconds idle; empty host sandboxes stop after 5 minutes. Override those defaults with DURABLE_OBJECT_ACTOR_IDLE_TIMEOUT_MS and DURABLE_OBJECT_HOST_IDLE_TIMEOUT_MS on the control plane.
See the architecture diagram for the request, credential, placement, and state flow.
Release maintainers should follow the release guide.
License
MIT © 2026 Terse