DURABLE OBJECTS GOTCHAS

The quiz you wish you had before your first surprise bill

QUIZ FORMAT 2025.12.16

Problem: Durable Objects billing is deceptively nuanced. Most people discover the gotchas after getting an unexpected bill.

Solution: Self-diagnosis quiz. Click to reveal answers. Learn before you deploy.

GOTCHA #1: DURATION BILLING TRAP

Scenario: You have a DO that handles a WebSocket connection for a real-time dashboard. User connects at 9am, disconnects at 5pm. During that time, the DO processes maybe 50 small messages total.

Question: What's your biggest cost driver here?

  • A) The 50 request invocations
  • B) 8 hours of wall-clock duration
  • C) CPU time processing the messages
  • D) Storage for connection state

GOTCHA #2: STORAGE.LIST() ON EVERY REQUEST

Scenario: Your DO stores user preferences (20 keys). On each request, you need 3 of those keys.

Question: What's the cheapest read pattern?

  • A) storage.get(['key1', 'key2', 'key3'])
  • B) storage.list() once on wake, cache in memory
  • C) Single storage.get('preferences') with all 20 keys as one object
  • D) It depends—on what?

GOTCHA #3: ALARM RECURSION

Scenario: You're using storage.setAlarm() to wake a DO every 5 minutes to check for stale data. The check takes 2ms of CPU time.

Question: Over 24 hours, what's happening to your costs that you might not expect?

GOTCHA #4: WEBSOCKET NEVER CLOSES

Scenario: Your DO handles WebSocket connections. Users sometimes close their browser tabs without properly disconnecting.

Question: What happens if you never call webSocket.close() on disconnect?

GOTCHA #5: SINGLETON VS SHARDING

Scenario: You're building a rate limiter. Design A uses one global DO. Design B creates one DO per user. Design C creates one DO per user-per-hour (ephemeral).

Question: For 10,000 users making 100 requests/day each, rank these by cost (cheapest to most expensive).

GOTCHA #6: STORAGE.GET() VS BATCHING

Scenario: You need to read 5 keys from storage on each request.

Question: Is it cheaper to call storage.get(['key1', 'key2', 'key3', 'key4', 'key5']) or make 5 separate storage.get() calls?

GOTCHA #7: HIBERNATION CONFUSION

Scenario: Your DO needs to respond to requests but also run background work every 10 minutes.

Question: How do you structure this so the DO can hibernate between alarm intervals, but still handle incoming requests without "waking up" a new instance that doesn't have warm state?

GOTCHA #8: FAN-OUT TAX

Scenario: You have an event that needs to notify 1,000 DOs. Each notification is tiny (100 bytes).

Question: What's the cost difference between a Worker making 1,000 stub.fetch() calls in parallel vs using a queue/alarm pattern?

GOTCHA #9: IDEMPOTENCY KEY EXPLOSION

Scenario: You're using DOs for idempotency. Each request gets a unique idempotency key. You create one DO per key.

Question: What happens if you create a new DO instance for each idempotency key that's used once?

GOTCHA #10: STORAGE COMPACTION

Scenario: You're writing events to DO storage. Each event is 100 bytes. You write 1 event per request.

Question: What's the cost difference between writing 1 item per event vs batching 100 events per write?

GOTCHA #11: WAITUNTIL() IN DOS

Scenario: You want to do background work after returning a response. You use waitUntil() like in Workers.

Question: Does waitUntil() work in DOs the same way it works in Workers?

GOTCHA #12: KV VS DO STORAGE

Scenario: You need to store user session data. It's read-heavy (20 reads per write), write-rare.

Question: Should you use KV or DO storage?

RED FLAGS CHECKLIST

Rate yourself 1-5 on whether you'd catch these in a code review:

  • DO with WebSocket that never calls close() on disconnect
  • setAlarm() inside the alarm handler without conditional logic
  • storage.list() on every request instead of caching
  • Creating new DO instances for idempotency keys that are used once
  • Using DO storage for data that could live in KV (read-heavy, write-rare)
  • Keeping request context alive with waitUntil() inside a DO

Score: 0-2 = You'll get surprised by bills. 3-4 = You'll catch most issues. 5 = You're ready to optimize.

PROVE YOU KNOW CLOUDFLARE

95 questions. AI grading. No multiple choice safety net.

TRY CF-TUTORIAL
Get new posts by email.
Join 6 other subscribers.