3 min read

Deploying to Vercel vs Fly.io: Which Should You Pick?

  • #comparison
  • #tooling

Both show up constantly in side-project deploy conversations, and they solve fairly different problems. Picking wrong doesn’t usually break your project, but it does mean fighting the platform instead of your code for months without noticing that’s what’s happening.

Vercel: you don’t think about servers

It inspects your package.json, figures out you’re running Next.js, Astro, or SvelteKit, and deploys with zero configuration. Push to a branch, get a URL. Open a PR, get a preview URL automatically. Serverless and edge functions are first-class here, not bolted on.

For anything mostly request/response, a blog, a CRUD app, an API reading and writing per request, this is about as frictionless as deploying gets.

Where it falls apart: anything needing a persistent connection. WebSockets, background jobs, a process that needs to stay warm in memory, all of it fights a model built for functions that spin up, respond, and disappear. You end up reaching for a separate service for that one piece, and now your “simple” deploy has two moving parts anyway.

Fly.io: it’s just a real machine

Fly runs your Dockerfile as an actual persistent (or scale-to-zero) machine in a region near your users. WebSockets, cron-style workers, stateful processes all just work, because under the hood this is close to a traditional VPS. A minimal fly.toml looks like this:

app = "my-app"
primary_region = "ord"

[http_service]
  internal_port = 8080
  force_https = true
  auto_stop_machines = true
  auto_start_machines = true
  min_machines_running = 0

fly deploy builds the Dockerfile, ships it, and you have a running container. min_machines_running = 0 is what gets you scale-to-zero: no traffic, no machine, no bill, at the cost of a cold start on the next request.

You manage more of the stack yourself, though. No automatic framework detection, no zero-config preview deploys, and you own graceful restarts and health checks that Vercel handles invisibly. None of it is hard. It’s just work Vercel doesn’t ask you to do, and work you’ll forget you signed up for until a bad deploy takes the whole thing down with no health check to catch it.

Logs and debugging when something breaks

Vercel’s logs are per-invocation and only stick around briefly on the free tier, fine for catching an error right after it happens, less fine for digging into something that happened three days ago. Fly’s logs come from fly logs, streaming straight from the machine, and behave much more like tailing logs on a server you SSH into, because that’s essentially what it is. If you’re the kind of person who wants to grep through yesterday’s logs at 1am, Fly’s model matches that instinct better. If you mostly rely on error tracking (Sentry or similar) instead of raw logs anyway, this difference barely matters in practice.

The part that actually decides it

Forget the feature matrix. Ask one question: does anything in this project need to hold a connection open? If yes, that piece goes on Fly regardless of what else you’re using, because forcing a persistent connection through a serverless model is the single most common way people fight Vercel instead of their code. If no, Vercel wins on convenience alone and there’s no real argument for Fly.

Cost shakes out differently too: Vercel scales with invocations and bandwidth, which handles spiky traffic gracefully but makes a viral moment expensive in a way you can’t predict in advance. Fly bills per machine, closer to a traditional server bill, predictable but flat whether you get ten visitors or ten thousand, up until a machine actually falls over under load and you have to add another one.

Preview deploys are the other thing people underrate when comparing these. Vercel’s per-PR URL is free and automatic; on Fly you’d script something similar with a GitHub Actions workflow that spins up a temporary app per branch and tears it down on merge, which is doable but is now a piece of infrastructure you own and have to keep working. If your team leans on preview links for review, that’s a real point in Vercel’s favor that doesn’t show up on a feature comparison table.

Plenty of side projects end up running both, Vercel for the app shell, Fly for the one component that needs a real machine underneath it. That’s not a compromise. It’s each platform doing the one job it’s actually built for.

My own default is Vercel, and it’s not close. Next.js is my go-to frontend framework for side projects these days, and Vercel is optimized for exactly that pairing in a way no other host quite matches. I only reach for Fly when a specific project has a piece that genuinely needs a persistent connection, not as a default starting point.