Chapter 04 · Cloudflare Deploy
Subchapter 4.64
references/containers/gotchas.mdMarkdown4 KBView on GitHub
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);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);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);
}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;
}
});Problem: Container unresponsive during onStart()
Cause: Hooks run in blockConcurrencyWhile - no concurrent requests
Fix: Keep hooks fast, avoid long operations
Problem: Scheduled tasks don’t execute
Cause: schedule() uses alarm() internally
Fix: Implement alarm() to handle scheduled tasks
Cause: Container took >8s (start()) or >20s (startAndWaitForPorts())
Solutions:
entrypoint correctCause: Calling fetch() before port ready
Solution: Use startAndWaitForPorts()
Cause: Using more memory than instance type allows
Solutions:
"instance_type_custom": {
"vcpu": 2,
"memory_mib": 8192
}Cause: All max_instances slots in use
Solutions:
max_instancessleepAftergetRandom() for distributionCause: Account capacity limits reached
Solutions:
| 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 |
startAndWaitForPorts() by default - Prevents port errorssleepAfter - Balance resources vs cold startsfetch() for WebSocket - Not containerFetch()blockConcurrencyWhile⚠️ Containers in beta:
getRandom()Plan for API changes, test thoroughly before production.