Cloudflare
Cloudflare already guarantees a single instance of a Durable Object globally and serializes requests to it. That is the virtual-actor contract — so the platform is the cluster.
Installation
pnpm add @sigx/actors-cloudflareWhy it is small
This package needs none of the machinery @sigx/actors/cluster
uses to rebuild that contract: no membership heartbeats, no activation directory, no
HMAC-authenticated host-to-host mount.
There is no HMAC because a Durable Object stub is not network-reachable — holding the binding is the capability grant, and guards run once at the public edge. And there is no 421 retry because ref → object id is a pure function, so a mismatch is a config bug rather than a race.
Storage
const storage = durableObjectStorage(state.storage);
DO storage is strongly consistent and single-threaded per object, so the runtime's etag compare-and-set holds without a transaction.
Reminders
const reminders = durableObjectReminders({
storage: state.storage,
alarms: state.storage,
blockConcurrencyWhile: (fn) => state.blockConcurrencyWhile(fn),
});
export class ActorHost {
async alarm() {
await reminders.onAlarm(); // fire what is due, re-arm the rest
}
}
The default shardedReminders() splits one table into fixed hash shards and polls it, because
a host holds many actors and has to find whose reminder is due. A DO holds exactly one, so
there is nothing to search and nothing to poll — reminders live in the object's own storage and
the platform wakes it at the earliest due time.
The visible consequence: an alarm fires at the due time, where shardedReminders()
promises only "at or after nextDue".
Client sockets
Browsers can reach actors over a WebSocket here, terminating in either half:
createWorkerHandler({ ..., socket: {} }); // in the Worker
createWorkerHandler({ ..., socket: { terminate: 'object' } }); // in the object
Worker-terminated gives one multiplexed socket per client, reaching every actor — the
right shape for a dashboard. Object-terminated gives one socket per actor, accepted with
the hibernation API inside the object that owns it — the room pattern, and the mode where a
disconnect actually releases the activation, because teardown happens locally instead of dying
at the stub.fetch boundary.
Pair either with socketTransport() on the client. The
deployment guide has the choice in full,
plus the hibernation contract.
The getting-started path
Most apps do not touch the two seams directly — createHostDurableObject() and
createWorkerHandler() assemble them. See
Cloudflare Workers for the full entry, the wrangler.jsonc
and the three gotchas that are each worth their own callout.
Next steps
- Installation — bindings and migrations.
- API reference — exports.
- Cloudflare Workers — the deployment guide.
@sigx/actors-ws— the client half of a socket.
