Cookies

We use cookies for analytics and advertising. You can accept all, keep only necessary, or customize your preferences. Cookie Policy

Digital Vantage LogoDigital Vantage Logo
  • About us
  • Offer
    • Websites
    • Web Applications
    • Applications
    • Technology consulting for companies
    • Online marketing and branding
  • Resources
    • Blog & News
    • Tools and calculators
    • Templates and checklists
    • Independent industry reports
  • Contact
Let's talk!
Polski|English
Digital Vantage LogoDigital Vantage Logo
  • About us
  • Offer
  • Resources
  • Contact
  • Search articles⌘K
  • PL|EN
    • Websites
      Building a professional online presence
    • Web Applications
      Dedicated web applications - automate and grow your business!
    • Applications
      Custom solutions tailored to your business needs
    • Technology consulting for companies
      When technology stopped keeping up with the business
    • Online marketing and branding
      Designing logos, corporate colors and letterheads
    • Blog & News
      News from the digital world.
    • Tools and calculators
      Before you start talking to an agency, check how much your project should cost.
    • Templates and checklists
      Professional checklists for B2B companies
    • Independent industry reports
      Cyclical report programs based on publicly available sources
Let's talk!
Digital Vantage LogoDigital Vantage Logo

Digital Vantage
Tel+48 663 877 600, +48 22 152 51 05
Andriollego 34, 05-400 Warsaw
REGON: 540674000
EU VAT: PL5321813962

Services
  • Websites
  • Company websites
  • Landing page
  • Web applications
  • Mobile apps
  • MVP for startups
  • Software development
  • Technology consulting
  • Online marketing and branding
  • Website pricing
Digital Vantage
  • About us
  • Contact
  • Let's talk about your business
  • Resources for business
  • Site map
Articles and guides
  • Websites
  • Online stores
  • Starting a business online
  • Web applications
  • Business applications
  • Google Business Profile
  • SaaS software
  • Glossary
Industry reports
  • Polish web market price analysis
  • Website costs
  • Online store costs
  • Web application costs
  • Mobile app costs
  • SaaS tool costs
Tools and calculators
  • Website cost
  • Online store cost
  • Web application cost
  • Website maintenance cost
  • Online store TCO
  • Website speed test
  • Quiz: website or app
  • Quiz: which e-commerce platform
  • Quiz: WordPress or headless
  • Quiz: ready-made SaaS or custom
Checklists and templates
  • Launching a website
  • Website audit
  • E-commerce UX checklist
  • Store migration
  • Choosing a web agency
  • Website security
Follow Us
FacebookInstagram
© Digital Vantage - Warsaw, Poland
Cookie PolicyPrivacy PolicyConditions
Polski|English
© 2026 Digital Vantage. © 2026 Digital Vantage. All rights reserved.
Digital Vantage LogoDigital Vantage Logo

Digital Vantage
Tel+48 663 877 600, +48 22 152 51 05
Andriollego 34, 05-400 Warsaw
REGON: 540674000
EU VAT: PL5321813962

★ 5.0
Google reviews
24h
We reply on business days.
20+ yrs
in IT/B2B EMEA
100/100
Desktop PageSpeed
© Digital Vantage - Warsaw, Poland
Cookie PolicyPrivacy PolicyConditions
Polski|English
© 2026 Digital Vantage. © 2026 Digital Vantage. All rights reserved.

Table of Contents · 6 sections

In this article

  1. 01What you actually pay each month
  2. 02What that table does not show
  3. 03Architecture: how this is put together
  4. 04Three things that break
  5. 05When this pays off, and when it does not
  6. 06Where these numbers come from
  1. Home›
  2. ›
  3. Blog & News from the Digital World›
  4. Websites — a guide to the whole section›
  5. Website technologies — what to build on, and what changing your mind costs›
  6. Self-hosting Next.js and Payload: the maths that works, and three things that break
Cloud and servers·Costs and pricing·Maintenance and outages·11 min reading time·13,250 characters·2,029 words

Self-hosting Next.js and Payload: the maths that works, and three things that break

Vercel with a managed database versus a VPS on Coolify: 271 USD against 36 EUR a month at 2 TB of traffic, plus three failures we hit in production.

RE
Redakcja Digital Vantage
Published24 Aug 2026
Updated8 Oct 2026
PL|EN

Serverless pricing is built so that starting costs nothing. It works: a project goes live without an invoice, and the first bills arrive only once something starts to live. The problem is that they grow in proportion not to revenue, but to traffic, headcount and function execution time — three things nobody forecasts at the start.

This article is an arithmetic exercise, not a manifesto. Vercel with a managed database on one side, your own VPS running Coolify on the other. The numbers come from vendor price lists (read on 5 October 2026), and the three failures described at the end happened to us in production, on exactly the stack that serves the site you are reading.

If you are looking for step-by-step instructions, they live separately: our public starter on GitHub carries a ready configuration of this stack, deployment files included.

What you actually pay each month

The comparison only means something once both sides count the same things: the application, the database, traffic and file storage. Assume a three-person team and 2 TB of traffic a month — the scale of a small content site, not a funded startup.

Item

Vercel + Atlas

VPS with Coolify

Where the number comes from

Application

20 USD / seat → 60 USD

included with the server

Vercel pricing

Database

from 57 USD (Atlas M10)

included with the server

Atlas pricing

2 TB of traffic

1 TB included, the second ~154 USD

included (20 TB in the EU)

0.15 USD/GB

Server

—

35.99 EUR (CPX32)

Hetzner pricing

Total

≈ 271 USD

≈ 36 EUR


A Polish company is invoiced for these services in USD and EUR, not in złoty, so the bill moves with the exchange rate; the amounts are net, and VAT is settled by reverse charge.

Two numbers in that table deserve a comment, because they are the ones doing the work. First: traffic. Vercel Pro includes 1 TB and charges 0.15–0.35 USD per gigabyte above it, depending on the region. Hetzner includes 20 TB in European regions — twenty times more, as part of the price. Second: the database. Those 57 USD buy one M10 node, and a production database runs as a three-node replica set, so the real bill is closer to three times that before you add backups and traffic.

Traffic is worth counting past 2 TB, because it is the line that grows with your audience. At the lowest rate of 0.15 USD per gigabyte, every terabyte above the plan costs about 154 USD: at 3 TB the Vercel-plus-Atlas bill reaches about 424 USD a month, at 5 TB about 731 USD. The Coolify server costs the same 35.99 EUR in every one of those cases.

A bar chart of the monthly bill for Vercel Pro with a MongoDB Atlas database for a three-person team as traffic grows, based on price lists read on 5 October 2026. The fixed part: 60 USD for three seats at 20 USD, and from 57 USD for Atlas M10, 117 USD in total. Traffic above the 1 TB included in the plan at 0.15 USD per GB, which is about 154 USD for every additional terabyte. At 1 TB about 117 USD, at 2 TB about 271 USD, at 3 TB about 424 USD, at 4 TB about 578 USD, at 5 TB about 731 USD. Beside it, a VPS with Coolify on a Hetzner CPX32: 35.99 EUR in every one of these cases, because 20 TB of traffic is included in European regions; the amount is in euros, with no currency conversion. The rate of 0.15 USD per GB is the bottom of Vercel’s regional price list, which goes up to 0.35 USD. Takeaway: every terabyte above the plan costs more than a whole month of the server.

The Vercel-plus-Atlas bill grows with traffic; the Coolify server does not

Vercel, MongoDB Atlas and Hetzner Cloud price lists, read 5 Oct 2026; own calculation

There is also an item no table shows: on your own server every additional service is free. A queue worker, your own cron, Redis, a small helper service — same machine. Under per-execution billing each of them gets its own line on the invoice.

What that table does not show

The difference in subscriptions is not a saving; it is a cost moved off an invoice and onto somebody's time. You take on three duties you did not have before: backups together with point-in-time restore, security updates and watching availability. They do not disappear because the bill got smaller — they change owner.

The honest conversion is this: if maintenance takes two hours a month, multiply them by the hourly rate you pay — at PLN 150 an hour that is PLN 300 a month — and subtract that from the difference in subscriptions before you call what is left a saving. Self-hosting pays off when those hours are in the team anyway and cover several projects at once, not one.

Monthly hosting cost for a three-person team and 2 TB of traffic, prices read from the providers’ price lists on 5 October 2026. Vercel with a MongoDB Atlas database: about 271 USD — the application 60 USD (3 seats at 20 USD), an Atlas M10 database from 57 USD, traffic above the 1 TB included in the plan about 154 USD (0.15 USD per GB). A VPS with Coolify on a Hetzner CPX32 server: 35.99 EUR, with 20 TB of traffic included in European regions. Amounts are shown in the providers’ currencies, with no currency conversion. What is not on the invoice: people’s time — two hours of upkeep a month multiplied by your hourly rate, for backups, security updates and watching availability.

The monthly bill: Vercel with Atlas versus a VPS with Coolify

Vercel, MongoDB Atlas and Hetzner Cloud price lists, read 5 Oct 2026

Architecture: how this is put together

Since version 3, Payload is not a separate application standing beside Next.js. It runs as a package inside it, sharing the same process, the same build and the same config file. That changes deployment architecture more than it sounds: the admin panel, the API and the frontend are one artefact, so one application container instead of two. What Payload can do as a CMS and when we choose it is covered in: Payload CMS; Next.js itself we take apart in: Next.js.

One container or several

By default we go with one application container plus separate containers for the database, Redis and the proxy. Splitting the application into more processes only makes sense once one of them scales differently from the rest — a worker chewing through a job queue, say, which needs memory during a data import and does nothing for the rest of the day.

Service

Role

Why separate

app

Next.js + Payload in one process

one build, one artefact, one restart

database

MongoDB (or Postgres — Payload 3 supports both)

a different lifecycle from the code; it outlives every deployment

redis

cache, sessions, shared state across instances

without it the cache is local to the container

proxy

Traefik, managed by Coolify

routing and Let’s Encrypt certificates automatically

Standalone build: 1.5 GB versus 150 MB

Next.js can build a directory containing only what is needed at runtime — without the full tree of development dependencies. It is one line in the config (output: "standalone"), and the difference in image size is an order of magnitude: from roughly 1.5 GB down to about 150 MB. This is not cosmetic. A smaller image means a shorter transfer on every deployment and many times less disk eaten by the successive versions Docker keeps locally.

There is one condition and it is easy to miss: in a multi-stage build you have to copy the static asset and public directories by hand, because standalone does not take them. Skip it and you get a working application with no styles — a symptom that looks like a CSS problem and is a Dockerfile problem.

A docker-compose skeleton

The core of the configuration is below. Coolify adds routing, the domain and the certificate on top, so the file says nothing about Traefik — that is precisely the part you use it for instead of bare Docker.

1services:
2 app:
3 build: .
4 environment:
5 DATABASE_URI: mongodb://mongo:27017/app
6 PAYLOAD_SECRET: ${PAYLOAD_SECRET}
7 REDIS_URL: redis://redis:6379
8 volumes:
9 - media:/app/public/media # EVERY upload directory, separately
10 depends_on: [mongo, redis]
11
12 mongo:
13 image: mongo:7
14 volumes:
15 - dbdata:/data/db
16
17 redis:
18 image: redis:7-alpine
19 command: redis-server --save 60 1
20 volumes:
21 - redisdata:/data
22
23volumes:
24 media:
25 dbdata:
26 redisdata:
A deployment diagram. The application image is built in GitHub Actions and pushed to the GHCR registry; Coolify pulls the finished image, so the production server does not build. On the server, traffic from the internet is received by Traefik, managed by Coolify — routing, the domain and the Let's Encrypt certificate. Behind it, three containers: the application, meaning Next.js and Payload in one process from a standalone build; a MongoDB database; Redis for the cache and shared state. Every upload collection has its own persistent volume, and so do the database and Redis. Files can leave the server for S3-compatible storage, Cloudflare R2 for example.

How a Next.js and Payload deployment on a VPS with Coolify is put together

Digital Vantage, own diagram

A note on volumes, because this is the most common mistake. A container filesystem is ephemeral. Every directory the application writes files to must have its own entry under volumes — and “every” means every one, separately for each upload collection. Adding a new collection in Payload without adding its volume is not an error you will see in the logs. You will see it after a restart, when the files are gone.

The complete set — Dockerfile, compose, environment variables and a pre-launch checklist — sits in our public repository: nextjs-payload-starter.

Three things that break

Guides describe the deployment that worked. Below are the three mechanisms that break it most often — each with a real incident from our production as evidence rather than illustration.

Three self-hosting failures. Memory: sharp processes images in the app process on a 2–4 GB VPS; symptom — the OOM Killer kills it with no log entry; our incident — a collection with no volume, a restart took 11 files, the records stayed; fix — files to S3 or R2, images outside the app, a volume per collection. Cache: ISR in .next/cache on the container’s disk; symptom — each instance has its own cache, publishing does not clear it; our incident — a disk filled to 89 GB by bots on non-existent addresses; fix — a CacheHandler in Redis, afterChange with revalidate, a request filter. Resources: docker build on the database machine; symptom — the site slows during a deploy, with 8 GB of RAM the build can be killed; our incident — green CI, failed deploy: no database at build time, .dockerignore; fix — at least 4 GB of swap, build in GitHub Actions with GHCR, a separate database.

Three things that break self-hosting — mechanism, symptom, our incident, fix

Digital Vantage, incidents from our own production

1. Memory: image optimisation and the OOM killer

The next/image component processes images inside the application process by default, using the sharplibrary. On a managed platform a separate, scaled service does this and nobody notices. In a container on a VPS with 2–4 GB of memory, uploading a handful of product photos through the Payload panel can summon the OOM Killer — the kernel kills the process to save the system. The application vanishes with no entry in the application logs, because it never got to write one.

The business consequence is out of all proportion to the cause: the site stops responding in the middle of the day, and if a search engine crawler happens to arrive, the page drops out of the index for far longer than the outage itself lasted.

The fix has two steps. Files move off the server into S3-compatible storage — in Payload that is @payloadcms/plugin-cloud-storage with an adapter for Cloudflare R2, AWS S3 or a Hetzner Storage Box. Image processing goes outside too: either to a CDN that transforms on the fly (Cloudflare Images), or by turning off the built-in optimiser (images.unoptimized) and generating sizes on the Payload side at save time. The application then stops holding in memory something it has no reason to hold. More on choosing hosting, a CDN and what actually makes a site faster: Hosting, domains and CDN.

Our version of this bug was worse, because it was quieter. We did not run out of memory — we ran out of volume. One collection's directory had no persistent storage attached, so a container restart took every one of its files while the database records stayed behind, insisting the files existed. It happened twice: once with a media collection, once with the documents collection — eleven report and template files gone from disk while the site went on offering them for download.

2. Cache: ISR has nowhere to live

On Vercel, static page revalidation and revalidateTag work at the level of a global CDN. In your own container the Next.js cache writes to .next/cache on that container's disk. Two things follow, both unpleasant: with two instances each has its own unsynchronised cache, and publishing content in the panel does not clear it by itself. This is, incidentally, one of the prices of headless architecture — more on that in: How headless architecture changes business strategy.

The fix. Your own CacheHandler pointed at from next.config, keeping entries in Redis — then the state is shared across all instances and survives a restart. Plus an afterChange hook in the Payload collections which, after a save, calls revalidatePath or revalidateTag for exactly what changed. The minimal variant — a persistent volume on .next/cache — solves the restart only, not horizontal scaling.

Our version: a disk filled to 89 GB, though nobody had uploaded anything. Bots were scanning addresses that did not exist, and on-demand rendering wrote every one of those responses as a cache file under .next/server/app. It grew for weeks, symptom-free, until the disk ran out. The fix turned out to be one line — a filter that sieves such requests out before they generate a file. The lesson, though, is not about the filter: on your own server the cache is your directory on your disk, and nobody tidies it for you.

3. Resources and state: the build starves the database

If the database sits on the same machine as the application, then docker build takes practically the whole CPU and memory during a deployment. The effect: the site slows down exactly when you are shipping a fix — which is usually when something is already broken. With 8 GB of RAM the Next.js compile can also simply be killed.

  • Swap. Four gigabytes minimum. It will not speed the build up, but it will stop it being killed — and that is all anyone asks of it here.
  • Building off production. The image is built in GitHub Actions, lands in a registry (GHCR), and Coolify pulls the finished artefact. The production server stops taking part in the build at all — that is the right destination architecture, not an optimisation.
  • Separating the database. As the project grows, the database gets its own instance. The first expense worth incurring voluntarily, before an outage forces it.
  • Backups with point-in-time restore. A daily dump is not enough if what matters is how much data you can afford to lose. PITR rests on the write log — WAL in Postgres, the oplog in MongoDB — and that log decides whether you go back to yesterday or to ten minutes ago.

Two traps that caught us specifically. First: the build server has no access to the database, so every function generating paths at build time has to account for that — otherwise the build passes locally and falls over in production. The second is sneakier: next build type-checks the whole project, so a directory excluded by .dockerignore can break a deployment while CI — building outside Docker — stays green. That cost us several deployments before we understood that green CI and a successful deploy are two different things.

Certificates. Coolify renews them automatically through Let’s Encrypt, but renewal requires the proxy to answer an HTTP challenge. If Cloudflare sits in front of the server in full proxy mode and the rules do not let everything through, renewal quietly fails and you find out ninety days after the deployment.

When this pays off, and when it does not

The decision is rarely technical. It comes down to whether anyone on the team will pick up the phone when the server stops answering on a Saturday.

Choose your own server if

Stay on a managed platform if

traffic is predictable and grows gradually

traffic jumps by orders of magnitude (campaigns, seasons)

you run several projects on the same machine

it is one project and one site

someone on the team is comfortable with Docker

nobody wants to be a server administrator

data has to stay in a specific jurisdiction

time to market matters more than the bill

a fixed, predictable invoice has value in itself

you would rather pay more for not being on call

If, after this arithmetic, your own server still looks sensible, the starting point is our public starter — Next.js 16, Payload 3, MongoDB and a Coolify deployment in one repository: nextjs-payload-starter.

The wider technology context — what the choice of stack does to the cost of a project — we take apart in: Comparing ways to build a website. And if you want the full maintenance bill, not just hosting: Recurring website fees.

We build deployments like this for ourselves and for clients — see how we build web applications.

FAQ

The version you install on your own server is open source and free, with the full feature set — you pay only for the VPS. What costs money is Coolify Cloud: 5 USD a month for two connected servers and 3 USD for each further one. It is worth understanding what that buys: Cloud hosts the control panel, while your applications still run on your server (Coolify pricing).

For a content site, a sensible starting point is 4 vCPU and 8 GB of RAM — the Hetzner CPX32 tier at 35.99 EUR a month. Below 4 GB the problem is not running the site, it is building a new version and processing images. If you build the image off the server, in GitHub Actions, the requirements drop noticeably.

Yes, but not on its own. By default the cache goes to .next/cache inside the container, so every instance has its own and nothing clears it when content is published. The combination that works is your own CacheHandler backed by Redis plus an afterChange hook in Payload calling revalidatePath after a save.

No. Since version 3, Payload runs as a package inside the Next.js application — same process, same build, one container. The database, Redis and the proxy get their own containers, but the admin panel does not.

It is a duty you take on together with the server, and the most common place where the saving turns out to be illusory. A daily dump is enough only if you accept losing a day's work. If you do not, you need point-in-time restore — which means space for the write log and a restore procedure you have rehearsed. A backup you have never restored is a hypothesis, not a backup.

When deployment starts to be noticeable to users — that is, when building the image on the same machine slows the database's responses. If you build off production, that moment moves much further out and often never arrives.

Where these numbers come from

Prices come from vendor price lists, read on 5 October 2026, excluding VAT: Vercel (20 USD per seat per month, 1 TB of traffic included, 0.15–0.35 USD per GB above that depending on the region, per the regional pricing page), Hetzner Cloud (CPX32: 4 vCPU, 8 GB RAM, 160 GB NVMe, 35.99 EUR a month including an IPv4 address, 20 TB of traffic in European regions; the CPX31 we priced earlier is now offered only in US locations) and MongoDB Atlas (M10 from 56.94 USD a month; a production database is a three-node replica set). The failures described here come from our own deployments, not from the literature.

Run the numbers on your project?

The arithmetic in this article is an example, not a quote — it changes with traffic, headcount and how many maintenance hours you actually have. If you are wondering which side of that line you are on, we will go through it together: what you really pay today, what you take on yourself, and how long the difference takes to pay back.

Let’s talk about your deployment

About the Team

Digital Vantage Team

Share:

FacebookTwitterLinkedInWhatsAppMessengerDiscord

Table of Contents · 6 sections · 11 minutes read

In this article

  1. 01What you actually pay each month
  2. 02What that table does not show
  3. 03Architecture: how this is put together
  4. 04Three things that break
  5. 05When this pays off, and when it does not
  6. 06Where these numbers come from

Comments

Rate this article

No comments yet. Be the first to share your thoughts!

Related Articles

Back to the guide: Websites — a guide to the whole section

⇲
Image on the Digital Vantage website

SEO cost — a calculation instead of a price range

We found no independent Polish benchmark for SEO cost. How to turn a fee and its hours into an hourly rate, and what to ask before signing.

Data publikacji: 03/10/2026
Characters: 23058•Words: 3555•Reading time: 18 min
⇲
Image on the Digital Vantage website

SMS Marketing for Online Stores — Consent, Cost and Compliance

SMS marketing for online stores: GDPR and ePrivacy consent, what a campaign costs in PLN, and the Gmail, Yahoo and Outlook rules for email.

Data publikacji: 02/10/2026
Characters: 16170•Words: 2465•Reading time: 13 min
⇲
Image on the Digital Vantage website

Fulfillment in e-commerce — what it is, what it costs and when it pays off

Ecommerce fulfillment: what the service covers, how providers in Poland price it, and when outsourcing your warehouse pays off instead of doing it in-house.

Data publikacji: 01/10/2026
Characters: 15700•Words: 2246•Reading time: 12 min
⇲
Image on the Digital Vantage website

On premise — what it means and when your own server beats the cloud

On premise, your own server: the full cost beyond hardware, the end of Windows Server 2016 support, and when the cloud or VPS wins instead.

Data publikacji: 30/09/2026
Characters: 20740•Words: 3175•Reading time: 16 min
⇲
Image on the Digital Vantage website

SLA — what it is and what to check in an SLA with a cloud provider

SLA meaning: how much downtime fits in 99.9%, how AWS, Microsoft and Google SLAs compare, SLO, RPO, RTO and 10 things to check before signing.

Data publikacji: 30/09/2026
Characters: 21530•Words: 3253•Reading time: 17 min
⇲
Image on the Digital Vantage website

Cloud computing — what it is and how IaaS, PaaS and SaaS differ

Cloud computing by the NIST definition: five traits, IaaS, PaaS and SaaS, public, private and hybrid cloud, and how Polish businesses actually use the cloud.

Data publikacji: 30/09/2026
Characters: 14724•Words: 2196•Reading time: 11 min
⇲
An oak card-index cabinet with a dozen drawers; two are pulled open, each holding its own tightly packed set of cards.

ERP system — what it is, when a small business needs one and what it really costs

What an ERP system is, how many Polish firms use one, when a small business needs it, what it costs beyond the price list and where it goes wrong.

Data publikacji: 22/09/2026
Characters: 18970•Words: 2880•Reading time: 15 min
⇲
Website Monitoring for Businesses - The Complete Guide to Tools and Strategies 2025

500, 502 Bad Gateway, 503 and 504 errors — what they mean and who to call when they hit your site

A 502 Bad Gateway, 500, 503 or 504 error tells you which part failed: the application, the link between servers or an overload. And who to call.

Data publikacji: 19/09/2026
Characters: 14843•Words: 2285•Reading time: 12 min
⇲
Image on the Digital Vantage website

404 Not Found, 403, 401 and 400 errors — what these status codes mean and how to fix them

A 404 Not Found on your own site is usually a page removed without a redirect. What 4xx status codes mean, what Google does and why our 404 returns 200.

Data publikacji: 19/09/2026
Characters: 14112•Words: 2228•Reading time: 12 min