Vercel with a managed database against a VPS running Coolify: 271 USD versus 17 EUR a month at 2 TB of traffic. Plus three failures that happened to us in production.
Cenniki platform serverless są tak skonstruowane, żeby start był darmowy. To działa: projekt rusza bez faktury, a pierwsze rachunki przychodzą dopiero wtedy, gdy coś zaczyna żyć. Problem w tym, że rosną nie proporcjonalnie do przychodu, tylko do transferu, liczby osób w zespole i czasu wykonania funkcji — trzech rzeczy, których na starcie nikt nie prognozuje.
Ten artykuł jest rachunkiem, nie manifestem. Po jednej stronie Vercel z bazą zarządzaną, po drugiej własny VPS z Coolify. Liczby pochodzą z cenników dostawców (sierpień 2026), a trzy awarie opisane na końcu wydarzyły się nam na produkcji, na dokładnie tym stosie, na którym stoi serwis, który właśnie czytasz.
Jeśli szukasz instrukcji krok po kroku, jest osobno: publiczny starter na GitHubie zawiera gotową konfigurację tego stosu, razem z plikami wdrożeniowymi.
Porównanie ma sens dopiero wtedy, gdy po obu stronach policzysz to samo: aplikację, bazę, transfer i miejsce na pliki. Przyjmijmy trzyosobowy zespół i 2 TB transferu miesięcznie — to skala małego serwisu z treścią, nie startupu po rundzie.
Pozycja | Vercel + Atlas | VPS z Coolify | Skąd liczba |
|---|---|---|---|
Aplikacja | 20 USD / os. → 60 USD | w cenie serwera | cennik Vercela |
Baza danych | od 57 USD (Atlas M10) | w cenie serwera | cennik Atlasa |
Transfer 2 TB | 1 TB w cenie, drugie ~154 USD | w cenie (20 TB w UE) | 0,15 USD/GB |
Serwer | — | 16,49 EUR (CPX31) | cennik Hetznera |
Razem | ≈ 271 USD | ≈ 17 EUR |
Dwie liczby z tej tabeli wymagają komentarza, bo to one robią różnicę. Pierwsza: transfer. Vercel Pro daje 1 TB, powyżej liczy 0,15–0,35 USD za gigabajt zależnie od regionu. Hetzner w regionach europejskich wlicza 20 TB — dwudziestokrotnie więcej, jako część ceny. Druga: baza. 57 USD to cena jednego węzła M10, a baza produkcyjna działa jako trójwęzłowy zestaw replik, więc realny rachunek jest bliżej trzykrotności, zanim doliczysz kopie zapasowe i transfer.
Jest też pozycja, której nie widać w żadnej tabeli: na własnym serwerze każda kolejna usługa jest darmowa. Worker do kolejki, własny cron, Redis, mały serwis pomocniczy — to jest ta sama maszyna. W modelu rozliczanym za wykonanie każda z nich ma własną pozycję na fakturze.
Różnica w abonamencie to nie oszczędność, tylko przesunięcie kosztu z faktury na czyjś czas. Przejmujesz trzy obowiązki, których wcześniej nie miałeś: kopie zapasowe wraz z odtwarzaniem do punktu w czasie, aktualizacje bezpieczeństwa i pilnowanie dostępności. Nie znikają dlatego, że rachunek zmalał — zmieniają właściciela.
Uczciwy przelicznik jest taki: jeśli utrzymanie zabiera dwie godziny miesięcznie przy stawce 150 zł, to 300 zł miesięcznie — czyli więcej niż zaoszczędzony abonament. Self-hosting wychodzi wtedy, gdy te godziny i tak są w zespole i dotyczą kilku projektów naraz, a nie jednego.
Payload od wersji 3 nie jest osobną aplikacją stojącą obok Next.js. Działa jako pakiet wewnątrz niego, dzieli ten sam proces, ten sam build i ten sam plik konfiguracyjny. To zmienia architekturę wdrożenia bardziej, niż się wydaje: panel administracyjny, API i frontend to jeden artefakt, więc jeden kontener aplikacji zamiast dwóch. Co Payload potrafi jako CMS i kiedy go wybieramy, opisujemy w: Payload CMS; sam Next.js rozkładamy w: Next.js.
Domyślnie idziemy w jeden kontener aplikacji plus osobne kontenery na bazę, Redis i proxy. Rozbijanie aplikacji na więcej procesów ma sens dopiero wtedy, gdy któryś z nich skaluje się inaczej niż reszta — na przykład worker przetwarzający kolejkę zadań, który przy imporcie danych potrzebuje pamięci, a przez resztę doby nie robi nic.
Usługa | Rola | Dlaczego osobno |
|---|---|---|
aplikacja | Next.js + Payload w jednym procesie | jeden build, jeden artefakt, jeden restart |
baza | MongoDB (albo Postgres — Payload 3 obsługuje oba) | inny cykl życia niż kod; przeżywa każde wdrożenie |
redis | cache, sesje, wspólny stan między instancjami | bez tego cache jest lokalny dla kontenera |
proxy | Traefik zarządzany przez Coolify | routing i certyfikaty Let’s Encrypt automatycznie |
Next.js potrafi zbudować katalog zawierający wyłącznie to, co jest potrzebne w czasie działania — bez pełnego drzewa zależności deweloperskich. Włącza się to jedną linią w konfiguracji (output: "standalone"), a różnica w rozmiarze obrazu jest rzędu wielkości: z około 1,5 GB schodzi się do mniej więcej 150 MB. To nie jest kosmetyka. Mniejszy obraz to krótszy transfer przy każdym wdrożeniu i wielokrotnie mniej miejsca zjadanego przez kolejne wersje, które Docker trzyma lokalnie.
Warunek jest jeden i łatwo go przeoczyć: przy budowaniu wielostopniowym trzeba ręcznie skopiować katalogi ze statycznymi zasobami i plikami publicznymi, bo standalone ich nie zabiera. Pominięcie tego daje działającą aplikację bez stylów — objaw, który wygląda na problem z CSS-em, a jest problemem z Dockerfile’em.
Poniżej rdzeń konfiguracji. Coolify dokłada do tego routing, domenę i certyfikat, więc w pliku nie ma ani słowa o Traefiku — to jest właśnie ta część, za którą się go używa zamiast gołego Dockera.
1services:2 app:3 build: .4 environment:5 DATABASE_URI: mongodb://mongo:27017/app6 PAYLOAD_SECRET: ${PAYLOAD_SECRET}7 REDIS_URL: redis://redis:63798 volumes:9 - media:/app/public/media # KAŻDY katalog uploadów osobno10 depends_on: [mongo, redis]1112 mongo:13 image: mongo:714 volumes:15 - dbdata:/data/db1617 redis:18 image: redis:7-alpine19 command: redis-server --save 60 120 volumes:21 - redisdata:/data2223volumes:24 media:25 dbdata:26 redisdata:
Uwaga do wolumenów, bo to najczęstsza pomyłka. System plików kontenera jest ulotny. Każdy katalog, do którego aplikacja zapisuje pliki, musi mieć własny wpis w volumes — i „każdy” znaczy każdy, osobno dla każdej kolekcji uploadów. Dodanie nowej kolekcji w Payloadzie bez dopisania wolumenu to nie jest błąd, który zobaczysz w logach. Zobaczysz go po restarcie, gdy plików nie będzie.
Kompletny zestaw — Dockerfile, compose, zmienne środowiskowe i lista kontrolna przed uruchomieniem — leży w naszym publicznym repozytorium: nextjs-payload-starter.
Poradniki opisują wdrożenie udane. Poniżej trzy mechanizmy, które psują je najczęściej — każdy z realnym incydentem z naszej produkcji jako dowodem, a nie ilustracją.
Komponent next/image domyślnie przelicza grafiki w procesie aplikacji, używając biblioteki sharp. Na platformie zarządzanej robi to osobna, skalowana usługa i nikt tego nie zauważa. W kontenerze na VPS-ie z 2–4 GB pamięci wgranie kilku zdjęć produktowych przez panel Payloada potrafi wywołać OOM Killer — jądro zabija proces, żeby ratować system. Aplikacja znika bez wpisu w logach aplikacyjnych, bo nie zdążyła go zapisać.
Skutek biznesowy jest nieproporcjonalny do przyczyny: serwis przestaje odpowiadać w środku dnia, a jeśli trafi na to robot wyszukiwarki, strona wypada z indeksu na czas znacznie dłuższy niż sama awaria.
Naprawa ma dwa kroki. Pliki wychodzą z serwera do magazynu zgodnego z S3 — w Payloadzie robi to @payloadcms/plugin-cloud-storage z adapterem na Cloudflare R2, AWS S3 albo Hetzner Storage Box. Przeliczanie obrazów oddaje się na zewnątrz: albo do CDN-u z transformacją w locie (Cloudflare Images), albo przez wyłączenie wbudowanego optymalizatora (images.unoptimized) i generowanie rozmiarów po stronie Payloada przy zapisie. Aplikacja przestaje wtedy trzymać w pamięci coś, czego trzymać nie musi. Szerzej o doborze hostingu, CDN-u i tego, co realnie przyspiesza serwis: Hosting, domeny i CDN.
Nasza wersja tego błędu była gorsza, bo cichsza. Nie zabrakło nam pamięci — zabrakło wolumenu. Katalog jednej z kolekcji nie miał podpiętego trwałego magazynu, więc przy restarcie kontenera zniknęły wszystkie jej pliki, a rekordy w bazie zostały i twierdziły, że pliki istnieją. Zdarzyło się dwa razy: raz przy kolekcji z materiałami, raz przy kolekcji z dokumentami — jedenaście plików raportów i szablonów zniknęło z dysku, podczas gdy strona nadal oferowała je do pobrania.
Na Vercelu odświeżanie stron statycznych i revalidateTag działają na poziomie globalnej sieci CDN. We własnym kontenerze cache Next.js zapisuje się do .next/cache na dysku tego kontenera. Wynikają z tego dwie rzeczy, obie nieprzyjemne: przy dwóch instancjach każda ma swój własny, niezsynchronizowany cache, a publikacja treści w panelu nie czyści go sama z siebie. To jest zresztą jedna z cen architektury headless — więcej o niej w: Headless — kiedy ma sens.
Naprawa. Własny CacheHandler wskazany w next.config, trzymający wpisy w Redisie — wtedy stan jest wspólny dla wszystkich instancji i przeżywa restart. Do tego hook afterChange w kolekcjach Payloada, który po zapisie woła revalidatePath albo revalidateTag dokładnie dla tego, co się zmieniło. Wariant minimalny — trwały wolumen na .next/cache — rozwiązuje tylko restart, nie skalowanie poziome.
Nasza wersja: dysk zapełniony do 89 GB, choć nikt nic nie wgrywał. Boty skanowały nieistniejące adresy, a renderowanie na żądanie zapisywało każdą z tych odpowiedzi jako plik cache w .next/server/app. Rosło to tygodniami, bez objawów, aż zabrakło miejsca. Naprawa okazała się jednolinijkowa — filtr odsiewający takie żądania, zanim wygenerują plik. Wniosek nie dotyczy jednak filtru, tylko tego, że na własnym serwerze cache jest Twoim katalogiem na Twoim dysku i nikt go za Ciebie nie sprząta.
Jeśli baza stoi na tej samej maszynie co aplikacja, to docker build podczas wdrożenia zabiera praktycznie cały procesor i pamięć. Efekt: serwis zwalnia dokładnie wtedy, gdy wdrażasz poprawkę — czyli zwykle wtedy, gdy coś już nie działa. Przy 8 GB RAM kompilacja Next.js potrafi też po prostu zostać zabita.
Dwie pułapki, które trafiły akurat nas. Pierwsza: serwer budujący nie ma dostępu do bazy, więc każda funkcja generująca ścieżki w czasie budowania musi to przewidzieć — inaczej build przechodzi lokalnie i wywala się na produkcji. Druga jest podstępniejsza: next build sprawdza typy w całym projekcie, więc katalog wykluczony przez .dockerignore potrafi wywalić wdrożenie, podczas gdy CI — budujące poza Dockerem — świeci na zielono. Straciliśmy na tym kilka wdrożeń, zanim zrozumieliśmy, że zielone CI i udany deploy to dwie różne rzeczy.
Certyfikaty. Coolify odnawia je automatycznie przez Let’s Encrypt, ale odnowienie wymaga, żeby proxy odpowiedziało na wyzwanie HTTP. Jeśli przed serwerem stoi Cloudflare w trybie pełnego proxy, a reguły przepuszczają nie wszystko, odnowienie cicho nie przechodzi i dowiadujesz się o tym dziewięćdziesiąt dni po wdrożeniu.
Decyzja rzadko jest techniczna. Sprowadza się do tego, czy w zespole jest ktoś, kto odbierze telefon, gdy serwer przestanie odpowiadać w sobotę.
Wybierz własny serwer, jeśli | Zostań przy platformie zarządzanej, jeśli |
|---|---|
ruch jest przewidywalny i rośnie stopniowo | ruch skacze o rzędy wielkości (kampanie, sezony) |
prowadzisz kilka projektów na tej samej maszynie | to jeden projekt i jedna strona |
ktoś w zespole czuje się swobodnie z Dockerem | nikt nie chce być administratorem serwera |
dane muszą zostać w konkretnej jurysdykcji | liczy się czas wejścia na rynek, nie rachunek |
stała, przewidywalna faktura ma wartość sama w sobie | wolisz zapłacić więcej za brak dyżuru |
Jeśli po tym rachunku własny serwer nadal wygląda sensownie, punktem wyjścia jest nasz publiczny starter — Next.js 16, Payload 3, MongoDB i wdrożenie na Coolify w jednym repozytorium: nextjs-payload-starter.
Szerszy kontekst technologiczny — co wybór stosu robi z kosztem projektu — rozkładamy w: Porównanie technik budowy strony. A jeśli interesuje Cię pełny rachunek utrzymania, nie tylko hosting: Opłaty cykliczne.
Budujemy takie wdrożenia u siebie i dla klientów — zobacz, jak realizujemy aplikacje webowe.
Wersja instalowana na własnym serwerze jest otwartoźródłowa i bezpłatna, z pełnym zestawem funkcji — płacisz wyłącznie za VPS. Płatny jest wariant Coolify Cloud: 5 USD miesięcznie za dwa podłączone serwery i 3 USD za każdy kolejny. Warto rozumieć, co się wtedy kupuje: Cloud utrzymuje panel sterujący, a Twoje aplikacje i tak działają na Twoim serwerze (cennik Coolify).
Do serwisu z treścią rozsądnym punktem startowym jest 4 vCPU i 8 GB RAM — to poziom Hetznera CPX31 za 16,49 EUR miesięcznie. Poniżej 4 GB pamięci problemem nie jest działanie, tylko budowanie nowej wersji i przetwarzanie obrazów. Jeśli budujesz obraz poza serwerem, w GitHub Actions, wymagania spadają wyraźnie.
Tak, ale nie samo z siebie. Domyślnie cache trafia do .next/cache wewnątrz kontenera, więc każda instancja ma własny i nic go nie czyści po publikacji treści. Działający zestaw to własny CacheHandler oparty o Redis plus hook afterChange w Payloadzie, wołający revalidatePath po zapisie.
Nie. Od wersji 3 Payload działa jako pakiet wewnątrz aplikacji Next.js — ten sam proces, ten sam build, jeden kontener. Osobne kontenery mają baza danych, Redis i proxy, ale nie panel administracyjny.
To obowiązek, który przejmujesz razem z serwerem, i najczęstsze miejsce, w którym oszczędność okazuje się pozorna. Zrzut raz na dobę wystarcza tylko wtedy, gdy akceptujesz utratę doby pracy. Jeśli nie — potrzebujesz odtwarzania do punktu w czasie, czyli miejsca na dziennik zapisów i przećwiczonej procedury przywracania. Kopia, której nigdy nie odtwarzałeś, jest hipotezą, nie kopią.
Wtedy, gdy wdrożenie zaczyna być odczuwalne dla użytkowników — czyli gdy budowanie obrazu na tej samej maszynie spowalnia odpowiedzi bazy. Jeśli budujesz poza produkcją, ten moment przesuwa się znacznie dalej i często nie nadchodzi wcale.
Ceny pochodzą z cenników dostawców, stan na sierpień 2026: Vercel (20 USD za osobę miesięcznie, 1 TB transferu w cenie, powyżej 0,15–0,35 USD za GB zależnie od regionu), Hetzner Cloud (CPX31: 4 vCPU, 8 GB RAM, 160 GB NVMe, 16,49 EUR miesięcznie, 20 TB transferu w regionach europejskich) oraz MongoDB Atlas (M10 od około 57 USD miesięcznie za węzeł; baza produkcyjna to trójwęzłowy zestaw replik). Opisane awarie pochodzą z naszych własnych wdrożeń, nie z literatury.
Rachunek z tego artykułu jest przykładem, nie wyceną — zmienia go ruch, liczba osób w zespole i to, ile godzin utrzymania faktycznie masz. Jeśli zastanawiasz się, po której stronie tej granicy jesteś, przejdziemy przez to razem: co realnie płacisz dziś, co przejmujesz na siebie i po jakim czasie różnica się zwraca.
Your Partner in Business, Digital Vantage Team
Digital Vantage team is a group of experienced professionals combining expertise in web development, software engineering, DevOps, UX/UI design and digital marketing. Together we carry out projects from concept to implementation - websites, e-commerce stores, dedicated applications and digital strategies. Our team combines years of experience from technology corporations with the flexibility and immediacy of working in a smaller, close-knit structure. We work in agile methodologies, focus on transparent communication and treat each project as if it were our own business. The strength of the team is the diversity of perspectives - from systems architecture and infrastructure, frontend and design, to SEO and content marketing strategy. As a result, the client receives a cohesive solution where technology, aesthetics and business goals go hand in hand.
Rate this article

When a low quote makes sense and when it is a trap, plus the costs that surface after launch. Figures from our Polish market study.

Learn more about Costs. A practical guide with concrete tips and examples. Learn best practices and avoid common mistakes.

What are the real costs of creating an online store in 2026? Check out an overview of expenses: domain, hosting, e-commerce platforms, advertising, SEO.

What is a website wireframe and why should you prepare one? Find out how a wireframe helps you plan UX, reduce costs and avoid mistakes.

Learn about one-time website costs: hidden expenses, UX/UI rates, hosting, integrations and budgeting strategy. Find out how to save.

How much does it realistically cost to maintain a site? Find out about hosting, domain, extensions after promotions and budget 200-800 PLN. Learn 5 ways to save money.

A comparison of techniques (WordPress, custom, no-code) with specific costs, hidden expenses and a 5 question framework. Learn how to choose and save.

Wireframing is the process of creating the skeleton of a website - a structure that shows where the various elements will be located, how they will work and in what order the user will interact with them.

Build trust in 3 seconds, Automatically generate leads 24/7, Reduce repeat inquiries by 60%, Competitive advantage with SEO