
There is a standard arc to how developers make hosting decisions. You ship something on Vercel because it is fast and free. Traffic grows, or you add a teammate, and the bill shows up. You Google "Vercel alternatives," read four posts that all say "just use a VPS," spend a weekend setting up nginx, question your career, and end up back on Vercel paying $20 a seat. Fly.io appears in the comments of every one of those threads and no one seems to explain it properly.
This post is an attempt at the actual explanation. Not a feature grid. Not a paragraph that says "Vercel is great for beginners" and calls it a day. Three platforms, three genuinely different execution models, real pricing numbers, and a straight answer on when each one makes sense.
The Three Machines
Before the pricing matters, the architecture matters. These platforms do not just charge differently -- they run your code differently, and that distinction drives every other trade-off.
Vercel is a serverless platform. When a request hits a Vercel function, the platform boots a sandboxed execution environment, runs your code, and tears it down. Nothing persists between requests unless you explicitly store state externally. Vercel built this model to handle arbitrary traffic spikes without any configuration from you, and it works -- but the model shapes what your application can and cannot do. Long-running processes, persistent in-memory caches, WebSocket connections, background workers: none of these are natural fits for a request-scoped function runtime.
A VPS is a rented Linux box. You get root. You install what you want, run what you want, and keep it running as long as you want. The process that handles your HTTP request at 3 AM is the same process that was running at noon. Nothing spins up on demand. Nothing tears down after the response. This model gives you total control and zero automatic scaling. If traffic doubles at midnight and your box cannot handle it, the box falls over.
Fly.io occupies a third position that most comparisons skip. It runs your workloads inside Firecracker microVMs -- hardware-virtualized containers that boot in sub-second timeframes, much faster than a traditional VM but with stronger isolation than a plain Docker container. You push a Docker image, specify regions, and Fly handles scheduling, TLS termination, health checks, and routing. The process that handles your request is a long-lived container, not an ephemeral function. You get persistent state, WebSockets, and background workers. You do not get bare root access to the underlying host, and you do not manage nginx.
The distinction matters because it determines what breaks first as you scale, what you can build, and where the surprise costs hide.
Cold Starts, and What Vercel Did About Them
The canonical knock on Vercel serverless functions has always been cold starts. When a function has not been invoked recently, the platform boots a fresh execution environment before it can respond. Historically, users reported delays of 2 to 3 seconds on cold paths, and that number climbed further if your function opened a database connection, because serverless cannot share persistent connection pools between invocations.
In April 2025, Vercel shipped a new execution model called Fluid Compute and made it the default for all projects created after that date. The core change is that warm function instances can now serve multiple concurrent requests rather than being locked to a single request lifecycle. According to Vercel's own knowledge base, this means most production requests land on an already-running instance, making a true cold start the exception rather than the rule for active workloads.
This is a meaningful improvement, but it has limits. Fluid Compute helps on active, traffic-receiving functions. If you have dozens of routes that each see sporadic traffic, cold starts still happen on the quiet ones. Regional cold starts also persist: a function warmed in us-east-1 is cold in ap-southeast-1.
Fly.io's situation is different because the underlying model is different. A Fly Machine is a container that stays running. Requests hit a warm process every time, with no boot sequence required. Fly does support scale-to-zero as an opt-in feature -- machines can suspend when idle and resume on the next request -- with a reported wake time of 200 to 500ms for lightweight apps. That is still faster than a traditional serverless cold start, and it is a deliberate trade-off you make, not a platform default you accept.
A VPS has no cold starts in any meaningful sense. Your process is either running or it is not. The latency floor depends on your server's geographic proximity to your users, your Node (or whatever runtime) startup time on deploys, and how well you have configured process management. nginx with PM2 or systemd handling a Node process adds no cold start overhead. What a VPS does not give you is automatic global distribution -- your server is in one datacenter.
Real Cost at Three Traffic Tiers
Abstract pricing pages are not useful. Let's ground this in a specific scenario: a Next.js application serving 500,000 requests per month, with 200GB of bandwidth, one developer on the team, and a Postgres database.
Tier 1: Low traffic, single developer
Vercel's free Hobby plan covers this traffic comfortably on paper, but commercial use is prohibited on Hobby -- a restriction most developers miss until they re-read the terms. If the app is commercial in any sense, you are on Pro: $20 per seat per month. Your 200GB bandwidth sits well inside the 1TB monthly allowance, and Fluid Compute keeps you inside the included function execution budget for a 500k-request app. Total: $20/month.
A Hetzner CX22 -- 2 vCPU, 4GB RAM, 40GB NVMe, 20TB bandwidth -- costs $4.39 per month. Add self-managed Postgres on the same box and you stay at $4.39. Add Supabase Pro for a hands-off database and you are at $29/month. Either way, the figure assumes you know nginx, Let's Encrypt, deployment pipelines, and Postgres backup management. That knowledge has a real cost even if it does not appear on an invoice.
A Fly.io minimal setup with one shared-cpu-1x machine and a Fly Postgres instance runs $13 to $20 per month all-in. You push Docker images with flyctl deploy. TLS, routing, and health checks are included. The gap between Vercel Pro and Fly.io at this tier is roughly zero to seven dollars, depending on how you count the database. Fly's advantage here is not price -- it is that you are building on a model that does not punish you later.
Tier 2: Mid-scale SaaS, 3 million requests per month, 600GB bandwidth, 3 developers
On Vercel Pro at three seats, the base cost is $60/month. Your 600GB bandwidth sits inside the 1TB cap. The function execution story depends on what your routes do -- an SSR-heavy app with database queries on most routes burns execution time faster than a mostly-static site. A real-world example from pagepro.co showed one service consuming 1,276 GB-hours against a 1,000 GB-hour Pro inclusion, generating $160 in overages. Realistically: $60 to $150/month.
A Hetzner CX32 at $7.88/month handles this traffic on a 4 vCPU, 8GB RAM box without breaking a sweat. The 20TB bandwidth inclusion means you will never pay an egress overage on Hetzner for this workload. Add a managed database -- whether on the same box or offloaded to Neon or PlanetScale -- and call it $30 to $50/month depending on your setup. The catch is operational overhead: three developers means you need a shared deployment pipeline, runbooks, and someone to handle the server when it misbehaves at 2 AM.
Fly.io at this tier with two production machines, a Postgres cluster, and multi-region deployment: roughly $40 to $70/month. You get the operational simplicity of a PaaS -- flyctl deploy, automatic rolling updates, built-in metrics via VictoriaMetrics -- without the function execution meter running.
Tier 3: High-traffic application, 20 million requests per month, 3TB bandwidth, 5 developers
This is where Vercel's pricing model shows its architecture. Your bandwidth overage at 3TB on Pro is $0.15/GB for the 2TB above the 1TB inclusion: $300 in bandwidth alone. Five seats at $100. Edge request overages depending on your geographic distribution. A realistic Vercel bill at this tier: $500 to $900/month, with genuine uncertainty on the execution overage side if your workload is compute-heavy.
A Hetzner CX42 at $19/month gives you 8 vCPU, 16GB RAM, and 20TB of bandwidth -- enough for this workload on a single box with a reasonable horizontal scaling plan. A proper production setup with load balancing, a Postgres primary/replica, and automated deployments: $80 to $120/month. The gap between Vercel and VPS at this tier is $400 to $700 per month. That is real money, and it represents the point where the VPS operational overhead genuinely pays for itself.
Fly.io at high traffic with multiple regions: $150 to $250/month, depending on how many regions and what instance sizes you need. More expensive than raw VPS, meaningfully cheaper than Vercel, and with global distribution built in that a single-region VPS cannot match.
The Ops Tax
Every article about VPS hosting undersells what managing one actually costs. The financial comparison above uses Hetzner's invoice, not the real cost -- which includes developer time spent on things that do not ship features.
Here is a realistic list of what a production VPS setup requires that Vercel and Fly.io handle for you: nginx configuration and maintenance, Let's Encrypt SSL with automatic renewal, systemd or PM2 for process management, firewall rules (UFW, fail2ban for brute-force protection), OS patching and security updates, database backup automation, deployment pipelines that handle zero-downtime restarts, log aggregation, and uptime monitoring with alerting.
None of this is intellectually hard if you already know it. But the learning curve, if you are coming from PaaS tools, runs 20 to 100 hours depending on your starting point. And the ongoing cost -- monthly patches, the occasional nginx debugging session, the SSL renewal that did not auto-renew -- adds up to meaningful opportunity cost even for experienced teams.
Tools like Coolify and Dokploy have changed this calculus somewhat. Coolify gives you a Heroku-like deployment UI on top of your own server, with 280+ one-click app templates, and it is free. But you are still running it on infrastructure you own, and when Coolify breaks, it is your problem. The abstraction is better than raw nginx; it is not the same as Vercel's zero-configuration deploy-and-forget model.
Fly.io's ops surface is narrow by design. flyctl deploy handles rolling updates. TLS is automatic. You do not write nginx configs. You do not manage process supervisors. The operational surface you own is your Dockerfile and your fly.toml configuration -- both of which are portable and readable. The trade-off is that Fly's Postgres is self-managed in the sense that you handle backups and failover configuration yourself; it is a Postgres instance running inside a Fly Machine, not a hands-off managed database service like RDS.
What Vercel Actually Locks You Into
Vendor lock-in on Vercel is not a conspiracy. It is the natural result of building a framework and a platform simultaneously, with each one optimized for the other. Understanding exactly what you cannot take with you is more useful than a vague warning about it.
next/image routes image optimization requests through Vercel's proprietary processing pipeline. The component API is standard React -- <Image src="..." /> -- but the underlying optimization (format conversion to AVIF/WebP, responsive variants, lazy loading) runs on Vercel's infrastructure. Moving to Cloudflare Pages requires either Cloudflare Images ($5/month) or a custom loader. Moving to a VPS means rebuilding with Sharp or an external service like imgix. The code change is small; the infrastructure decision is not.
ISR (Incremental Static Regeneration) assumes persistent filesystem access for cache storage. Vercel handles this transparently. On a VPS or another platform, ISR requires external cache storage -- Redis or S3 -- and configuration that Vercel abstracts away. The framework assumes infrastructure that Vercel provides, which is fine on Vercel and works on other platforms, but the work is real.
Vercel Middleware runs on a proprietary edge runtime. The API is similar to the Web Platform's Request/Response model, but it is not identical. Migrating middleware to Cloudflare Workers requires a port -- not a copy-paste -- and Netlify's Deno-based edge functions are different again. Apps heavily using Next.js 15.1+ features on Vercel can break on non-Vercel deployments for reasons that are non-obvious until you try.
Preview deployments are not a lock-in risk, but they are worth mentioning as a genuine Vercel advantage. Every pull request gets a unique URL with your full application running against it. Teams that have built review workflows around preview URLs face a real workflow change when migrating -- Fly.io can replicate this with some scripting, a VPS requires significant CI/CD work to match it.
The honest summary: if your Next.js app uses next/image, ISR, and Edge Middleware heavily, and it is a year into production, migrating off Vercel is a one to three month engineering project. Not impossible. Not trivial.
When to Move, and Where to Go
The signals that it is time to leave Vercel are more predictable than most teams realize.
Stay on Vercel when: you are shipping a Next.js app and your team is under 5 developers. You do not have a DevOps function. Your bandwidth stays under 1TB per month. You use ISR, next/image, and Edge Middleware, and you have not built around workarounds for their limitations. The $20/seat cost is lower than the opportunity cost of managing infrastructure for a small team with feature velocity as the top priority.
Move to Fly.io when: your application has backend requirements that do not fit the serverless model -- WebSockets, long-running jobs, persistent in-memory state, or a custom runtime. When you need global distribution but cannot afford the Vercel bandwidth bill at scale. When your stack is Docker-native and you want a platform that deploys containers without asking you to reshape your architecture around function execution limits. Fly's anycast routing handles geographic routing automatically; you deploy to ord, ams, and syd with a single command.
Move to a VPS when: cost efficiency is the primary constraint, you have the DevOps knowledge (or time to acquire it), your traffic pattern is predictable enough that autoscaling is not a survival requirement, and you are running a stack that benefits from persistent server processes -- a Rails app, a Django monolith, a Go binary, a NestJS service with a BullMQ worker. Hetzner at $4.39 to $19/month for the CX series, with 20TB of included bandwidth, represents genuinely cheap compute. The operational overhead is the real cost.
The moment most teams miss is not when they first hit the Vercel bill -- it is when they start building architectural workarounds for Vercel's model. The first time you reach for Redis because your serverless function cannot hold state. The first time you find yourself warming a function on a cron job. The first time you discover that your queue consumer cannot stay alive between requests -- because Vercel terminates functions once the response completes, and no process persists until the next one arrives. Those are the signals. Each workaround is a quiet vote to move to a model that fits what you are building.
A Concrete Decision Matrix
Scenario | Best Pick |
|---|---|
Next.js MVP, solo developer, commercial use | Vercel Pro ($20/month) |
Next.js app, 3-5 devs, under 1TB/month | Vercel Pro ($60-100/month) |
Any stack needing WebSockets or background workers | Fly.io |
High traffic Next.js, over 1.5TB/month bandwidth | Fly.io or VPS |
Full-stack with Docker, multi-region, no ops team | Fly.io |
Predictable traffic, ops knowledge, cost is primary | Hetzner VPS |
Rails, Django, Go binaries, NestJS monoliths | Hetzner VPS |
Vercel bill over $200/month, traffic not going down | Audit then migrate |
The audit step in that last row matters. Before migrating off Vercel, check your usage dashboard. Middleware misuse is the most common source of unexpected Vercel bills -- middleware that a developer added after reading a tutorial and forgot is a documented billing culprit. Unoptimized server-side rendering that reruns on every request when it could be cached is the second. The migration often waits until you have eliminated the inefficiencies, because those same inefficiencies will make your VPS or Fly.io bill higher than it needs to be.
The Honest Summary
Vercel is genuinely excellent infrastructure for what it does. The problem is that developers pick it for projects that will eventually need what it cannot provide without workarounds, and they do not notice until the workarounds have accumulated into a migration. Fly.io occupies a position most comparisons skip: a server model (long-lived process, persistent state, real containers) with PaaS ergonomics (push to deploy, automatic TLS, anycast routing). A VPS gives you the most compute per dollar, the most control, and the largest ops surface.
None of these are wrong choices. They are choices that suit different moments in a product's life. Knowing which moment you are in is the actual skill.
Comments (0)
Login to post a comment.