Fly.io

Single-machine app hosting for druthers-gsx — dev→staging, main→prod, scale-to-zero.

Goals

Run a low-traffic ranked-choice-polling app (druthers-gsx) across two environments (prod druthers-gsx, staging druthers-gsx-staging) with automatic CI-driven deploys, without paying for always-on compute. Dogfooded repeatedly 2026-08-02/03: shipping an image-clear feature through the full pipeline, a staging-only entitlement-override feature, and two live bug investigations against the deployed staging app.

Effectiveness

Recommended for this shape of workload. Once the pipeline is set up, a green push to dev or main is the entire deploy story — no manual flyctl deploy in the common case. Scale-to-zero means an idle side project costs nothing between visits, and cold starts were fast enough (machine reachable in single-digit milliseconds to ~1.4s in the logs) that it never became a user-facing problem during testing.

What made it effective

Friction / pain points / surprises

flyctl isn't on PATH by default. It lives at ~/.fly/bin/flyctl; every fresh shell needs export PATH="$HOME/.fly/bin:$PATH" or an alias, or the command silently isn't found.

flyctl apps list labels the prod app "suspended," not "scale-to-zero-idle." At a glance this reads like an incident, not the expected steady state of a healthy low-traffic app between visits.

CI carries a live deprecation warning that's easy to ignore because it still passes. A gh run watch on staging surfaced: "Node.js 20 is deprecated. The following actions target Node.js 20 but are being forced to run on Node.js 24: actions/checkout@v4, actions/setup-go@v5, actions/setup-node@v4, pnpm/action-setup@v3." Green build, so nothing forced the fix — it's the kind of thing that only gets addressed when someone happens to be watching the log, which is exactly what happened here.

Scale-to-zero cold-start logs are indistinguishable from a crash-restart loop unless you read timestamps carefully. A tail of flyctl logs shows repeated "Starting machine → ... → Sending signal SIGINT → reboot: Restarting system" cycles roughly every 6-90 minutes; this is auto_stop_machines doing its job, not instability, but it looks alarming out of context.