Files
dotfiles/.agents/skills/cloudflare-deploy/references/containers/gotchas.md
2026-03-17 16:53:22 -07:00

4.4 KiB

Critical Gotchas

⚠️ WebSocket: fetch() vs containerFetch()

Problem: WebSocket connections fail silently

Cause: containerFetch() doesn't support WebSocket upgrades

Fix: Always use fetch() for WebSocket

// ❌ WRONG
return container.containerFetch(request);

// ✅ CORRECT
return container.fetch(request);

⚠️ startAndWaitForPorts() vs start()

Problem: "connection refused" after start()

Cause: start() returns when process starts, NOT when ports ready

Fix: Use startAndWaitForPorts() before requests

// ❌ WRONG
await container.start();
return container.fetch(request);

// ✅ CORRECT
await container.startAndWaitForPorts();
return container.fetch(request);

⚠️ Activity Timeout on Long Operations

Problem: Container stops during long work

Cause: sleepAfter based on request activity, not internal work

Fix: Renew timeout by touching storage

const interval = setInterval(() => {
  this.ctx.storage.put("keepalive", Date.now());
}, 60000);

try {
  await this.doLongWork(data);
} finally {
  clearInterval(interval);
}

⚠️ blockConcurrencyWhile for Startup

Problem: Race conditions during initialization

Fix: Use blockConcurrencyWhile for atomic initialization

await this.ctx.blockConcurrencyWhile(async () => {
  if (!this.initialized) {
    await this.startAndWaitForPorts();
    this.initialized = true;
  }
});

⚠️ Lifecycle Hooks Block Requests

Problem: Container unresponsive during onStart()

Cause: Hooks run in blockConcurrencyWhile - no concurrent requests

Fix: Keep hooks fast, avoid long operations

⚠️ Don't Override alarm() When Using schedule()

Problem: Scheduled tasks don't execute

Cause: schedule() uses alarm() internally

Fix: Implement alarm() to handle scheduled tasks

Common Errors

"Container start timeout"

Cause: Container took >8s (start()) or >20s (startAndWaitForPorts())

Solutions:

  • Optimize image (smaller base, fewer layers)
  • Check entrypoint correct
  • Verify app listens on correct ports
  • Increase timeout if needed

"Port not available"

Cause: Calling fetch() before port ready

Solution: Use startAndWaitForPorts()

"Container memory exceeded"

Cause: Using more memory than instance type allows

Solutions:

  • Use larger instance type (standard-2, standard-3, standard-4)
  • Optimize app memory usage
  • Use custom instance type
"instance_type_custom": {
  "vcpu": 2,
  "memory_mib": 8192
}

"Max instances reached"

Cause: All max_instances slots in use

Solutions:

  • Increase max_instances
  • Implement proper sleepAfter
  • Use getRandom() for distribution
  • Check for instance leaks

"No container instance available"

Cause: Account capacity limits reached

Solutions:

  • Check account limits
  • Review instance types across containers
  • Contact Cloudflare support

Limits

Resource Limit Notes
Cold start 2-3s Image pre-fetched globally
Graceful shutdown 15 min SIGTERM → SIGKILL
start() timeout 8s Process start
startAndWaitForPorts() timeout 20s Port ready
Max vCPU per container 4 standard-4 or custom
Max memory per container 12 GiB standard-4 or custom
Max disk per container 20 GB Ephemeral, resets
Account total memory 400 GiB All containers
Account total vCPU 100 All containers
Account total disk 2 TB All containers
Image storage 50 GB Per account
Disk persistence None Use DO storage

Best Practices

  1. Use startAndWaitForPorts() by default - Prevents port errors
  2. Set appropriate sleepAfter - Balance resources vs cold starts
  3. Use fetch() for WebSocket - Not containerFetch()
  4. Design for restarts - Ephemeral disk, implement graceful shutdown
  5. Monitor resources - Stay within account limits
  6. Keep hooks fast - Run in blockConcurrencyWhile
  7. Renew activity for long ops - Touch storage to prevent timeout

Beta Caveats

⚠️ Containers in beta:

  • API may change without notice
  • No SLA guarantees
  • Limited regions initially
  • No autoscaling - manual via getRandom()
  • Rolling deploys only (not instant like Workers)

Plan for API changes, test thoroughly before production.