Skills
Skill 6 of 14
Build, debug, or review Cloudflare Durable Objects code for persistent state and coordination.
2 minutes · 421 words · 16 sections
Install
npx skills add cloudflare/skills --skill durable-objectsnpx skills add cloudflare/skills/plugin marketplace add cloudflare/skillsThe first command installs just this skill, by the name in its SKILL.md; the second installs the whole repository.
Build stateful, coordinated applications on Cloudflare’s edge using Durable Objects.
Your knowledge of Durable Objects APIs and configuration may be outdated. Prefer retrieval over pre-training for any Durable Objects task.
Fetch the relevant doc page when implementing features.
./references/rules.md - Core rules, storage, concurrency, RPC, alarms./references/workers.md - Workers handlers, types, wrangler config, observabilitySearch: blockConcurrencyWhile, idFromName, getByName, setAlarm, sql.exec
| Need | Example |
|---|---|
| Coordination | Chat rooms, multiplayer games, collaborative docs |
| Strong consistency | Inventory, booking systems, turn-based games |
| Per-entity storage | Multi-tenant SaaS, per-user data |
| Persistent connections | WebSockets, real-time notifications |
| Scheduled work per entity | Subscription renewals, game timeouts |
// wrangler.jsonc
{
"durable_objects": {
"bindings": [{ "name": "MY_DO", "class_name": "MyDurableObject" }]
},
"migrations": [{ "tag": "v1", "new_sqlite_classes": ["MyDurableObject"] }]
}import { DurableObject } from "cloudflare:workers";
export interface Env {
MY_DO: DurableObjectNamespace<MyDurableObject>;
}
export class MyDurableObject extends DurableObject<Env> {
constructor(ctx: DurableObjectState, env: Env) {
super(ctx, env);
ctx.blockConcurrencyWhile(async () => {
this.ctx.storage.sql.exec(`
CREATE TABLE IF NOT EXISTS items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
data TEXT NOT NULL
)
`);
});
}
async addItem(data: string): Promise<number> {
const result = this.ctx.storage.sql.exec<{ id: number }>(
"INSERT INTO items (data) VALUES (?) RETURNING id",
data
);
return result.one().id;
}
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const stub = env.MY_DO.getByName("my-instance");
const id = await stub.addItem("hello");
return Response.json({ id });
},
};getByName() for deterministic routing - Same input = same DO instancenew_sqlite_classes in migrationsblockConcurrencyWhile() for schema setup onlysetAlarm() replaces any existing alarmDurable Objects do not have separate roles or permissions; access follows the Worker that implements them. Retrieve the current Durable Objects authorization guidance (opens in a new tab) before granting observability or Data Studio access, and scope the Workers role to the intended Worker or Workers product.
blockConcurrencyWhile() on every request (kills throughput)await between related storage writes (breaks atomicity)blockConcurrencyWhile() across fetch() or external I/O// Deterministic - preferred for most cases
const stub = env.MY_DO.getByName("room-123");
// From existing ID string
const id = env.MY_DO.idFromString(storedIdString);
const stub = env.MY_DO.get(id);
// New unique ID - store mapping externally
const id = env.MY_DO.newUniqueId();
const stub = env.MY_DO.get(id);// SQL (synchronous, recommended)
this.ctx.storage.sql.exec("INSERT INTO t (c) VALUES (?)", value);
const rows = this.ctx.storage.sql.exec<Row>("SELECT * FROM t").toArray();
// KV (async)
await this.ctx.storage.put("key", value);
const val = await this.ctx.storage.get<Type>("key");// Schedule (replaces existing)
await this.ctx.storage.setAlarm(Date.now() + 60_000);
// Handler
async alarm(): Promise<void> {
// Process scheduled work
// Optionally reschedule: await this.ctx.storage.setAlarm(...)
}
// Cancel
await this.ctx.storage.deleteAlarm();Read the testing reference (opens in a new tab) before configuring a suite or writing Durable Object tests. It routes to current setup, APIs, and examples and identifies the behavior to cover.
main, last pushed 22 September 2026.SKILL.md, not by matching a directory convention. One layout observed: skills/*/SKILL.md.h1 and no skipped levels:.claude-plugin/marketplace.json by Cloudflare, declaring 1 plugin. It is read for editorial metadata only — never as the skill index, which is always the repository tree./cloudflare/skills.md, and each skill at its own .md URL.3 files · 12 KB
Everything this skill ships beside its prose. All of it is set here, as subchapters of skill 6.
Documentation the agent loads on demand, rather than up front.