cloudflare-durable-objects
Comprehensive guide for Cloudflare Durable Objects - globally unique, stateful objects for coordination, real-time communication, and persistent state management. Use when: building real-time applications, creating WebSocket servers with hibernation, implementing chat rooms or multiplayer games, coordinating between multiple clients, managing per-user or per-room state, implementing rate limiting or session management, scheduling tasks with alarms, building queues or workflows, or encountering "do class export", "new_sqlite_classes", "migrations required", "websocket hibernation", "alarm api error", or "global uniqueness" errors. Prevents 15+ documented issues: class not exported, missing migrations, wrong migration type, constructor overhead blocking hibernation, setTimeout breaking hibernation, in-memory state lost on hibernation, outgoing WebSocket not hibernating, global uniqueness confusion, partial deleteAll on KV backend, binding name mismatches, state size limits exceeded, non-atomic migrations, location hints misunderstood, alarm retry failures, and fetch calls blocking hibernation. Keywords: durable objects, cloudflare do, DurableObject class, do bindings, websocket hibernation, do state api, ctx.storage.sql, ctx.acceptWebSocket, webSocketMessage, alarm() handler, storage.setAlarm, idFromName, newUniqueId, getByName, DurableObjectStub, serializeAttachment, real-time cloudflare, multiplayer cloudflare, chat room workers, coordination cloudflare, stateful workers, new_sqlite_classes, do migrations, location hints, RPC methods, blockConcurrencyWhile, "do class export", "new_sqlite_classes", "migrations required", "websocket hibernation", "alarm api error", "global uniqueness", "binding not found"
What this skill does
# Cloudflare Durable Objects **Status**: Production Ready ✅ **Last Updated**: 2025-10-22 **Dependencies**: cloudflare-worker-base (recommended) **Latest Versions**: [email protected]+, @cloudflare/[email protected]+ **Official Docs**: https://developers.cloudflare.com/durable-objects/ --- ## What are Durable Objects? Cloudflare Durable Objects are **globally unique, stateful objects** that provide: - **Single-point coordination** - Each Durable Object instance is globally unique across Cloudflare's network - **Strong consistency** - Transactional, serializable storage (ACID guarantees) - **Real-time communication** - WebSocket Hibernation API for thousands of connections per instance - **Persistent state** - Built-in SQLite database (up to 1GB) or key-value storage - **Scheduled tasks** - Alarms API for future task execution - **Global distribution** - Automatically routed to optimal location - **Automatic scaling** - Millions of independent instances **Use Cases**: - Chat rooms and real-time collaboration - Multiplayer game servers - Rate limiting and session management - Leader election and coordination - WebSocket servers with hibernation - Stateful workflows and queues - Per-user or per-room logic --- ## Quick Start (10 Minutes) ### Option 1: Scaffold New DO Project ```bash npm create cloudflare@latest my-durable-app -- \ --template=cloudflare/durable-objects-template \ --ts \ --git \ --deploy false cd my-durable-app npm install npm run dev ``` **What this creates:** - Complete Durable Objects project structure - TypeScript configuration - wrangler.jsonc with bindings and migrations - Example DO class implementation - Worker to call the DO ### Option 2: Add to Existing Worker ```bash cd my-existing-worker npm install -D @cloudflare/workers-types ``` **Create a Durable Object class** (`src/counter.ts`): ```typescript import { DurableObject } from 'cloudflare:workers'; export class Counter extends DurableObject { async increment(): Promise<number> { // Get current value from storage (default to 0) let value: number = (await this.ctx.storage.get('value')) || 0; // Increment value += 1; // Save back to storage await this.ctx.storage.put('value', value); return value; } async get(): Promise<number> { return (await this.ctx.storage.get('value')) || 0; } } // CRITICAL: Export the class export default Counter; ``` **Configure wrangler.jsonc:** ```jsonc { "$schema": "node_modules/wrangler/config-schema.json", "name": "my-worker", "main": "src/index.ts", "compatibility_date": "2025-10-22", // Durable Objects binding "durable_objects": { "bindings": [ { "name": "COUNTER", // How you access it: env.COUNTER "class_name": "Counter" // MUST match exported class name } ] }, // REQUIRED: Migration for new DO class "migrations": [ { "tag": "v1", // Unique migration identifier "new_sqlite_classes": [ // Use SQLite backend (recommended) "Counter" ] } ] } ``` **Call from Worker** (`src/index.ts`): ```typescript import { Counter } from './counter'; interface Env { COUNTER: DurableObjectNamespace<Counter>; } export { Counter }; export default { async fetch(request: Request, env: Env): Promise<Response> { // Get Durable Object stub by name const id = env.COUNTER.idFromName('global-counter'); const stub = env.COUNTER.get(id); // Call RPC method on the DO const count = await stub.increment(); return new Response(`Count: ${count}`); }, }; ``` **Deploy:** ```bash npx wrangler deploy ``` --- ## Durable Object Class Structure ### Base Class Pattern All Durable Objects **MUST extend `DurableObject`** from `cloudflare:workers`: ```typescript import { DurableObject } from 'cloudflare:workers'; export class MyDurableObject extends DurableObject { constructor(ctx: DurableObjectState, env: Env) { super(ctx, env); // Optional: Initialize from storage ctx.blockConcurrencyWhile(async () => { // Load state before handling requests this.someValue = await ctx.storage.get('someKey') || defaultValue; }); } // RPC methods (recommended) async myMethod(): Promise<string> { return 'Hello from DO!'; } // Optional: HTTP fetch handler async fetch(request: Request): Promise<Response> { return new Response('Hello from DO fetch!'); } } // CRITICAL: Export the class export default MyDurableObject; ``` ### Constructor Pattern ```typescript constructor(ctx: DurableObjectState, env: Env) { super(ctx, env); // REQUIRED // Access to environment bindings this.env = env; // this.ctx provides: // - this.ctx.storage (storage API) // - this.ctx.id (unique ID) // - this.ctx.waitUntil() (background tasks) // - this.ctx.acceptWebSocket() (WebSocket hibernation) } ``` **CRITICAL Rules:** - ✅ **Always call `super(ctx, env)`** first - ✅ **Keep constructor minimal** - heavy work blocks hibernation wake-up - ✅ **Use `ctx.blockConcurrencyWhile()`** to initialize from storage before requests - ❌ **Never use `setTimeout` or `setInterval`** - breaks hibernation (use alarms instead) - ❌ **Don't rely only on in-memory state** with WebSockets - persist to storage ### Exporting the Class ```typescript // Export as default (required for Worker to use it) export default MyDurableObject; // Also export as named export (for type inference in Worker) export { MyDurableObject }; ``` **In Worker:** ```typescript // Import the class for types import { MyDurableObject } from './my-durable-object'; // Export it so Worker can instantiate it export { MyDurableObject }; interface Env { MY_DO: DurableObjectNamespace<MyDurableObject>; } ``` --- ## State API - Persistent Storage Durable Objects provide **two storage APIs** depending on the backend: 1. **SQL API** (SQLite backend) - **Recommended** 2. **Key-Value API** (KV or SQLite backend) ### Enable SQLite Backend (Recommended) In `wrangler.jsonc` migrations: ```jsonc { "migrations": [ { "tag": "v1", "new_sqlite_classes": ["MyDurableObject"] // ← Use this for SQLite } ] } ``` **Why SQLite?** - ✅ Up to **1GB storage** (vs 128MB for KV backend) - ✅ **Atomic operations** (deleteAll is all-or-nothing) - ✅ **SQL queries** with transactions - ✅ **Point-in-time recovery** (PITR) - ✅ Synchronous KV API available too ### SQL API Access via `ctx.storage.sql`: ```typescript import { DurableObject } from 'cloudflare:workers'; export class MyDurableObject extends DurableObject { sql: SqlStorage; constructor(ctx: DurableObjectState, env: Env) { super(ctx, env); this.sql = ctx.storage.sql; // Create table on first run this.sql.exec(` CREATE TABLE IF NOT EXISTS messages ( id INTEGER PRIMARY KEY AUTOINCREMENT, text TEXT NOT NULL, user TEXT NOT NULL, created_at INTEGER NOT NULL ); CREATE INDEX IF NOT EXISTS idx_created_at ON messages(created_at); `); } async addMessage(text: string, user: string): Promise<number> { // Insert with exec (returns cursor) const cursor = this.sql.exec( 'INSERT INTO messages (text, user, created_at) VALUES (?, ?, ?) RETURNING id', text, user, Date.now() ); const row = cursor.one<{ id: number }>(); return row.id; } async getMessages(limit: number = 50): Promise<any[]> { const cursor = this.sql.exec( 'SELECT * FROM messages ORDER BY created_at DESC LIMIT ?', limit ); // Convert cursor to array return cursor.toArray(); } async deleteOldMessages(beforeTimestamp: number): Promise<void> { this.sql.exec( 'DELETE FROM messages WHERE created_at < ?', beforeTimestamp ); } } ``` **SQL API Methods:** ```typescript // Execute query (returns cursor) const cursor = this.sql.exec('SELECT * FROM table WHERE id = ?', id
Related in Backend & APIs
jfrog
IncludedInteract with the JFrog Platform via the JFrog CLI and REST/GraphQL APIs. Use this skill when the user wants to manage Artifactory repositories, upload or download artifacts, manage builds, configure permissions, manage users and groups, work with access tokens, configure JFrog CLI servers, search artifacts, manage properties, set up replication, manage JFrog Projects, run security audits or scans, look up CVE details, query exposures scan results from JFrog Advanced Security, manage release bundles and lifecycle operations, aggregate or export platform data, or perform any JFrog Platform administration task. Also use when the user mentions jf, jfrog, artifactory, xray, distribution, evidence, apptrust, onemodel, graphql, workers, mission control, curation, advanced security, exposures, or any JFrog product name.
cupynumeric-migration-readiness
IncludedPre-migration readiness assessor for porting NumPy to cuPyNumeric. Use BEFORE substantial porting work begins when the user asks whether code will scale on GPU, whether they should migrate to cuPyNumeric, which NumPy patterns transfer cleanly, what must be refactored before porting, or mentions pre-port assessment, scaling analysis, or refactor planning. Inspect the user's source code, look up NumPy usage, cross-reference the cuPyNumeric API support manifest, and distinguish distributed-scaling-friendly patterns from blockers such as unsupported APIs, scalar synchronization, host round-trips, Python/object-heavy control flow, shape/data-dependent branching, and in-place mutation hazards. Produce a verdict of READY, LIGHT REFACTOR, SIGNIFICANT REFACTOR, or NOT RECOMMENDED, with concrete refactor pointers.
alibabacloud-data-agent-skill
IncludedInvoke Alibaba Cloud Apsara Data Agent for Analytics via CLI to perform natural language-driven data analysis on enterprise databases. Data Agent for Analytics is an intelligent data analysis agent developed by Alibaba Cloud Database team for enterprise users. It automatically completes requirement analysis, data understanding, analysis insights, and report generation based on natural language descriptions. This tool supports: discovering data resources (instances/databases/tables) managed in DMS, initiating query or deep analysis sessions, real-time progress tracking, and retrieving analysis conclusions and generated reports. Use this Skill when users need to query databases, analyze data trends, generate data reports, ask questions in natural language, or mention "Data Agent", "data analysis", "database query", "SQL analysis", "data insights".
token-optimizer
IncludedReduce OpenClaw token usage and API costs through smart model routing, heartbeat optimization, budget tracking, and native 2026.2.15 features (session pruning, bootstrap size limits, cache TTL alignment). Use when token costs are high, API rate limits are being hit, or hosting multiple agents at scale. The 4 executable scripts (context_optimizer, model_router, heartbeat_optimizer, token_tracker) are local-only — no network requests, no subprocess calls, no system modifications. Reference files (PROVIDERS.md, config-patches.json) document optional multi-provider strategies that require external API keys and network access if you choose to use them. See SECURITY.md for full breakdown.
resend-cli
IncludedUse this skill when the task is specifically about operating Resend from an AI agent, terminal session, or CI job via the official resend CLI: installing/authenticating the CLI, sending/listing/updating/cancelling emails, batch sends, domains and DNS, webhooks and local listeners, inbound receiving, contacts, topics, segments, broadcasts, templates, API keys, profiles, or debugging Resend CLI/API failures. Trigger on mentions of Resend CLI, `resend`, `resend doctor`, `resend emails send`, `resend domains`, `resend webhooks listen`, `resend emails receiving`, or agent-friendly terminal automation.
alibabacloud-odps-maxframe-coding
IncludedUse this skill for MaxFrame SDK development and documentation navigation on Alibaba Cloud MaxCompute (ODPS). Helps answer MaxFrame API, concept, official example, and supported pandas API questions; create data processing programs; read/write MaxCompute tables; debug jobs (remote or local); and build custom DPE runtime images. Trigger when users mention MaxFrame, MaxCompute with MaxFrame, ODPS table processing, DPE runtime, MaxFrame docs/examples, DataFrame/Tensor operations, or GPU runtime setup. Works for both English and Chinese queries about Alibaba Cloud data processing with MaxFrame.