Vercel vs Hetzner with Coolify: what the bandwidth line really costs
A PaaS bill is two numbers wearing one coat: seats, and everything you ship out of the edge. At one terabyte of egress a month the seat line still dominates. At ten terabytes it does not, and the overage rate - about $150 per terabyte on the mainstream PaaS plans - is roughly seventy-five times what the same gigabyte costs on a VPS. This calculator finds the crossover for your traffic.
Migration and sizing sheet
3-Year FinOps Migration & Sizing Sheet
| Line | Value | Unit | Basis |
|---|
The hosting line is a mainstream KVM instance at 2 vCPU / 4 GB, stepping through 4/8, 4/16, 8/32 and 16/64 as services are added; past 64 GB the calculator buys a second host. VPS plans in this class typically include 4 to 20 TB of egress a month, and the traffic line above 10 TB is billed at $2 per extra terabyte, which is the conservative end of that range. Off-site backup is priced as a real line because a database dump that lives on the same provider as the host is one account compromise away from being gone. Platform engineering time is your own rate.
Two meters, one invoice
A PaaS bill looks like a per-seat product and behaves like a metered utility. The seat line is the one on the pricing page; the usage line is the one that arrives at the end of the month with no ceiling on it unless somebody remembered to configure a spend limit.
The seat line is honest and small. Twenty dollars per developer per month is roughly what a hosted CI runner plus a staging environment costs, so the seat line is rarely the complaint. It is also the line that makes the platform feel cheap when you sign up: six developers, $120 a month, done.
The egress line is the one that scales with success. The plan includes 1 TB of fast data transfer a month and then meters on-demand bandwidth at about $0.15 per GB - $150 per terabyte. For an API or a dashboard that is nothing. For anything serving images, video segments, large JSON payloads or a public dataset, traffic is proportional to popularity, which means the invoice grows fastest in the month your marketing works. There is no volume discount at the bottom of the curve and no way to pre-buy your way out of it on the self-serve plans.
Everything else is metered too. Function invocations and duration sit on their own meter, image optimisation bills per source image transformed rather than per byte served, and preview deployments multiply the whole surface - every branch push builds and serves something. A team that opens fifteen pull requests a week is running fifteen throwaway environments, and those count even though nobody looks at them after review.
The structural problem is not the price of any one meter. It is that the meters are denominated in units that grow with traffic and with team activity, while the alternative - one host you rent by the month - is denominated in a unit that does not move at all.
The crossover, across team sizes
The table holds egress at 3 TB a month - a mid-size marketing site plus an API - and scales the service count the way real teams do, at roughly 0.6 services per developer with a floor of four. Watch the fourth column: it is flat for the first five rows, because four to nine containers all fit comfortably on the same instance.
| Dev seats | Services | PaaS/mo | Coolify/mo | Coolify, 3 yr | Net saving | Egress tax, 3 yr |
|---|---|---|---|---|---|---|
| 2 | 4 | 340 | 146 | 5,238 | 7,002 | 10,800 |
| 4 | 4 | 380 | 146 | 5,238 | 8,442 | 10,800 |
| 6 | 4 | 420 | 146 | 5,238 | 9,882 | 10,800 |
| 10 | 6 | 500 | 146 | 5,238 | 12,762 | 10,800 |
| 15 | 9 | 600 | 146 | 5,238 | 16,362 | 10,800 |
| 25 | 15 | 800 | 174 | 6,246 | 22,554 | 10,800 |
| 40 | 24 | 1,100 | 230 | 8,262 | 31,338 | 10,800 |
| 60 | 36 | 1,500 | 230 | 8,262 | 45,738 | 10,800 |
The egress tax column is the one to argue about. It is identical in every row because it depends only on traffic, which is precisely the point: a traffic spike does not care how many developers you employ. The calculator above also ignores the small per-seat usage credit the Pro plan bundles, which makes the PaaS side of this model very slightly pessimistic at low traffic - and does not change the answer once egress is measured in terabytes.
What Coolify actually is
Coolify is a self-hostable control plane for Docker: you point it at a Git repository, it builds the image on the host, runs it as a container, and puts a reverse proxy in front of it with a Let's Encrypt certificate. In practice a deployment looks like this:
- Coolify itself - a Laravel application plus a queue worker, running in containers, listening on a management port.
- Its own PostgreSQL and Redis - state, queue, session and cached build metadata. These are not optional and they are the part you have to back up.
- Traefik - the reverse proxy that terminates TLS, routes by domain and handles certificate renewal.
- Your application containers - one per service, built from your Dockerfile or a Nixpacks guess, with their own environment variables and volumes.
That is the whole architecture. It is not a distributed system, it has no edge, and it does not pretend to. What it does have is a per-branch preview feature that behaves the way developers expect: push, wait for a build, get a URL.
Sizing the host without guessing
The arithmetic is in the calculator, so this section is about the three numbers people get wrong.
Builds, not requests, set the memory floor. A running Next.js container might idle at 200 MB. The build that produced it will spike to 1.5-2.5 GB, and Coolify builds on the same host by default. An instance sized for steady state will OOM during a deploy, which is the most confusing failure mode in self-hosting because the site was fine until you shipped something. Size for the build, then add the running containers.
Disk is not storage, it is a build artefact problem. Every deploy leaves an image behind, and image layers are shared but not free. A modest application with fifteen deploys a week will accumulate tens of gigabytes of dangling layers within a couple of months. Coolify can prune on a schedule and you should turn that on before the disk fills, because a full disk takes down the database and the proxy at the same time.
Egress on the host is generous until it is not. Mainstream VPS plans include 4 to 20 TB a month depending on provider and tier, which is between four and twenty times what the PaaS plan includes for a fraction of the price. Above that, providers charge a small per-terabyte rate - the calculator uses $2 per terabyte over a conservative 10 TB floor. The gap between that and $150 per terabyte is the entire economic argument for this page.
Feature parity, honestly
| Capability | Status | What you get instead |
|---|---|---|
| Git push deploy, build logs | Full | Webhook or polling, build output streamed in the UI. |
| Per-branch preview environments | Full | One container and one subdomain per branch, torn down on merge. |
| Custom domains and TLS | Full | Traefik plus Let's Encrypt, automatic renewal, wildcard with DNS challenge. |
| Instant rollback | Full | Redeploy the previous image. Slower than a platform rollback, same result. |
| Cron and background workers | Full | Scheduled tasks and worker containers, defined per service. |
| Managed Postgres with point-in-time recovery | Partial | A container with a volume. Backups are a cron job you own, not a console toggle. |
| Global edge network | None | One region. Put a CDN in front if latency matters, and price that separately. |
| Serverless functions with per-request isolation | None | Long-running containers instead. Cheaper per hour, not cold-start isolated. |
| Image optimisation at the edge | Partial | Do it at build time or behind a CDN. This is the most common migration surprise. |
| DDoS absorption and WAF | None | Add Cloudflare in front, on the free tier or above. |
| Team roles and audit log | Partial | Basic users and tokens. Fine for a small team, thin for a regulated one. |
The operational bill nobody puts in the spreadsheet
Self-hosting moves cost from a line item to a person's attention. One and a half hours a month is a realistic steady state for a stable stack: patching the host, bumping image tags, confirming that last night's dump actually landed, renewing a certificate that failed because a DNS record moved. It is not realistic during the first month, when you will spend a day wiring TLS, environment variables, backups and a health check that pages somebody.
Two things make the difference between a smooth migration and a slow-motion outage. First, a restore drill: put the dump back into a scratch container and confirm the application boots against it, at least once, before you trust the backup. Second, an alert on disk and on certificate expiry, because both fail silently and both take the whole stack down when they do.
Independent estimate. SelfHostTCO is an independent third-party cost tool with no commercial relationship to Vercel Inc., Hetzner, Coolify or any other vendor named on this page. Plan terms, included allowances and metered rates change; confirm them on the vendor's own pricing page and in your contract. Hosting prices are representative list prices for a mainstream KVM instance and vary by region, commitment and included egress. Engineering-time estimates are yours to set. Nothing here is a recommendation to migrate a production system without a rollback plan.
Related cost pages
If the subscription under audit is software rather than hosting, the Docusign alternative TCO page prices a self-hosted e-signature stack with the same 36-month method, and the Acrobat alternative TCO page applies it to a hybrid desktop-and-browser PDF stack. The method page documents the pricing sources, the hardware ladder and how every table is recomputed before publication.