Migrating from Fly.io
Fly.io is purpose-built for global multi-region deploys with anycast routing. If your app actually needs that, and most don't, stay on Fly.io. If you'd rather have one command from your terminal or AI tool, flat pricing, and the option to deploy to your own server, this guide covers the move.
Most Fly.io apps move over with one change: drop the `fly.toml`, run `doable deploy`. The Dockerfile (or auto-detected runtime) does the rest.
Fly's CLI dumps secrets as JSON. Convert to KEY=VALUE format for Doable's import.
fly secrets list --json | node -e "const j=JSON.parse(require('fs').readFileSync(0)); j.forEach(s=>console.log(s.Name+'='))" > .env.fly`fly secrets list` doesn't return values for security reasons. Edit the file to fill in each secret's value (you have these locally or in your password manager).
One-time setup.
npm install -g doable-cli && doable loginFrom your repo directory. Doable reads your Dockerfile (or auto-detects runtime if there isn't one).
doable projects createEncrypted at rest, injected at container start.
doable env import .env.flyFly Postgres: `pg_dump` from your Fly app, restore into Neon (or Supabase, Upstash), then `doable addon attach postgres <new-url>`. LiteFS / SQLite users: copy the SQLite file into your build context if you can use a single-region SQLite, or migrate to Postgres.
First deploy hits a cold cache. Subsequent deploys reuse layers.
doable deployPoint your custom domain at Doable. CNAME for subdomains, A for apex. Let's Encrypt provisions HTTPS within a minute.
doable domain connect <hostname>Your Dockerfile. Fly users almost always have one and Doable uses it as-is, no platform-specific build steps to refactor.
Container shape: same `EXPOSE`, same env vars, same entrypoint. The container that ran on a Fly Machine runs identically on Doable.
Build cache behaviour. Both platforms reuse layers between deploys when possible.
No multi-region. Doable Cloud runs single-region; BYO supports any number of regions but each project deploys to one server. If you need true global multi-region with anycast routing, Fly is purpose-built for it and probably worth keeping for that specific app.
No `fly.toml`. Doable's config lives on the project (env vars, custom domains) and the rest is auto-detected. The escape hatch for unusual setups is a Dockerfile.
Pricing: flat $0/$15/$39 vs. Fly's per-machine + per-volume + per-region usage billing. For single-region apps Doable is almost always cheaper; for multi-region, you're paying for something Doable doesn't offer yet.
Database: bring an external one via `doable addon attach`. Fly Postgres / LiteFS users typically move to Neon (Postgres) or keep SQLite-in-the-image if their data fits.
Yes for almost all Fly Dockerfiles. The shape is the same, `EXPOSE`, `CMD`, env vars all work identically. The only changes typically needed are removing Fly-specific entrypoint scripts (e.g. ones that read `fly.toml` or `FLY_REGION`).
Migrate to Neon, Supabase, or Upstash. `pg_dump` from your Fly Postgres connection string, restore to the new provider, then `doable addon attach postgres <new-url>`. Most databases under a few GB migrate in 5–15 minutes.
If your data fits in the build context (small / mostly read), bake the SQLite file into your image. Otherwise, migrate to Postgres on Neon and `doable addon attach`. There's no LiteFS equivalent on Doable today.
Yes, Doable runs single-region. For most apps the latency difference is small; for apps where it matters (interactive multiplayer, latency-sensitive APIs serving global traffic), Fly is the better fit and worth keeping.
No credit card. Deploy your first project in under a minute.