Volume-backed Fly.io deploys. First push creates the infrastructure; every edit after that syncs only changed files in ~200 ms–1 s.
What it is
Fly.io Live is a deploy provider that decouples infrastructure from content. The Docker image contains only a lightweight web server and a signed sync endpoint. Your site's files live on a persistent Fly Volume. Publishing a content change uploads only the changed files — not the whole image.
Result: typical text edit is live in 200 ms–1 s, vs. ~30–120 s for a full Docker rebuild.
When to use Fly.io Live
- You want everything in Fly (EU data residency, same account as your other services)
- Your site is static (build.ts outputs HTML/CSS/JS/images)
- You want "save in CMS → live" feedback without waiting on Docker
- You also run Fly apps for dynamic services (forms, auth, SSR pages) and want the static content there too
When NOT to use it
If your site is pure static with no Fly requirement, Cloudflare Pages is faster (300+ PoPs) and free. Fly Live is single-region by default — use only if you have a Fly-specific reason.
If your site is a Next.js SSR app or a custom server, use the classic Fly.io (rebuild) provider — SSR apps can't be expressed as static files.
How it works
First deploy (infrastructure setup)
- CMS admin runs
flyctl apps create,flyctl volumes create - Generates an HMAC secret and stores it in Fly Secrets as
SYNC_SECRET - Builds and deploys the sync-endpoint Docker image (Caddy/Bun serving from the volume)
- Waits for
/_icd/healthto respond - Does the first content sync
This takes about 30–60 seconds, one time.
Subsequent deploys (content sync, every save)
- CMS admin builds your site locally (
deploy/) - Fetches the remote file manifest:
GET /_icd/manifest→{ files: { path: sha256 } } - Diffs against local — computes
{ added, changed, removed, unchanged } POST /_icd/deploys→ begins a new staging deployPUTeach changed/added file,DELETEeach removed filePOST /_icd/deploys/:id/commit→ atomic symlink swap on the server
Transport is HMAC-SHA256 signed (same pattern as Instant Content Deployment). All requests expire after 5 minutes.
Atomic deploys
Each deploy lives in its own directory under /srv/deploys/<id>/. On commit, the server atomically swaps the /srv/current symlink to point at the new directory. Requests in flight never see a half-updated tree. The server keeps the last 5 deploys for rollback; older ones are pruned.
Setup
1. Configure the provider
Settings → Deploy → Fly.io Live (instant sync). Provide:
- API token — Fly personal access token (get one)
- App name — auto-generated from your site name if left empty
- Region — default
arn(Stockholm); pick the closest Fly region to your users - Volume name — default
site_data; you rarely need to change this
The organisation slug is auto-detected from your token.
2. Click Deploy
First click provisions the infrastructure and then does the first content sync. You'll see the live URL (https://<app-name>.fly.dev) when it completes.
3. Subsequent saves
Once set up, every deploy is fast. Enable Deploy on save in the same panel if you want auto-publish on content changes.
Rebuilding infrastructure
The Docker image rarely needs rebuilding. When cms-admin ships a new version of the sync-endpoint server, the admin UI surfaces a "Rebuild infrastructure" prompt — click it to refresh the image. Volume data is preserved, so content survives rebuilds.
Triggers that require an infra rebuild:
- cms-admin update with a new sync-endpoint version
- Custom server configuration (headers, redirects) — requires editing the image template
- Fly machine resize (memory, CPU) — via
fly.toml
Custom domain
Add your domain in Settings → Deploy → Custom domain. Fly Live automatically runs flyctl certs add on the next deploy. Configure the DNS records at your registrar per Fly's instructions.
Limitations
- Single-region: Fly volumes are region-pinned. For global low latency, pair with a CDN in front, or use Cloudflare Pages instead.
- One writer: The volume has one primary machine. Don't scale horizontally without understanding Fly volume semantics.
- 1 GB volume default: Fine for most sites (content is small). Resize via
flyctl volumes extendif needed.
Troubleshooting
"Sync endpoint did not come online" — first deploy timed out waiting for the container. Check Fly logs: flyctl logs -a <app-name>. Most common cause: the volume failed to mount.
"Invalid signature" on sync requests — the SYNC_SECRET in Fly Secrets got out of sync with the CMS config. Re-run the deploy; the admin will regenerate and push a new secret.
"Version mismatch, rebuilding infra" — expected when you upgrade cms-admin to a version with a newer sync-endpoint. Let it run; the rebuild takes ~60 s.
Comparison
| Fly.io Live | Fly.io (rebuild) | Cloudflare Pages | GitHub Pages | |
|---|---|---|---|---|
| Time per content edit | ~200 ms–1 s | 30–120 s | 3–10 s | 15–30 s |
| Global edge | No (1 region) | No | Yes (300+ PoPs) | Yes (CDN) |
| SSR support | No (static only) | Yes | Workers only | No |
| Monthly cost (small site) | ~$3–5 | ~$3–5 | $0 | $0 |
| When to pick it | Fly ecosystem | Next.js / SSR apps | Pure static, global | Open-source projects |
Related
- Cloudflare Pages — alternative for pure static
- Instant Content Deployment (ICD) — the same HMAC pattern used for Next.js revalidation
- Deploy settings — full provider reference
- Fly.io (rebuild) — the Docker-rebuild-every-deploy path (SSR apps)