Marketplace
durable-objects-pattern-checker
Automatically validates Cloudflare Durable Objects usage patterns, ensuring correct state management, hibernation, and strong consistency practices
$ Installieren
git clone https://github.com/hirefrank/hirefrank-marketplace /tmp/hirefrank-marketplace && cp -r /tmp/hirefrank-marketplace/plugins/edge-stack/skills/durable-objects-pattern-checker ~/.claude/skills/hirefrank-marketplace// tip: Run this command in your terminal to install the skill
SKILL.md
name: durable-objects-pattern-checker description: Automatically validates Cloudflare Durable Objects usage patterns, ensuring correct state management, hibernation, and strong consistency practices triggers: ["Durable Object imports", "DO stub usage", "state management patterns", "DO ID generation"]
Durable Objects Pattern Checker SKILL
Activation Patterns
This SKILL automatically activates when:
- Durable Object imports or exports are detected
- DO stub creation and usage patterns
- State management in Durable Objects
- ID generation patterns (
idFromName,newUniqueId) - Hibernation and lifecycle patterns
- WebSocket or real-time features with DOs
Expertise Provided
Durable Objects Best Practices
- State Management: Ensures proper state persistence and consistency
- ID Generation: Validates correct ID patterns for different use cases
- Hibernation: Checks for proper hibernation implementation
- Lifecycle Management: Validates constructor, fetch, and alarm handling
- Strong Consistency: Ensures DOs are used when strong consistency is needed
- Performance: Identifies DO performance anti-patterns
Specific Checks Performed
â Durable Objects Anti-Patterns
// These patterns trigger immediate alerts:
// Using DOs for stateless operations
export default {
async fetch(request: Request, env: Env) {
const id = env.COUNTER.newUniqueId(); // New DO every request!
const stub = env.COUNTER.get(id);
return stub.fetch(request); // Overkill for simple counter
}
}
// Missing hibernation for long-lived DOs
export class ChatRoom {
constructor(state, env) {
this.state = state;
// Missing this.state.storage.setAlarm() for hibernation
}
}
â Durable Objects Best Practices
// These patterns are validated as correct:
// Reuse DO instances for stateful coordination
export default {
async fetch(request: Request, env: Env) {
const ip = request.headers.get('CF-Connecting-IP');
const id = env.RATE_LIMITER.idFromName(ip); // Reuse same DO
const stub = env.RATE_LIMITER.get(id);
return stub.fetch(request);
}
}
// Proper hibernation implementation
export class ChatRoom {
constructor(state, env) {
this.state = state;
this.env = env;
// Set alarm for hibernation after inactivity
this.state.storage.setAlarm(Date.now() + 30000); // 30 seconds
}
alarm() {
// DO will hibernate after alarm
}
}
Integration Points
Complementary to Existing Components
- cloudflare-architecture-strategist agent: Handles complex DO architecture, SKILL provides immediate pattern validation
- edge-performance-oracle agent: Handles DO performance analysis, SKILL ensures correct usage patterns
- workers-binding-validator SKILL: Ensures DO bindings are correct, SKILL validates usage patterns
Escalation Triggers
- Complex DO architecture questions â
cloudflare-architecture-strategistagent - DO performance troubleshooting â
edge-performance-oracleagent - DO migration strategies â
cloudflare-architecture-strategistagent
Validation Rules
P1 - Critical (Will Cause Issues)
- New Unique ID Per Request: Creating new DO for every request
- Missing Hibernation: Long-lived DOs without hibernation
- State Leaks: State not properly persisted to storage
- Blocking Operations: Synchronous operations in DO fetch
P2 - High (Performance/Correctness Issues)
- Wrong ID Pattern: Using
newUniqueIdwhenidFromNameis appropriate - Stateless DOs: Using DOs for operations that don't need state
- Missing Error Handling: DO operations without proper error handling
- Alarm Misuse: Incorrect alarm patterns for hibernation
P3 - Medium (Best Practices)
- State Size: Large state objects that impact performance
- Concurrency: Missing concurrency control for shared state
- Cleanup: Missing cleanup in DO lifecycle
Remediation Examples
Fixing New Unique ID Per Request
// â Critical: New DO for every request (expensive and wrong)
export default {
async fetch(request: Request, env: Env) {
const userId = getUserId(request);
// Creates new DO instance for every request!
const id = env.USER_SESSION.newUniqueId();
const stub = env.USER_SESSION.get(id);
return stub.fetch(request);
}
}
// â
Correct: Reuse DO for same entity
export default {
async fetch(request: Request, env: Env) {
const userId = getUserId(request);
// Reuse same DO for this user
const id = env.USER_SESSION.idFromName(userId);
const stub = env.USER_SESSION.get(id);
return stub.fetch(request);
}
}
Fixing Missing Hibernation
// â High: DO never hibernates (wastes resources)
export class ChatRoom {
constructor(state, env) {
this.state = state;
this.env = env;
this.messages = [];
}
async fetch(request) {
// Handle chat messages...
// But never hibernates - stays in memory forever!
}
}
// â
Correct: Implement hibernation
export class ChatRoom {
constructor(state, env) {
this.state = state;
this.env = env;
// Load persisted state
this.loadState();
// Set alarm for hibernation after inactivity
this.resetHibernationTimer();
}
async loadState() {
const messages = await this.state.storage.get('messages');
this.messages = messages || [];
}
resetHibernationTimer() {
// Reset alarm for 30 seconds from now
this.state.storage.setAlarm(Date.now() + 30000);
}
async fetch(request) {
// Reset timer on activity
this.resetHibernationTimer();
// Handle chat messages...
return new Response('Message processed');
}
async alarm() {
// Persist state before hibernation
await this.state.storage.put('messages', this.messages);
// DO will hibernate after this method returns
}
}
Fixing Wrong ID Pattern
// â High: Using newUniqueId for named resources
export default {
async fetch(request: Request, env: Env) {
const roomId = new URL(request.url).searchParams.get('room');
// Wrong: Creates new DO for same room name
const id = env.CHAT_ROOM.newUniqueId();
const stub = env.CHAT_ROOM.get(id);
return stub.fetch(request);
}
}
// â
Correct: Use idFromName for named resources
export default {
async fetch(request: Request, env: Env) {
const roomId = new URL(request.url).searchParams.get('room');
// Correct: Same DO for same room name
const id = env.CHAT_ROOM.idFromName(roomId);
const stub = env.CHAT_ROOM.get(id);
return stub.fetch(request);
}
}
Fixing State Persistence
// â Critical: State not persisted (lost on hibernation)
export class Counter {
constructor(state, env) {
this.state = state;
this.count = 0; // Not persisted!
}
async fetch(request) {
if (request.url.endsWith('/increment')) {
this.count++; // Lost when DO hibernates!
return new Response(`Count: ${this.count}`);
}
}
}
// â
Correct: Persist state to storage
export class Counter {
constructor(state, env) {
this.state = state;
}
async fetch(request) {
if (request.url.endsWith('/increment')) {
// Persist to storage
const currentCount = (await this.state.storage.get('count')) || 0;
const newCount = currentCount + 1;
await this.state.storage.put('count', newCount);
return new Response(`Count: ${newCount}`);
}
if (request.url.endsWith('/get')) {
const count = await this.state.storage.get('count') || 0;
return new Response(`Count: ${count}`);
}
}
}
Fixing Stateless DO Usage
// â High: Using DO for stateless operation (overkill)
export default {
async fetch(request: Request, env: Env) {
// Using DO for simple API call - unnecessary!
const id = env.API_PROXY.newUniqueId();
const stub = env.API_PROXY.get(id);
return stub.fetch(request);
}
}
// â
Correct: Handle stateless operations in Worker
export default {
async fetch(request: Request, env: Env) {
// Simple API call - handle directly in Worker
const response = await fetch('https://api.example.com/data');
return response;
}
}
// â
Correct: Use DO for actual stateful coordination
export default {
async fetch(request: Request, env: Env) {
const ip = request.headers.get('CF-Connecting-IP');
// Rate limiting needs state - perfect for DO
const id = env.RATE_LIMITER.idFromName(ip);
const stub = env.RATE_LIMITER.get(id);
return stub.fetch(request);
}
}
Durable Objects Use Cases
Use Durable Objects When:
- Strong Consistency required (rate limiting, counters)
- Stateful Coordination (chat rooms, game sessions)
- Real-time Features (WebSockets, collaboration)
- Distributed Locks (coordination between requests)
- Long-running Operations (background processing)
Don't Use Durable Objects When:
- Stateless Operations (simple API calls)
- Read-heavy Caching (use KV instead)
- Large File Storage (use R2 instead)
- Simple Key-Value (use KV instead)
MCP Server Integration
When Cloudflare MCP server is available:
- Query DO performance metrics and best practices
- Get latest hibernation patterns and techniques
- Check DO usage limits and quotas
- Analyze DO performance in production
Benefits
Immediate Impact
- Prevents Resource Waste: Catches DO anti-patterns that waste resources
- Ensures Correctness: Validates state persistence and consistency
- Improves Performance: Identifies performance issues in DO usage
Long-term Value
- Consistent DO Patterns: Ensures all DO usage follows best practices
- Better Resource Management: Proper hibernation and lifecycle management
- Reduced Costs: Efficient DO usage reduces resource consumption
Usage Examples
During DO Creation
// Developer types: const id = env.MY_DO.newUniqueId();
// SKILL immediately activates: "â ïž HIGH: Using newUniqueId for every request. Consider idFromName for named resources or if this should be stateless."
During State Management
// Developer types: this.count = 0; in constructor
// SKILL immediately activates: "â CRITICAL: State not persisted to storage. Use this.state.storage.put() to persist data."
During Hibernation
// Developer types: DO without alarm() method
// SKILL immediately activates: "â ïž HIGH: Durable Object missing hibernation. Add alarm() method and setAlarm() for resource efficiency."
Performance Targets
DO Creation
- Excellent: Reuse existing DOs (idFromName)
- Good: Minimal new DO creation
- Acceptable: Appropriate DO usage patterns
- Needs Improvement: Creating new DOs per request
State Persistence
- Excellent: All state persisted to storage
- Good: Critical state persisted
- Acceptable: Basic state management
- Needs Improvement: State not persisted
Hibernation
- Excellent: Proper hibernation implementation
- Good: Basic hibernation setup
- Acceptable: Some hibernation consideration
- Needs Improvement: No hibernation (resource waste)
This SKILL ensures Durable Objects are used correctly by providing immediate, autonomous validation of DO patterns, preventing common mistakes and ensuring efficient state management.
Repository

hirefrank
Author
hirefrank/hirefrank-marketplace/plugins/edge-stack/skills/durable-objects-pattern-checker
2
Stars
0
Forks
Updated2d ago
Added1w ago