Files
2026-03-17 16:53:22 -07:00

4.5 KiB

Gotchas & Debugging

Common Errors

"Step Timeout"

Cause: Step execution exceeding 10 minute default timeout or configured timeout
Solution: Set custom timeout with step.do('long operation', {timeout: '30 minutes'}, async () => {...}) or increase CPU limit in wrangler.jsonc (max 5min CPU time)

"waitForEvent Timeout"

Cause: Event not received within timeout period (default 24h, max 365d)
Solution: Wrap in try-catch to handle timeout gracefully and proceed with default behavior

"Non-Deterministic Step Names"

Cause: Using dynamic values like Date.now() in step names causes replay issues
Solution: Use deterministic values like event.instanceId for step names

"State Lost in Variables"

Cause: Using module-level or local variables to store state which is lost on hibernation
Solution: Return values from step.do() which are automatically persisted: const total = await step.do('step 1', async () => 10)

"Non-Deterministic Conditionals"

Cause: Using non-deterministic logic (like Date.now()) outside steps in conditionals
Solution: Move non-deterministic operations inside steps: const isLate = await step.do('check', async () => Date.now() > deadline)

"Large Step Returns Exceeding Limit"

Cause: Returning data >1 MiB from step
Solution: Store large data in R2 and return only reference: { key: 'r2-object-key' }

"Step Exceeded CPU Limit But Ran for < 30s"

Cause: Confusion between CPU time (active compute) and wall-clock time (includes I/O waits)
Solution: Network requests, database queries, and sleeps don't count toward CPU. 30s limit = 30s of active processing

"Idempotency Violation"

Cause: Step operations not idempotent, causing duplicate charges or actions on retry
Solution: Check if operation already completed before executing (e.g., check if customer already charged)

"Instance ID Collision"

Cause: Reusing instance IDs causing conflicts
Solution: Use unique IDs with timestamp: await env.MY_WORKFLOW.create({ id: \${userId}-${Date.now()}`, params: {} })`

"Instance Data Disappeared After Completion"

Cause: Completed/errored instances are automatically deleted after retention period (3 days free / 30 days paid)
Solution: Export critical data to KV/R2/D1 before workflow completes

"Missing await on step.do"

Cause: Forgetting to await step.do() causing fire-and-forget behavior
Solution: Always await step operations: await step.do('task', ...)

Limits

Limit Free Paid Notes
CPU per step 10ms 30s (default), 5min (max) Set via limits.cpu_ms in wrangler.jsonc
Step state 1 MiB 1 MiB Per step return value
Instance state 100 MB 1 GB Total state per workflow instance
Steps per workflow 1,024 1,024 step.sleep() doesn't count
Executions per day 100k Unlimited Daily execution limit
Concurrent instances 25 10k Maximum concurrent workflows; waiting state excluded
Queued instances 100k 1M Maximum queued workflow instances
Subrequests per step 50 1,000 Maximum outbound requests per step
State retention 3 days 30 days How long completed instances kept
Step timeout default 10 min 10 min Per attempt
waitForEvent timeout default 24h 24h Maximum 365 days
waitForEvent timeout max 365 days 365 days Maximum wait time

Note: Instances in waiting state (from step.sleep or step.waitForEvent) don't count toward concurrent instance limit, allowing millions of sleeping workflows.

Pricing

Metric Free Paid Notes
Requests 100k/day 10M/mo + $0.30/M Workflow invocations
CPU time 10ms/invoke 30M CPU-ms/mo + $0.02/M CPU-ms Actual CPU usage
Storage 1 GB 1 GB/mo + $0.20/GB-mo All instances (running/errored/sleeping/completed)

References

See: README.md, configuration.md, api.md, patterns.md