RAM dla VPS z WordPressem policz tak: około 400 MB na system, nginx, MariaDB i współdzieloną część PHP, do tego zapełniona część buffer poola bazy danych, do tego liczba workerów PHP-FPM razy pamięć jednego workera, a na koniec dodaj 25% zapasu. Na naszym stanowisku testowym lekka strona mieści się według tego wzoru w 1 GB, a sklep z ciężkimi wtyczkami potrzebuje 4 GB lub więcej. Liczba vCPU decyduje, ile niezcache’owanych stron serwer zwraca na sekundę: 2 vCPU obsłużyły około 42 takich żądań WordPressa, a z cache stron nginx ponad 14 000. NVMe oceniaj po losowych operacjach 4K, a nie po prędkości sekwencyjnej z reklam.
Jak testowaliśmy
Stanowisko testowe RichHost, 25 października 2026: izolowany kontener z 2 vCPU / 8 GB RAM (KVM, Intel Xeon 2,1 GHz), Ubuntu 24.04, nginx 1.24, PHP 8.3-FPM z OPcache, MariaDB 10.11.14, WordPress 6.7.2, motyw Twenty Twenty-Five, 300 wpisów. Pamięć to PSS i RSS każdego procesu z /proc/<pid>/smaps_rollup, szczyt z próbek pobieranych co 2 sekundy, gdy ab obciążał niezcache’owaną stronę wpisu. Buffer pool MariaDB testowaliśmy na tymczasowej tabeli 258 MB (milion wierszy), usuniętej po teście. Dysk: fio 3.36 z direct=1 i dd na pliku 1 GB. To liczby laboratoryjne ze stanowiska testowego, a nie dane produkcyjne RichHost ani benchmark jakiegokolwiek dostawcy VPS.
Ile pamięci zużywają nginx, PHP-FPM i MariaDB
top i ps pokazują RSS: całą pamięć, której dotknął proces, łącznie ze stronami współdzielonymi. Workery PHP-FPM współdzielą OPcache, więc suma ich RSS kilkukrotnie zawyża rzeczywiste zużycie. Dokładniejszy jest PSS: strony współdzielone są dzielone między procesy, które z nich korzystają, dlatego wartości PSS można po prostu zsumować.
| Komponent | Tuż po starcie | Po pierwszych żądaniach | Pod obciążeniem, 5 workerów |
|---|---|---|---|
| nginx (master, 2 workery, cache manager) | 5,5 MB | 5,3 MB | 5,5 MB |
| Master PHP-FPM | 3,3 MB | 3,6 MB | 2,2 MB |
| Workery PHP-FPM | 2 × 3,1 MB | 2 × 23 MB | 5 workerów, łącznie 69,7 MB |
| MariaDB (buffer pool 128 MB, baza WordPressa 1 MB) | 102 MB | 103 MB | 104 MB |
| Cały stos razem | 117 MB | 158 MB | 181 MB |
Bez systemu operacyjnego cały stos małej strony na WordPressie pod obciążeniem nie przekroczył 200 MB. Samo Ubuntu na VPS z systemd, journald, SSH i cronem potrzebuje mniej więcej kolejnych 200-300 MB: kontener testowy nie ma żadnej z tych usług, więc ta wartość to szacunek, a nie pomiar.
Ile pamięci potrzebuje jeden worker PHP-FPM
Aby oddzielić część współdzieloną od własnej pamięci każdego workera, ustaliliśmy stałą liczbę workerów (pm = static) i wysłaliśmy 20 równoczesnych żądań:
| Workery | PSS wszystkich workerów | Suma RSS | Żądania na sekundę |
|---|---|---|---|
| 5 | 69,9 MB | 213 MB | 42,0 |
| 10 | 106,6 MB | 421 MB | 40,6 |
| 20 | 179,4 MB | 844 MB | 38,6 |

Każdy dodatkowy worker dokłada 7,3 MB, a około 33 MB jest współdzielone, głównie OPcache (31 MB z 128 MB w użyciu, 480 skryptów). Pojedynczy worker pokazuje w ps 42-50 MB RSS, co zgadza się z wcześniejszymi pomiarami na stanowisku, ale do planowania pamięci ta wartość jest mniej więcej pięciokrotnie za wysoka. Szczytowe zużycie pamięci PHP na żądanie na stanowisku: 5,1 MB na stronie głównej i we wpisie, 5,9 MB w kokpicie, 8 MB (12 MB przydzielone) w edytorze wpisów.
To lekki motyw bez wtyczek. Nie uruchamialiśmy na stanowisku WooCommerce, page builderów ani wtyczek do importu, więc ich zużycie nie jest tu ujęte. Górną granicę wyznacza memory_limit: rdzeń WordPressa domyślnie żąda 40 MB dla strony i 256 MB dla panelu administracyjnego (WP_MEMORY_LIMIT i WP_MAX_MEMORY_LIMIT). Własne liczby na działającym serwerze sprawdzisz tak (wynik ze stanowiska):
for p in $(pgrep -f "php-fpm: pool"); do sudo awk '/^Pss:/{print $2}' /proc/$p/smaps_rollup; done \
| awk '{s+=$1; n++} END{printf "workers=%d PSS=%.0f MB, avg %.1f MB\n", n, s/1024, s/n/1024}'
workers=5 PSS=53 MB, avg 10.6 MB
sudo awk '/^Pss:/{printf "mariadbd PSS=%.0f MB\n", $2/1024}' /proc/$(pgrep -x mariadbd)/smaps_rollup
mariadbd PSS=125 MB
Średni PSS workera po godzinie normalnego ruchu jest nieco wyższy niż rzeczywisty przyrost na worker, bo zawiera udział pamięci współdzielonej. Przy doborze konfiguracji to nie problem: daje niewielki zapas.
MariaDB: co naprawdę robi innodb_buffer_pool_size
Buffer pool InnoDB zajmuje pamięć dopiero wtedy, gdy trafiają do niego dane. Uruchomiliśmy MariaDB z trzema rozmiarami poola, puściliśmy obciążenie WordPressa, potem trzy razy odczytaliśmy tymczasową tabelę 258 MB i wykonaliśmy 10 000 losowych wyszukiwań po kluczu głównym:
| innodb_buffer_pool_size | PSS po starcie | Po obciążeniu WordPressa | Po odczycie 258 MB | Ponowny pełny odczyt | 10 000 losowych wyszukiwań |
|---|---|---|---|---|---|
| 32 MB | 119 MB | 121 MB | 122 MB | 0,50-0,57 s | 0,68 s |
| 128 MB (domyślnie) | 114 MB | 117 MB | 219 MB | 0,52 s | 0,47 s |
| 512 MB | 140 MB | 145 MB | 375 MB | 0,24 s | 0,25 s |
Przy bazie WordPressa o rozmiarze 1 MB wielkość poola nie miała żadnego znaczenia: 38,9, 42,5 i 40,0 żądania na sekundę mieszczą się w szumie pomiarowym. Zmniejszanie poola poniżej 128 MB, by „zaoszczędzić” pamięć na małym VPS, nie ma sensu. Zwiększ go, gdy dane przestają się mieścić: z poolem 512 MB tabela 258 MB została odczytana dwa razy szybciej. Na stanowisku z 8 GB chybienia poola obsługiwał cache systemu plików, więc na VPS z 1-2 GB różnica będzie większa. Rozmiar swoich baz sprawdzisz poleceniem:
mariadb -e "SELECT table_schema, ROUND(SUM(data_length+index_length)/1048576) AS mb
FROM information_schema.tables GROUP BY table_schema"
Wzór na RAM i trzy przykłady
Z pomiarów wynika prosty wzór:
RAM = (B + P + N × X) × 1,25, gdzie B to około 400 MB (system mniej więcej 250 MB, nginx 6 MB, MariaDB 110 MB, współdzielona część PHP-FPM 33 MB), P to zapełniona część buffer poola, czyli rozmiar aktywnych danych, ale nie więcej niż innodb_buffer_pool_size, N to pm.max_children, a X to pamięć jednego workera. Współczynnik 1,25 zostawia miejsce na cache systemu plików, crona i szczyty żądań.
| Strona | N | X | P | Obliczenie | Wybierz |
|---|---|---|---|---|---|
| Blog lub landing page, lekki motyw, cache stron | 5 | 10 MB (zmierzone 7,3) | 50 MB | (400 + 50 + 50) × 1,25 = 625 MB | 1 GB |
| Strona firmowa lub 3-5 stron z wtyczkami | 10 | 40 MB (założenie) | 256 MB | (400 + 256 + 400) × 1,25 = 1320 MB | 2 GB |
| Sklep na WooCommerce | 20 | 80 MB (założenie) | 1 GB | (400 + 1024 + 1600) × 1,25 = 3780 MB | 4 GB, 6-8 GB z Redisem i wyszukiwarką |
X w drugim i trzecim wierszu to nasze założenie, a nie pomiar: użyj średniego PSS workera ze swojego serwera. Jeśli suma zbliża się do zainstalowanej pamięci RAM, jądro zaczyna wypychać dane do swapu, a bez swapu OOM killer zatrzymuje MariaDB albo PHP-FPM. Inne ustawienia stosu, które warto sprawdzić przed zmianą planu na większy, opisuje nasz poradnik o konfiguracji serwera.
Ile vCPU: co pokazał serwer z 2 rdzeniami
| Scenariusz na 2 vCPU | TTFB, mediana | Żądania na sekundę |
|---|---|---|
| OPcache wyłączony | 190-195 ms | 9,7-9,8 |
| OPcache włączony, bez cache stron | 41-45 ms | 41,6-44,1 |
| Symulowana ciężka wtyczka (150 zapytań SQL + 250 ms zewnętrznego API) | 309-311 ms | 15,0-15,3 |
| Ta sama ciężka wtyczka, 20 workerów zamiast 5 | 846 ms przy 20 równoczesnych | 18,8 zamiast 14,0 |
| Cache stron nginx fastcgi_cache, anonimowi odwiedzający | 0,3 ms | 14 700-21 600 |

Bez cache stron głównym ograniczeniem jest CPU: 2 vCPU przy około 42 żądaniach na sekundę oznaczają mniej więcej 48 ms czasu CPU na stronę, prawie tyle co TTFB. Stąd praktyczna reguła: vCPU ≈ szczytowa liczba niezcache’owanych żądań na sekundę × TTFB w sekundach. Na przykład 100 żądań na sekundę od zalogowanych użytkowników lub z koszyków przy TTFB 45 ms daje 4,5 rdzenia, czyli 4-6 vCPU. Ruch anonimowy obsługiwany z cache stron prawie nie obciąża CPU, dlatego cache i RAM są często tańsze niż większy plan.
Więcej workerów nie przyspiesza, dopóki PHP liczy: przy 20 workerach zamiast 5 serwer zwrócił 38,6 zamiast 42 żądań na sekundę. Workery pomagają tylko wtedy, gdy żądania czekają na zewnętrzne API lub wolną bazę danych, jak w scenariuszu z ciężką wtyczką. Praktyczna zasada: 2-3 workery na vCPU dla typowej strony, a więcej tylko wtedy, gdy żądania wyraźnie czekają i pozwala na to pamięć. Przydzielone rdzenie i steal time sprawdzisz tak (wynik ze stanowiska):
nproc
2
lscpu | grep -E "^CPU\(s\)|Model name|Hypervisor"
CPU(s): 2
Model name: Intel(R) Xeon(R) Processor @ 2.10GHz
Hypervisor vendor: KVM
vmstat 1 5 # column st = steal time, 0-1% on our bench
Jeśli st utrzymuje się powyżej kilku procent, fizyczny host jest przeciążony przez sąsiadów: skontaktuj się z pomocą techniczną albo przejdź na plan z dedykowanymi rdzeniami.
Dysk: dlaczego liczą się losowe operacje 4K
| Test (fio, direct=1) | Przepustowość | IOPS | Opóźnienie p50 / p99 |
|---|---|---|---|
| Odczyt sekwencyjny, bloki 1 MB | 2565 MB/s | 2446 | 326 / 561 µs |
| Zapis sekwencyjny, bloki 1 MB | 440 MB/s | 419 | 1745 / 2900 µs |
| Odczyt losowy 4K, głębokość kolejki 1 | 108 MB/s | 26 321 | 23 / 60 µs |
| Zapis losowy 4K, głębokość kolejki 1 | 45,5 MB/s | 11 106 | 58 / 144 µs |
| Odczyt losowy 4K, głębokość kolejki 32 | 464 MB/s | 113 191 | 230 / 610 µs |
| Zapis losowy 4K, głębokość kolejki 32 | 144 MB/s | 35 160 | 725 / 1368 µs |
dd, zapisy 4K z oflag=dsync |
18,4 MB/s | ~4 500 | - |

Na tym samym dysku przepustowość różniła się 140-krotnie: 2565 MB/s przy odczycie sekwencyjnym i 18,4 MB/s przy małych zapisach potwierdzanych pojedynczo, czyli tak, jak baza danych zatwierdza transakcje. To liczby z naszego kontenera, a nie benchmark dostawcy, i cache hosta mógł je poprawić, ale ta proporcja jest typowa dla każdego dysku. Szukaj więc na stronie planu IOPS albo przynajmniej typu pamięci masowej (lokalny NVMe czy pamięć sieciowa) i przetestuj serwer samodzielnie pierwszego dnia:
sudo apt install -y fio
fio --name=rand4k --filename=/root/fio.test --size=1G --rw=randwrite --bs=4k \
--iodepth=1 --ioengine=libaio --direct=1 --runtime=15 --time_based --group_reporting
rm /root/fio.test
Przy pojemności licz 5-10 GB na system, plus strony i bazy danych, plus logi i lokalne kopie zapasowe, plus 20-30% wolnego miejsca. Gdy dysk zapełni się całkowicie, MariaDB przestaje zapisywać dane.
Jaką konfigurację wybrać według typu strony
Tabela powstała na podstawie powyższego wzoru i pomiarów ze stanowiska. Traktuj liczby jako punkt wyjścia: sprawdź swój serwer poleceniami z tego artykułu i skaluj według rzeczywistego obciążenia.
| Jeśli masz | vCPU | RAM | NVMe | Dlaczego |
|---|---|---|---|---|
| Jedną lub kilka stron bez własnego oprogramowania | VPS nie jest konieczny, wystarczy hosting współdzielony | Stos zajmuje 200-600 MB, a ty unikasz administrowania serwerem | ||
| Blog lub landing page z cache stron | 1 | 1 GB | 20 GB | Wyliczone 625 MB, cache obsługuje ruch anonimowy |
| Strona firmowa, 3-5 stron z wtyczkami | 2 | 2 GB | 40 GB | Wyliczone 1,3 GB, 2 vCPU dają około 40 niezcache’owanych żądań/s |
| Sklep na WooCommerce | 2-4 | 4-8 GB | 60-80 GB | Koszyk i konto klienta nie trafiają do cache, baza danych rośnie |
| Wielu zalogowanych użytkowników (forum, LMS) | według wzoru na vCPU | 4 GB lub więcej | 40-80 GB | Cache stron nie działa, licz szczytowe żądania × TTFB |
| Osobny serwer bazy danych | 2-4 | aktywne dane + 30-50% | z zapasem IOPS | Pool musi pomieścić dane robocze, inaczej baza czyta z dysku |
RichHost nie sprzedaje planów VPS. Jeśli prowadzisz jedną lub kilka stron bez własnego oprogramowania serwerowego, zwykle wystarczą plany hostingu współdzielonego z dyskami NVMe i własnym panelem sterowania z asystentem AI, a poradnik o tym, jakiego rodzaju hostingu potrzebuje strona, wyjaśnia dostępne opcje. Ceny według konfiguracji porównujemy w zestawieniu cen serwerów VPS, a pierwsze kroki po zamówieniu opisuje poradnik konfiguracja VPS z Ubuntu 24.04. Gdy jeden VPS przestaje wystarczać, przeczytaj, kiedy VPS już nie wystarcza.
Najczęstsze pytania
Dlaczego top pokazuje, że PHP-FPM zajmuje gigabajt, skoro pamięci nie brakuje?
top i ps pokazują RSS, który liczy współdzielony OPcache w każdym workerze. Na stanowisku 20 workerów miało łącznie 844 MB RSS, ale tylko 179 MB rzeczywistego PSS.
Ile workerów PHP-FPM na 2 vCPU?
4-6 dla typowej strony: na stanowisku 5 workerów dało najwięcej żądań na sekundę. Więcej ustawiaj tylko wtedy, gdy żądania czekają na zewnętrzne usługi, i tylko jeśli N × X mieści się w pamięci.
Czy zmniejszać innodb_buffer_pool_size na VPS z 1 GB?
Przy małej bazie nie: pool zajmuje pamięć tylko na dane, które do niego trafiły. Z poolem 32 MB i 128 MB baza WordPressa o rozmiarze 1 MB zużywała tyle samo pamięci.
Czy 1 GB RAM wystarczy dla WordPressa?
Dla jednej lekkiej strony z cache stron tak: nasz wzór daje około 625 MB. Dla sklepu lub kilku stron z ciężkimi wtyczkami nie.



