ReactJavascript

Hetzner + Coolify vs Vercel for SaaS Hosting in 2026

When Hetzner + Coolify beats Vercel for a stateful SaaS: real cost math, Postgres and BullMQ on one box, and the trade-offs.

Last updated: 1 Aug 2026

Split-frame illustration with a single Hetzner server stack on the left and a fan of Vercel functions plus metered add-ons on the right

Short answer: if your SaaS holds state, queues background jobs, or needs row-level security, the comparison of hetzner coolify vs vercel tips clearly toward the Hetzner side. A single Hetzner cloud node running Coolify costs roughly $20 to $40 a month, runs the app, Postgres, Redis, and a BullMQ worker together, and removes the function-timeout class of bugs entirely. Vercel still wins for edge-heavy marketing sites. The rest of this article shows the math and the trade-offs.

TL;DR, hetzner coolify vs vercel in one paragraph

For a stateful SaaS with Postgres, Redis, and background jobs, Hetzner + Coolify runs the whole stack on one box for roughly $20 to $40 a month and removes the function-timeout class of bugs entirely. Vercel still wins for edge-heavy marketing sites and ISR-heavy Next.js apps with global readers. If your app holds state, queues jobs, or needs row-level security, start on Hetzner with Coolify and revisit only when you outgrow a single machine. Stateful belongs on Hetzner; stateless and global belongs on Vercel.

Side-by-side: Hetzner + Coolify vs Vercel

The table below is the article in one screen. Read it, then drop into the sections that matter for your situation.

DimensionVercelHetzner + Coolify
Hosting modelServerless functions plus edge CDNSingle VM, Docker-managed by Coolify
Persistent processesNo, every request is a fresh functionYes, long-lived Node, queues, sockets
Background jobs and queuesAdd a separate worker host (Render, Railway, Fly)Included on the same box via BullMQ + Redis
PostgresThird-party add-on (Neon, Supabase, Vercel Postgres)Runs on the same box, managed by Coolify
RedisThird-party add-on (Upstash, Redis Cloud)Runs on the same box, managed by Coolify
Function timeout class of bugsYes, capped per planNone, requests run as long as the process
Predictable monthly billNo, metered across functions, Postgres rows, bandwidthYes, flat SKU price
Global edge / CDNYes, built inNo, add Cloudflare in front
Preview deploys per branchYes, polished GitHub integrationYes, one app per branch via Coolify
SSL certificatesAutomaticAutomatic via Coolify and Let's Encrypt
Disaster recovery ownerVercel plus each add-on vendorYou
Typical cost at 1k MAU stateful SaaS$80 to $300+ depending on add-ons$20 to $40
Setup time from zero to first deployMinutesOne afternoon

One pattern jumps out of the table: every row where the answer is "yes, by default" on Vercel is paid for in metering or add-ons, and every row where the answer is "you" on the Hetzner side is paid for in operational ownership. That is the trade everyone is actually choosing between.

The hidden Vercel cost for a stateful SaaS

Vercel's pricing page looks tidy until you add up what a real SaaS actually pulls in: a Postgres provider, a Redis provider, a worker host, and bandwidth on top. Three traps catch teams, in this order: function timeouts, Postgres metering, and bandwidth. The pattern: every Vercel bill quoted in a comparison post is the marketing-site bill, not the SaaS bill.

Function timeouts and the queue you cannot run

Vercel functions have a hard duration cap per plan, documented at Vercel's function duration page. Those numbers shift over time, so check the source. The shape of the problem does not shift. Anything that takes longer than the cap (a long export, a large file scan, an AI streaming response over a minute, a transactional migration) cannot run inside a Vercel function.

The conventional fix is to add a worker host. Render, Railway, or Fly all sell this. You now have a second deploy target, a second set of env vars, a second set of secrets, a second set of alerts, and a queue running on a third vendor (Upstash for the Redis BullMQ talks to, typically). Each piece is fine in isolation. The four-vendor stack is the cost.

Coolify's answer here is structural. The same box that serves the web app runs a BullMQ worker as a sibling service, talking to a Redis container managed by Coolify. One panel, one set of secrets, one deploy. Long jobs run because there is no function boundary in the first place.

One box. One queue. One bill. Vercel forces a multi-vendor worker stack to escape the function timeout; Hetzner + Coolify runs the worker on the same box as the app.

Postgres add-ons and the per-row pricing trap

Vercel does not ship a database; you bolt one on. The three common picks are Neon (linked via Supabase here because Supabase's own RLS docs are the cleanest reference), Supabase, or Vercel's own Postgres offering. All three meter some combination of storage, compute hours, row reads, and egress.

The trap is the row-read meter. A chatty ORM that issues N+1 queries against a relational schema, or a poorly indexed dashboard that scans a 200k-row table on every load, will burn through the read budget on a low tier in days. The fix is not "buy a bigger plan." It is to fix the query itself. But that takes engineering time you would not have spent if Postgres lived on the same box at a flat price.

Coolify spins up a Postgres container as a managed database. It exposes scheduled backups, exec access, and an env-var injection model that gives the app a DATABASE_URL automatically. No row metering. The query plan matters for performance; it does not show up on the bill. Per-row Postgres metering punishes chatty ORMs; an on-box Postgres charges flat regardless of query shape.

The bandwidth bill nobody quotes you

The third hidden cost is egress. Vercel's pricing page (see vercel.com/pricing for current tiers) bundles a generous-looking bandwidth allotment, but a SaaS that ships images, exports, or AI outputs blows past the free tier quickly. Once you go over, the per-GB pricing starts to matter.

Hetzner cloud servers include a large monthly traffic allowance per instance, well documented on the Hetzner Cloud page. Past that, the per-TB overage cost is roughly an order of magnitude cheaper than Vercel's per-GB metered tier. For a workload that streams a lot of bytes, this is often the single biggest line-item difference, not the compute price. Bandwidth, not compute, is usually the line item that decides which platform is cheaper.

What Hetzner + Coolify actually gives you

The Hetzner side of hetzner coolify vs vercel is less glamorous and more contained. You rent a virtual machine, install Coolify, and Coolify becomes the operating layer for everything else. The reason this feels different to "2014 sysadmin pain" is that Coolify covers the parts that used to require a real ops engineer: SSL, deploys, container lifecycle, backups, log access, and a UI that does not assume you know systemctl.

One box, one Postgres, one Redis, one BullMQ

A typical Coolify stack for a Node or Nuxt SaaS lays out four services on the same machine: the app itself, a Postgres container, a Redis container, and a BullMQ worker process that consumes from the same Redis. Coolify generates a standard docker-compose.yml along these lines internally.

docker-compose.yml (generated by Coolify)

services:
  app:
    image: your-app:latest
    environment:
      DATABASE_URL: postgres://app:***@postgres:5432/app
      REDIS_URL: redis://redis:6379
    depends_on: [postgres, redis]

  worker:
    image: your-app:latest
    command: ["node", "dist/worker.js"]
    environment:
      DATABASE_URL: postgres://app:***@postgres:5432/app
      REDIS_URL: redis://redis:6379
    depends_on: [postgres, redis]

  postgres:
    image: postgres:16
    volumes:
      - pgdata:/var/lib/postgresql/data

  redis:
    image: redis:7
    volumes:
      - redisdata:/data

You do not actually write this file in Coolify; the panel generates it. The point is the topology. A worker that shares the codebase with the app, hits the same Postgres, and pulls from the same Redis (Redis docs for the data layer, BullMQ docs for the queue contract) removes a whole class of "the worker is in a different region from Postgres" latency bugs that the multi-vendor Vercel shape produces. The web app, Postgres, Redis, and the BullMQ worker all run as colocated containers on a private Docker network.

Coolify in plain English, Heroku UX on your hardware

Coolify is best described as Heroku's UX bolted onto a server you own. You connect a GitHub repo, point Coolify at a Dockerfile or a Nixpacks-detected stack, and it builds, deploys, and exposes the app on a subdomain with a free Let's Encrypt certificate. Install is a single shell command documented at coolify.io/docs, which the project maintains and updates with each release; do not paste an install snippet from memory, run the one on the docs page.

What you get out of the panel: Git-based deploys with rollback to any previous build, environment variable management with per-environment overrides, scheduled tasks (cron) tied to the same image, log streaming, exec into a container, and one-click backups for managed databases. The release cadence is active; the Coolify GitHub repo is the source of truth for which version is current and what changed.

What you do not get out of the panel: someone else worrying about the host being patched. You own the kernel updates. Hetzner cloud servers ship with a sensible default image and unattended-upgrades can be turned on, but the operational responsibility line is on your side of the panel. Coolify gives a Heroku-style deploy and backup UI on a server you own; kernel patching and OS-level ops stay on your side.

Backups, SSL, deploys, and rollbacks out of one panel

The four operations that used to require four scripts are all in the same UI in Coolify. SSL renews itself via Let's Encrypt. Deploys are Git-push triggered, with a manual rollback button per app. Database backups can be scheduled in the panel, but the panel writes them to the same disk by default, which is not a real backup. The real backup setup needs an off-box destination.

The canonical pattern: configure Postgres for continuous WAL archiving shipping to S3, R2, or a Hetzner Storage Box, then layer a nightly logical dump on top using one of the methods in the Postgres backup overview. For everything that is not Postgres (uploads, generated assets, container volumes), restic writing to the same off-box destination is the simplest stack that works.

A backup that lives on the same machine as the database is not a backup; it is a second copy. Coolify handles SSL, deploys, and rollbacks in-panel; off-box Postgres WAL archiving and restic for volumes cover the actual disaster-recovery story.

Cost math at 100, 1k, and 10k users

The honest comparison is at three load points. Numbers below are illustrative ranges based on the public pricing pages cited; verify against vercel.com/pricing and hetzner.com/cloud at the time you make the decision, because both pages move.

ScaleVercel side, monthlyHetzner + Coolify side, monthly
100 active users, low traffic$20 Pro + $0 to $25 Postgres free tier + $0 to $10 Redis free tier + bandwidth headroom: ~$25 to $60One CPX21 or CCX13 + Storage Box for backups: ~$15 to $25
1k active users, real workload$20 Pro + $25 to $100 Postgres + $10 to $30 Redis + worker host $7 to $25 + bandwidth: ~$80 to $200One CCX13 or CCX23 + Storage Box: ~$25 to $50
10k active users, busy$20+ Pro plus team seats + $100 to $400 Postgres + $30 to $80 Redis + worker host + bandwidth overages: $300 to $1000+One CCX33 or CCX43 + Storage Box, possibly a second box for the worker: ~$70 to $200

The 10k row is where I want to be honest. A single Hetzner CCX node can absolutely serve 10k MAU for a typical SaaS workload, but the moment Postgres becomes the bottleneck, the right move is to lift Postgres onto a managed service (Hetzner offers managed Postgres via partners, or you reach for Neon at the database layer only) and keep the app and worker on Hetzner. The single-box story is not infinite. It is durable enough to carry most early-stage SaaS through product-market fit without distraction.

A stateful SaaS on Hetzner + Coolify is roughly 3 to 10 times cheaper than the equivalent Vercel-plus-add-ons stack at every scale below "needs a managed Postgres."

When to pick each

Comparison articles owe you a recommendation, not a balanced both-sides list. Here is the call.

Pick Hetzner + Coolify when:

  • The app holds state in Postgres with real schemas, foreign keys, or row-level security policies.
  • You queue background jobs (BullMQ, scheduled cron, batch exports).
  • You need long-running requests (uploads, exports, AI streaming over a minute).
  • You want a flat, predictable bill that does not scale with row reads or egress.
  • You want one panel to operate the whole stack and one place to look when something is wrong.
  • You are post-prototype and the math has started to matter.

Pick Vercel when:

  • The product is mostly a marketing site or content site with globally distributed readers.
  • You ship a Next.js app whose hot path is ISR or static plus light API.
  • The team is one person and ten hours of monthly ops time is worth more than $30 of savings.
  • You are pre-launch and time-to-first-deploy beats every other metric.

If you are between vibe-coding stage and production stage, the earlier guide on turning a vibe-coded React prototype into something deployable sits one step before this decision. This article is the next one.

Pick Hetzner + Coolify the moment the app holds state or queues jobs; pick Vercel for stateless content sites with global readers.

The real trade-offs (and how to mitigate each)

No platform is free. The Hetzner side has three honest trade-offs that the Vercel side does not.

You own the uptime now

On Vercel, when something is on fire at 3 a.m., Vercel's on-call wakes up alongside yours. With Hetzner, only you do. That asymmetry is real and worth pricing.

The mitigation is structural, not heroic. Run Hetzner snapshots nightly (the panel does it). Wire uptime checks to a free tier of Better Stack, UptimeRobot, or your existing PagerDuty. Once revenue justifies the spend, run a second small Hetzner node as a warm standby with Postgres logical replication. The DR story is a real engineering task with a defined scope; it is not a permanent on-call burden.

Restore drills are non-optional

A backup you have never restored is not a backup. This sounds obvious and almost nobody does it.

The mitigation is to put a restore-drill script in the repo, run it quarterly against a temporary Hetzner box, and time the restore. Our earlier piece on hardening an AI-generated React app before it touches users has the same shape of argument for the application layer: write the failure mode down, run the drill, fix what surfaces.

When Vercel still wins (edge-heavy marketing sites)

There is a class of project where Vercel is genuinely the right answer. Marketing sites with global readers and ISR-heavy Next.js apps benefit from a polished edge network that Hetzner does not ship. Cloudflare in front of a Hetzner origin closes a chunk of the gap, not all of it.

The mitigation is not religious. Dual-deploy: the marketing surface on Vercel, the app on Hetzner. The two halves never need to share a deploy pipeline, and you keep the right platform for each job.

The Hetzner side trades operational responsibility, restore discipline, and edge-CDN convenience for a flat bill and a unified panel.

A migration checklist if you are coming off Vercel

Moving an app off Vercel onto Hetzner + Coolify is a multi-day project, not an afternoon. The shape that works in practice:

  1. Provision the Hetzner cloud node. Pick a CCX or CPX SKU at the Hetzner Cloud page sized for current load plus 2x headroom. Enable backups.
  2. Install Coolify using the install command on coolify.io/docs. The shell snippet there is the canonical source; the docs are versioned with the project.
  3. Move Postgres. A pg_dump and restore is the simplest path for a low-traffic app. For zero-downtime, set up logical replication from the current managed Postgres into a Coolify-managed Postgres on the new box, let it catch up, then cut over. Bring any row-level security policies with the schema; they are stored as policies on the table and travel with pg_dump --section=pre-data.
  4. Move Redis. If Redis only holds queue state and ephemeral caches, the easier move is to drain the queue on Vercel-side, deploy the new stack with an empty Redis, and accept that BullMQ jobs in flight at cutover will be lost or replayed. For payment or invoicing flows, snapshot the queue first with BGSAVE.
  5. Stand up a staging subdomain pointing at the new box. Run the app end-to-end with production data (or a recent dump) and confirm the worker, cron, and login flows all work.
  6. Cut DNS. Switch the apex record to the Hetzner IP. Vercel keeps serving traffic from any cached deployments for a few minutes; that is fine.
  7. Decommission Vercel after a cooldown week. Keep the Vercel deployment running for seven days as a fallback. Do not save the $20 by cancelling on day one.

Treat the migration as onboarding to a new codebase with AI tools treats a green-field project: write the runbook as you go, keep it in the repo, and assume the next maintainer is you in six months with no memory of this week.

A clean Vercel-to-Hetzner migration is provision, install Coolify, move Postgres, move Redis, stage, cut DNS, decommission after one cooldown week.

When this stack stops scaling

The single-box Hetzner + Coolify story is not infinite. There are three honest tipping points where the stack needs to grow.

The first tipping point is a noisy Postgres workload. When a background analytics query starts to steal IOPS from the web path, the answer is not "add a bigger box." It is "lift Postgres onto a managed service" (a managed Postgres provider, or a dedicated Hetzner node with Postgres only), and keep the app and worker on the original box. Database isolation is the cheapest scaling lever.

The second is a CPU-bound BullMQ worker stealing from web requests. Split the deployment: keep the web app on the original box, spin up a second Hetzner node, install Coolify there too, and run the worker on the second machine pointing at the same Redis. Coolify handles the multi-server topology in v4 without ceremony.

The third is a region requirement. Hetzner has data centers in Germany, Finland, and the United States, with Singapore added more recently; check hetzner.com/cloud for the current region list. If you need true global presence in front of users (not only a CDN in front of a static site), you are buying a multi-region deploy, and at that point both Hetzner and Vercel become parts of a bigger architecture rather than the whole architecture.

Vertical scale first, split web and worker second, move Postgres to managed third; only then does the question become "platform" again.

Conclusion: where this stack actually fits

For a stateful SaaS in 2026 (Postgres, Redis, queues, RLS, long-running requests), the hetzner coolify vs vercel question has a defensible answer: start on Hetzner with Coolify, accept the operational ownership, and keep the bill flat while the product finds its audience. Move pieces out (managed Postgres, a second worker box) only when a real bottleneck names itself. Vercel remains the right answer for the slice of products that are stateless and global; do not let the comparison turn into a religious war.

The shape of the recommendation lines up with what the From Vibe Code to Production book deploys for its example SaaS, and with the earlier guides on shipping a real React app: turning a vibe-coded prototype into something deployable and hardening it before users touch it. Pick the box, install Coolify, write the runbook, and the rest is just engineering.

Found this useful?

Share
Thomas Findlay photo

About the author

Written by Thomas Findlay.

Thomas Findlay is a CTO, senior full-stack engineer, and the author of React - The Road To Enterprise and Vue - The Road To Enterprise. With 13+ years of experience, he has built and led engineering teams, architected multi-tenant SaaS platforms, and driven AI-augmented development workflows that cut feature delivery time by 50%+.

Thomas has spoken at international conferences including React Summit, React Advanced London, and Vue Amsterdam, and has written 50+ in-depth technical articles for the Telerik/Progress blog. He holds an MSc in Advanced Computer Science (Distinction) from the University of Exeter and a First-Class BSc in Web Design & Development from Northumbria University.

With a 5-star rating across 2,500+ mentoring sessions and 1,250+ reviews on Codementor, Thomas has helped developers and teams worldwide with architecture consulting, code reviews, and hands-on development support. Find him on LinkedIn, GitHub, or Twitter/X, or get in touch directly. Read the full bio →

Stop fighting your codebase. Start shipping.

Long-form articles like this one, plus a 400+ page book that takes you end-to-end through production React in TypeScript.