Durable Objects
CloudflareOfficialPublished by Cloudflare
- Skill
- Tool integration
- Cloud and DevOps
- Apache-2.0
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
This skill provides guidance on implementing Cloudflare Durable Objects, which enable stateful coordination on the edge. It covers the use of Durable Objects for tasks requiring strong consistency, persistent connections, and per-entity storage. The skill includes best practices for configuration, storage operations using SQLite or KV, alarm scheduling, and testing strategies, while emphasizing the importance of using current documentation for API implementation.
What it does
- Provides patterns for creating and configuring Durable Object classes.
- Offers guidance on using SQLite and KV storage within Durable Objects.
- Assists in setting up alarms for scheduled per-entity work.
- Helps with configuring bindings and migrations in wrangler files.
- Supports the implementation of RPC methods and WebSocket handlers.
- Provides references for testing Durable Objects using Vitest.
When to use it
- When building stateful coordination features like chat rooms or multiplayer games.
- When implementing systems requiring strong consistency, such as inventory management.
- When managing per-user data or multi-tenant application state.
- When handling persistent connections like WebSockets.
- When reviewing existing Durable Object code for alignment with best practices.
Advantages
- Promotes the use of current, authoritative documentation via retrieval.
- Provides clear patterns for deterministic routing and storage initialization.
- Helps avoid common anti-patterns like blocking concurrency on every request.
- Supports structured configuration for migrations and bindings.
Usage examples
- “How do I initialize a SQLite database in a Durable Object?”
- The agent provides a pattern using blockConcurrencyWhile in the constructor to execute SQL schema creation.
- “What is the best way to route requests to a specific Durable Object instance?”
- The agent explains how to use getByName for deterministic routing to ensure the same input maps to the same object instance.
- “How should I handle scheduled tasks within a Durable Object?”
- The agent demonstrates the use of setAlarm and the alarm() handler method for per-object scheduled work.
- “Can you review my Durable Object migration configuration?”
- The agent checks the wrangler configuration against the provided patterns for bindings and new_sqlite_classes.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/cloudflare/durable-objects/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip durable-objects.zip -d .agents/skills
Documentation by Cloudflare
Durable Objects
Build stateful, coordinated applications on Cloudflare's edge using Durable Objects.
Retrieval Sources
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.
When to Use
Creating new Durable Object classes for stateful coordination
Implementing RPC methods, alarms, or WebSocket handlers
Reviewing existing DO code for best practices
Configuring wrangler.jsonc/toml for DO bindings and migrations
Writing tests with Cloudflare’s Vitest integration
Designing sharding strategies and parent-child relationships
Reference Documentation
./references/rules.md- Core rules, storage, concurrency, RPC, alarmsTesting reference - Current Vitest documentation, migration choices, and test selection
Workers reference - Workers handlers, types, configuration, tracing, and local debugging
Search: blockConcurrencyWhile, idFromName, getByName, setAlarm, sql.exec
Core Principles
Use Durable Objects For
| 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 |
Do NOT Use For
Stateless request handling (use plain Workers)
Maximum global distribution needs
High fan-out independent requests
Quick Reference
Wrangler Configuration
// wrangler.jsonc
{
"durable_objects": {
"bindings": [{ "name": "MY_DO", "class_name": "MyDurableObject" }]
},
"migrations": [{ "tag": "v1", "new_sqlite_classes": ["MyDurableObject"] }]
}Basic Durable Object Pattern
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 });
},
};Critical Rules
Model around coordination atoms - One DO per chat room/game/user, not one global DO
Use
getByName()for deterministic routing - Same input = same DO instanceUse SQLite storage - Configure
new_sqlite_classesin migrationsInitialize in constructor - Use
blockConcurrencyWhile()for schema setup onlyUse RPC methods - Not fetch() handler (compatibility date >= 2024-04-03)
Persist first, cache second - Always write to storage before updating in-memory state
One alarm per DO -
setAlarm()replaces any existing alarm
Authorization
Durable Objects do not have separate roles or permissions; access follows the Worker that implements them. Retrieve the current Durable Objects authorization guidance before granting observability or Data Studio access, and scope the Workers role to the intended Worker or Workers product.
Anti-Patterns (NEVER)
Single global DO handling all requests (bottleneck)
Using
blockConcurrencyWhile()on every request (kills throughput)Storing critical state only in memory (lost on eviction/crash)
Using
awaitbetween related storage writes (breaks atomicity)Holding
blockConcurrencyWhile()acrossfetch()or external I/O
Stub Creation
// 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);Storage Operations
// 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");Alarms
// 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();Testing
Read the testing reference before configuring a suite or writing Durable Object tests. It routes to current setup, APIs, and examples and identifies the behavior to cover.
Skill feedback
If the user reports that this skill gave incorrect or outdated guidance, or is missing information, read references/skill-feedback.md.
Files
- ATTRIBUTION.mdAdded by AutoGineer866 B
- LICENSELicence file added by AutoGineer11.1 KiB
- SKILL.md6.1 KiB
- references/rules.md2.8 KiB
- references/skill-feedback.md2.7 KiB
- references/testing.md2.5 KiB
- references/workers.md7.8 KiB
references/skill-feedback.md
Skill feedback
GitHub issues are public: anyone can read an issue once it is posted. Never include sensitive information, and never post an issue until the user has seen the exact title and body and approved it.
Use this when the user reports that the durable-objects skill gave incorrect or outdated guidance, is missing information, or could be improved. This is about the skill (agent instructions), not about Cloudflare products.
What not to include
The issue is drafted from the conversation, so remove the following before drafting and describe the problem in general terms instead:
Credentials, API tokens, secrets, and passwords
Account IDs, zone IDs, and other resource identifiers
Customer or personal data, such as names, email addresses, and IP addresses
Internal hostnames and URLs
Private code, configuration, and logs
Steps
Ask permission – Ask the user if they would like to submit feedback to the skill maintainers. If they decline, move on.
Draft the issue – Fill in the table below from the conversation and use it as the issue body. Always identify which specific file and section caused the problem. Leave out everything listed in What not to include.
Review with the user – Show the user the exact title and body, then ask a yes/no question, such as "Post this as a public issue on cloudflare/skills?" Submit only after the user answers yes. If they ask for changes, apply them and ask again. If they answer no, do not post. Agreeing to send feedback in step 1 is not approval of the text.
Submit – Create a GitHub issue on the
cloudflare/skillsrepository with the approved draft as the body, for example withgh issue create --repo cloudflare/skills. The title must follow this format:skill-feedback: durable-objects: <summary of the problem>.Share the result – Share the issue URL with the user after submission. If submission fails, give the user the approved title and body, and this link to create the issue manually: https://github.com/cloudflare/skills/issues/new
Issue body
| Field | Value |
|---|---|
| Type | bug (incorrect guidance), outdated, missing, or improvement |
| Skill | durable-objects |
| Source | File and section, e.g. SKILL.md > "Section name" or references/<file>.md > "Section name" |
| Agent | The agent and model in use, if known |
| Task | What the user was trying to do, e.g. "deploy a preview" |
| Expected | What should have happened, e.g. "Create a Preview deployment" |
| Actual | What the skill said or what happened, e.g. "Unknown option: --preview" |
| Impact | The effect on the user, e.g. "Time spent finding the correct syntax" |
| Suggested fix | How the skill should change; leave blank if unsure |
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Published by
- Cloudflare
- Publisher
- Cloudflare (Official)
- Source
- cloudflare/skills · skills/durable-objects · commit 6eb6c78
- Licence
- Apache License 2.0 (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Cloudflare or Cloudflare.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download durable-objects.zip