Skip to main content
WebSockets work on Fly.io without extra configuration. An app with an [http_service] section accepts ws:// and wss:// connections, and Fly Proxy passes the upgraded connection through to your app.

Idle connections stay open

Fly Proxy doesn’t close idle WebSocket connections. A connection with no traffic stays open until your app or the client closes it. A connection can still close for reasons outside your app:
  • Fly Proxy restarts. When we deploy a new version of the proxy, it closes open WebSockets with a close frame.
  • Autostop stops the Machine. See WebSockets and autostop.
  • You deploy your app. Each Machine restarts during a deploy, so its connections close.
  • Something else on the network drops it. Corporate proxies, load balancers and mobile networks often drop connections that have been idle for a while.
So every WebSocket client should reconnect when its connection closes, and long-lived connections should send a heartbeat.

Close codes

When Fly Proxy closes a WebSocket because it’s restarting or because the Machine is stopping, it waits for the current message to finish and then sends a close frame with the reason restarting: Treat 1012 as a signal to reconnect. The new connection goes to a running Machine.

Send a heartbeat

A heartbeat is a small message sent at a regular interval, usually a WebSocket ping that the other side answers with a pong. It keeps intermediate networks from treating the connection as idle, and it lets each side notice when the other has gone away without closing the connection. Send one every 30 seconds or so. Some libraries do this for you. Phoenix Channels: The phoenix JavaScript client sends a heartbeat every 30 seconds and reconnects with backoff when the connection drops. You don’t need to change anything. To change the interval, set heartbeatIntervalMs:
Socket.IO: The server pings each client every 25 seconds (pingInterval) and drops clients that don’t answer within 20 seconds (pingTimeout). The client reconnects automatically. These are the defaults:
ws for Node.js: The ws library has no built-in heartbeat. Ping each client on an interval and drop the ones that didn’t answer the last ping:
Browsers answer pings automatically. In the browser, reconnect when the connection closes. Add a random delay so that clients don’t all reconnect at once after a restart:

WebSockets and autostop

With autostop, Fly Proxy stops a Machine when the app’s other Machines can handle the current load. Open WebSockets count toward that load, but they don’t keep a Machine running: the proxy spreads connections evenly across Machines, so the Machine it stops usually has some open. Before it stops a Machine, the proxy stops sending it new traffic and closes its open WebSockets with code 1012. Clients that reconnect are routed to a Machine that’s still running. Raw TCP services work the same way: autostop can close their open connections too. If you use autostop, make sure your clients reconnect. To keep one Machine running at all times in your primary region, set min_machines_running:
If your connections must not be interrupted by autostop, turn it off with auto_stop_machines = "off". Connections can still close during deploys and proxy restarts.