Fly.io socket server auto-stop
Why the WebSocket server gets suspended on Fly.io and how to prevent it
The problem
The circular-socket app on Fly.io keeps getting suspended. When all WebSocket clients disconnect, the machine stops after a few minutes of inactivity, and the app shows as "suspended" in the dashboard.
This happens because of two config values in fly.toml:
Why this is bad for WebSocket servers
auto_stop is designed for HTTP APIs where the proxy can wake machines on incoming requests. But for WebSocket servers:
- When all clients disconnect, Fly's proxy detects "excess capacity" and stops the machine
- Since
min_machines_running = 0, all machines can be stopped - The app becomes "suspended" — no machine is running at all
- New WebSocket connections may fail or have significant latency during cold start
- Socket.io clients get connection errors until the machine finishes booting
The timeline (from real logs)
19:20:53Z Last user disconnected
19:25:31Z "App circular-socket has excess capacity,
autostopping machine 784e964c47ed68.
0 out of 1 machines left running"
19:25:31Z SIGINT → graceful shutdown → exit code 0Less than 5 minutes of inactivity and the machine is gone.
The fix
1. Update fly.toml
2. Apply without redeploying
If you just need to fix a suspended machine without a full deploy:
# Update machine config (disable autostop)
fly machine update --app circular-socket --autostop=off --skip-start -y <MACHINE_ID>
# Start the machine
fly machine start --app circular-socket <MACHINE_ID>
# Verify
fly status --app circular-socket3. Deploy from monorepo root
The Dockerfile expects monorepo context, so deploy from the repo root:
cd /path/to/cute
fly deploy --config apps/socket/fly.tomlRunning fly deploy from apps/socket/ fails because paths like COPY packages/db ./packages/db can't find files relative to the socket directory.
Cost
A shared-cpu-1x with 512MB running 24/7 on Fly.io costs ~$3-5/month. Worth it for a WebSocket server that needs to be always available.
When auto-stop IS appropriate
- HTTP API servers: Fly's proxy can wake machines transparently on incoming requests
- Cron/batch workers: Machines that only need to run periodically
- Preview environments: Low-traffic staging apps
It's not appropriate for:
- WebSocket servers: Clients expect persistent connections
- Any service with long-lived connections: gRPC streams, SSE, etc.