Railway runs your app in a region. Fly.io runs it in several, and routes each request to the nearest one. For an app with users on two continents, that’s the difference between 40ms and 300ms on every round trip — and you get it by changing a number, not by rewriting anything.

The unit is a Machine: a fast-booting Firecracker VM running your container image. It can also stop when idle and start on the next request in a couple of hundred milliseconds, which is what makes a multi-region app affordable.

Say this out loud first: there is no free tier

Fly.io removed its free allowances in 2024. New accounts get a short trial, and after that it’s pay-as-you-go — roughly a couple of dollars a month for one small always-on machine, and $10–20 for a typical app with a database.

That’s cheap, and it is not free. If free is the requirement, this is the page to skip: Railway’s Hobby plan or Cloudflare’s genuinely free tiers are the alternatives. Fly.io earns its cost when geography is the problem.

Deploy

  brew install flyctl
fly auth signup

cd my-app
fly launch          # detects the stack, writes fly.toml, offers a Postgres
fly deploy
fly open
  

fly launch reads your project — Dockerfile, or a framework it recognises — and generates fly.toml. The parts you’ll edit:

  app = "my-app"
primary_region = "iad"

[http_service]
  internal_port = 8080
  force_https = true
  auto_stop_machines = "stop"     # scale to zero when idle
  auto_start_machines = true
  min_machines_running = 0        # 1 if a cold start is unacceptable

[[vm]]
  memory = "512mb"
  cpu_kind = "shared"
  cpus = 1
  

auto_stop_machines is the flag that decides your bill. With min_machines_running = 0, an idle app costs almost nothing and pays a cold start on the next request; set it to 1 per region for the apps where that matters.

Going multi-region

  fly scale count 3 --region iad,fra,syd
fly status
fly logs
fly ssh console            # a shell inside the running machine
  

Three commands and the app runs on three continents behind one anycast address. The part that isn’t automatic is your data: reads near the user only help if the data is near the user too. Fly Postgres offers read replicas with writes forwarded to a primary region — workable, but it changes your app’s assumptions, and “replica lag” becomes a thing you have to reason about.

A pragmatic middle path: app servers in several regions, one database region, and Upstash or a CDN in front of the reads that dominate.

What it’s good and bad at

Good fitPoor fit
Latency-sensitive apps with users far apartA single-region CRUD app — simpler hosts win
Long-running processes, WebSockets, queuesStatic sites — Vercel or Pages are free
Anything already containerisedTeams who don’t want to think about regions
Bursty workloads that can scale to zeroA first deploy on a zero budget

Two operational notes worth knowing before you commit: Fly Postgres is an unmanaged Postgres you run, not a managed service with someone else’s pager — use Neon or Supabase if you’d rather not own that. And volumes are tied to a single machine in a single region, so persistent local storage does not replicate; object storage is the answer for anything that must survive.

Next

Push-to-deploy hosting for the frontend → Vercel

Last updated 25 Aug 2026, 00:00 UTC. history