Cloudflare Durable Objects
Status: Production Ready ✅ Last Updated: 2025-11-25 Dependencies: cloudflare-worker-base (recommended) Latest Versions: wrangler@4.50.0+, @cloudflare/workers-types@4.20251125.0+ Official Docs: https://developers.cloudflare.com/durable-objects/
Table of Contents
[What are Durable Objects?](#what-are-durable-objects) • [Quick Start](#quick-start-10-minutes) • [When to Load References](#when-to-load-references) • [Class Structure](#durable-object-class-structure) • [State API](#state-api---persistent-storage) • [WebSocket Hibernation](#websocket-hibernation-api) • [Alarms](#alarms-api---scheduled-tasks) • [RPC vs HTTP](#rpc-vs-http-fetch) • [Stubs & Routing](#creating-durable-object-stubs-and-routing) • [Migrations](#migrations---managing-do-classes) • [Common Patterns](#common-patterns) • [Critical Rules](#critical-rules) • [Known Issues](#known-issues-prevention)
What are Durable Objects?
Globally unique, stateful objects with single-point coordination, strong consistency (ACID), WebSocket Hibernation (thousands of connections), SQLite storage (1GB), and alarms API.
Use for: Chat rooms, multiplayer games, rate limiting, session management, leader election, stateful workflows
Quick Start (10 Minutes)
Option 1: Scaffold New DO Project
npm create cloudflare@latest my-durable-app -- \
--template=cloudflare/durable-objects-template --ts --git --deploy false
cd my-durable-app && bun install && npm run dev
Option 2: Add to Existing Worker
1. Install types:
bun add -d @cloudflare/workers-types
2. Create DO class (src/counter.ts):
import { DurableObject } from 'cloudflare:workers';
export class Counter extends DurableObject {
async increment(): Promise<number> {
let value: number = (await this.ctx.storage.get('value')) || 0;
await this.ctx.storage.put('value', ++value);
return value;
}
}
export default Counter; // CRITICAL
3. Configure (wrangler.jsonc):
{
"durable_objects": {
"bindings": [{ "name": "COUNTER", "class_name": "Counter" }]
},
"migrations": [
{ "tag": "v1", "new_sqlite_classes": ["Counter"] }
]
}
4. Call from Worker (src/index.ts):
import { Counter } from './counter';
interface Env {
COUNTER: DurableObjectNamespace<Counter>;
}
export { Counter };
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const stub = env.COUNTER.getByName('global-counter');
return new Response(`Count: ${await stub.increment()}`);
},
};
Deploy:
bunx wrangler deploy
Available Commands
Use these interactive commands for guided workflows:
/do-setup- Initialize new DO project with interactive setup wizard- Choose storage backend (SQL, KV, both)
- Select use case pattern (WebSocket, Sessions, Rate Limiting, etc.)
- Optional Vitest testing setup
- Generates complete DO implementation
/do-migrate- Interactive migration assistant- New class creation (new_sqlite_classes, new_classes)
- Rename existing classes (renamed_classes)
- Delete classes with safety confirmations (deleted_classes)
- Transfer classes between scripts (transferred_classes)
- Auto-increments migration tags (v1, v2, v3...)
/do-debug- Step-by-step debugging workflow- Detects error categories (deployment, runtime, performance, etc.)
- Runs diagnostic checks on configuration and code
- Provides specific fixes with code examples
- Guides local testing and production verification
/do-patterns- Pattern selection wizard- Recommends DO pattern based on use case
- Supports WebSocket, Rate Limiting, Sessions, Analytics, Leader Election
- Generates complete pattern implementation
- Provides best practices and optimization tips
/do-optimize- Performance optimization assistant- Analyzes existing DO code for bottlenecks
- Provides targeted optimization recommendations
- Covers constructor, queries, WebSocket, memory, alarms
- Measures performance improvements
Autonomous Agents
These agents work autonomously without user interaction:
do-debugger- Automatic error detection and fixing- Validates wrangler.jsonc configuration
- Detects 16+ common DO errors
- Applies fixes automatically with backups
- Tests fixes before reporting
do-setup-assistant- Automatic project scaffolding- Analyzes user requirements from natural language
- Generates complete DO implementation
- Creates tests, documentation, validation
- Supports all use case patterns
do-pattern-implementer- Production pattern implementation- Analyzes existing DO code
- Recommends patterns by priority
- Implements TTL cleanup, RPC metadata, SQL indexes, etc.
- Generates pattern-specific tests
When to Load References
Load immediately when user mentions:
state-api-reference.md→ "storage", "sql", "database", "query", "get/put", "KV", "1GB limit"websocket-hibernation.md→ "websocket", "real-time", "chat", "hibernation", "serializeAttachment"alarms-api.md→ "alarms", "scheduled tasks", "cron", "periodic", "batch processing"rpc-patterns.md→ "RPC", "fetch", "HTTP", "methods", "routing"rpc-metadata.md→ "RpcTarget", "metadata", "DO name", "idFromName access"stubs-routing.md→ "stubs", "idFromName", "newUniqueId", "location hints", "jurisdiction"migrations-guide.md→ "migrations", "rename", "delete", "transfer", "schema changes"migration-cheatsheet.md→ "migration quick reference", "migration types", "common migrations"common-patterns.md→ "patterns", "examples", "rate limiting", "sessions", "leader election"vitest-testing.md→ "test", "testing", "vitest", "unit test", "@cloudflare/vitest-pool-workers"gradual-deployments.md→ "gradual", "deployment", "traffic split", "rollout", "canary"typescript-config.md→ "TypeScript", "types", "tsconfig", "wrangler.jsonc", "bindings"advanced-sql-patterns.md→ "CTE", "window functions", "FTS5", "full-text search", "JSON functions", "complex SQL"security-best-practices.md→ "security", "authentication", "authorization", "SQL injection", "CORS", "encryption", "rate limiting"error-codes.md→ "error codes", "error catalog", "specific error", "E001", "troubleshooting"top-errors.md→ errors, "not working", debugging, "binding not found"
Load proactively when:
- Building new feature → Load relevant pattern from
common-patterns.md - Debugging issue → Load
error-codes.mdfor specific errors, thentop-errors.md - Implementing WebSocket → Load
websocket-hibernation.mdbefore coding - Setting up storage → Load
state-api-reference.mdfor SQL/KV APIs - Complex SQL queries → Load
advanced-sql-patterns.mdfor CTEs, window functions, FTS5 - Security review → Load
security-best-practices.mdfor authentication, authorization, SQL injection prevention - Creating first DO → Load
stubs-routing.mdfor ID methods - Writing tests → Load
vitest-testing.mdfor testing patterns - Planning deployment → Load
gradual-deployments.mdfor rollout strategy - Migration needed → Load
migration-cheatsheet.mdfor quick reference - Using DO name inside DO → Load
rpc-metadata.mdfor RpcTarget pattern - TypeScript configuration → Load
typescript-config.mdfor setup
Durable Object Class Structure
All DOs extend DurableObject and MUST be exported:
import { DurableObject } from 'cloudflare:workers';
export class MyDO extends DurableObject {
constructor(ctx: DurableObjectState, env: Env) {
super(ctx, env); // Required first line
// Keep minimal - heavy work blocks hibernation
ctx.blockConcurrencyWhile(async () => {
// Load from storage before handling requests
});
}
async myMethod(): Promise<string> { /