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".
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.
