Ви не відчуваєте вибору веб-сервера в спокійний вівторок. Ви відчуваєте його о 02:13 в суботу, коли оформлення замовлення зависає,
дашборди брешуть, а ваш мозок на виклику починає рахувати втрати пакетів. «Nginx проти Apache» — це не ідеологія.
Це про те, з якими режимами відмов ви згодні жити, які операційні ручки ваша команда справді крутитиме і які
налаштування за замовчуванням тихо витягуватимуть у вас ресурси місяцями.
У 2026 році правильна відповідь часто звучить так: «обоє, але навмисно». Рішення, яке справді має значення — це межа:
де завершується TLS, де відбувається буферизація запитів, де виконується динамічний код, де дозволені перевизначення по орендарю
і де ви хочете, щоб радіус аварії зупинився.
Що справді має значення у 2026 році (і що — ні)
У 2010 році питання було «який швидший?». У 2026 році сирий бенчмарк рідко є вашим вузьким місцем. Зазвичай ваш
вузький зуб — одне з цього: насичення апстріму (додаток або БД), невірні налаштування буферизації, надто багато повільних клієнтів,
проблеми з TLS або HTTP/2, стрибки латентності файлової системи або модель конфігурації, яка дозволяє випадковим командам
змінювати поведінку продакшену без рев’ю.
Рішення, яке справді має значення
Ви обираєте не просто веб-сервер. Ви обираєте контрольно-управлінський рівень для трафіку і конфігурації:
- Де ви завершуєте TLS? Саме там живуть сертифікати, шифри, ALPN, OCSP і клієнтські особливості.
- Де ви буферизуєте запити та відповіді? Це визначає, чи потонуть ваші апстріми від повільних клієнтів.
- Чи дозволяєте ви перевизначення по директоріях? Це питання управління, замасковане під фічу.
- Як ви робите reload? Якщо reload лякає — люди затримуватимуть виправлення. Затримані виправлення перетворюються на інциденти.
- Що ви логуєте за замовчуванням? Тому що ви будете дебажити тим, що записали, а не тим, що хотіли б записати.
Шість–десять історичних фактів, що досі впливають
- Apache HTTP Server почався у 1995 році як набір патчів («patchy server»). Його екосистема модулів і розростання конфігурації — пряме наслідок цього походження.
- Nginx створили на початку 2000-х для вирішення проблеми C10k: ефективно обробляти 10 000 одночасних з’єднань за допомогою подійної моделі.
- Розподіл MPM в Apache (prefork/worker/event) існує тому, що довелося узгодити потоки, процеси та не-потокобезпечні модулі з плином часу.
- .htaccess — це культурний артефакт з shared hosting: децентралізувати контроль по директоріях й прийняти накладні витрати. Зручно, але операційно хаотично.
- Ідентичність Nginx як «зворотного проксі перш за все» сформувала сучасні стеки, де «веб-сервер» часто — маршрутизатор трафіку, а не виконавець коду.
- HTTP/2 змінив завантаження ресурсів (мультиплексування), але також ввів head-of-line blocking на рівні TCP, роблячи латентність і втрати більш помітними.
- QUIC/HTTP/3 перемістили транспорт на UDP, що змінює поведінку міжмережевих коробок, фаєрволів і спостережуваності, особливо в корпоративних мережах.
- Let’s Encrypt нормалізував автоматизацію короткоживучих сертифікатів, і твердження «TLS складний» стало менш справедливим, але «відновлення TLS ламає продакшн о 3:00» все ще правда.
- Покращення в ядрі (epoll, sendfile, TCP tuning) зробили обидва сервери швидшими; тепер відмінність — у моделі конфігурації та поведінці при відмовах.
Висновок: обидва сервери «достатньо швидкі» для більшості сайтів. Питання в тому, який з них зробить наступний інцидент коротшим, дешевшим і менш принизливим.
Жорсткі рекомендації (обирайте це, уникайте того)
Якщо ви керуєте типовим сучасним Linux веб-стеком
- За замовчуванням обирайте Nginx на краю для статичних ресурсів, термінації TLS, кешування та зворотного проксі до беку додатків.
- Запускайте додатки за ним через PHP-FPM, uWSGI, Gunicorn, Node або що б ви там не обрали, про що потім жалкуватимете.
- Використовуйте Apache тільки коли він потрібен: інтенсивні правила per-directory, застарілі додатки або модулі, які важко замінити.
Якщо у вас кілька команд редагують конфіг
- Уникайте .htaccess у проді, якщо ви не любите робити постмортеми зі словами «хтось відредагував файл у директорії на випадковому хості».
- Надавайте перевагу централізованій конфігурації та CI-валідації (Nginx природно підходить для цього; Apache теж може, але .htaccess часто саботує процес).
Якщо ви хостите контент, створений користувачами, або маєте справу з повільними клієнтами
- Модель буферизації Nginx зазвичай простіша для розуміння: ви можете захистити апстріми від повільних завантажень/завантажень.
- Apache теж може, але потрібно бути явним і обережним з вибором MPM і таймаутами.
Жарт №1: Обирати веб-сервер тому, що бенчмарк показав на 3% швидше — це як вибирати парашут за кольором. Погану вибірку ви помітите лише одного разу.
Архітектура, яка переживає реальний трафік
Архітектура, що тримає ваш пейджер тихо, виглядає нудною:
Nginx (edge) → сервери додатків (PHP-FPM / контейнери / рантайм мови) → БД/кеш.
Помістіть «дорогу думку» (динамічний код) за тим, що може поглинати дивну поведінку клієнтів.
Обов’язки краю (що належить на фронті)
- Термінація TLS з розумними шифрами, відновленням сесій, OCSP stapling там, де доцільно.
- Обмеження запитів (rate/conn) і базовий захист від зловживань. Не «театральна» безпека — а формування навантаження.
- Статичні ресурси з диска з коректними caching headers.
- Compressія (обережно з форматами, що вже стиснуті) та коректні content-type.
- Маршрутизація до апстрімів, health checks (або хоча б таймаути з урахуванням стану), граціозна поведінка при відмовах.
Обов’язки апстріму (що належить позаду)
- Динамічний рендеринг і бізнес-логіка.
- Аутентифікація/авторизація (край може допомагати, але не запихайте модель ідентичності в проксі-конфіг).
- Доступ до БД і логіка кешування.
Чому «просто запускати Apache з mod_php» — здебільшого спадщина
Справа не в тому, що mod_php не працює. Річ у тому, що він зв’язує модель HTTP-воркера з життєвим циклом PHP, і ця
зв’язка — місце, куди йдуть операційні свободи. Також це заохочує «ще одне правило перезапису», розкидане по директоріях.
Сучасна реальність: ви хочете чіткий шов між «прийняти трафік від клієнта» й «виконати код додатка». У цей шов
поміщають таймаути, буферизацію, ліміти й спостережуваність. Nginx робить цей шов природним. Apache теж може, але
вам доведеться боротися зі старими значеннями за замовчуванням і звичками.
Глибоке занурення в Apache: MPM, .htaccess і коли він виграє
Вибір MPM — не опція
Якщо ви запускаєте Apache у 2026 і не знаєте, який MPM у вас використовується, ви керуєте ним «за відчуттями». Перестаньте.
Мульти-процесні модулі Apache визначають поведінку конкуренції та ресурсів:
- prefork: по одному процесу на з’єднання. Сумісний зі старими, не потокобезпечними модулями. Високе споживання пам’яті. Легко перегрузити при великій конкуренції.
- worker: потоки в процесі. Краща економія пам’яті. Важлива потокобезпека модулів.
- event: як worker, але краща робота з keep-alive. Загалом найкращий дефолт для сучасного Apache в ролі зворотного проксі.
Переваги Apache досі реальні:
- Сумісність: застарілі корпоративні додатки, старі модулі авторизації і налаштування, що залежать від семантики Apache.
- Конфігурація по директоріях: якщо ви дійсно в мульти-орендному середовищі з делегованим контролем, .htaccess може бути найменш поганим вибором.
- Екосистема модулів: деякі модулі фактично «тільки для Apache» в оперативній культурі, а не лише в коді.
.htaccess: фіча чи пастка?
.htaccess існує тому, що shared hosting потребував розподіленого контролю. Це також змушує Apache перевіряти файли-перевизначення
в директоріях під час обробки запиту. Ця вартість часто незначна для одного запиту, доки ви не масштабували, не збили кеш
або не поклали контент на файлову систему з вищою латентністю.
Більша проблема — не CPU. Це контроль змін. З .htaccess розробник може «полагодити прод» редагуванням файлу на одному хості,
обминаючи рев’ю, CI і відкат. Ви не хочете, щоб «дрейф конфігурації» став рисою характеру вашого флоту.
Глибоке занурення в Nginx: event loop, буферизація і коли він виграє
Nginx — фактично опінонований трафік-машин: мала кількість воркерів, event loop і звичка буферизувати, щоб захистити апстріми.
Він сяє, коли потрібно одночасно обробляти багато з’єднань, не прив’язуючи потік/процес до кожного клієнта.
Де Nginx зазвичай правильний вибір
- Зворотне проксування до кількох апстрімів з передбачуваною поведінкою під навантаженням.
- Роздача статичних файлів з sendfile, caching headers та адекватними keep-alive.
- Формування навантаження (rate limiting, connection limiting), яке просто розуміти.
- Операційна гігієна: централізована конфігурація, тестований синтаксис, reload, що не рве активні з’єднання при правильному налаштуванні.
Де Nginx підводить людей
- Неочікуваності буферизації: якщо ви не розумієте буферизацію запитів/відповідей, можете ненавмисно наростити диск-IO або латентність.
- Невідповідні таймаути: таймаути Nginx, які не збігаються з таймаутами апстріму, породжують «таємничі 504».
- Читабельність конфігурації: конфіг Nginx чистий, поки не ні. Вкладені location і regex-правила можуть стати головоломкою.
Жарт №2: Конфіги Nginx не стають нечитаємими поступово. Вони стають такими в момент, коли хтось каже: «ще один блок location — і все буде ок».
HTTP/2, HTTP/3, TLS і те, що тихо ламається
HTTP/2 і HTTP/3 — це не «включи і стане швидше». Вони змінюють ваші режими відмов.
Мультиплексування HTTP/2 зменшує кількість з’єднань, але може посилити біль від втрат пакетів на одному з’єднанні.
HTTP/3 (QUIC) може покращити продуктивність в умовах ненадійних мереж, але він також взаємодіє з фаєрволами та моніторингом
так, що ваша мережна команда почне ставити гострі питання.
Термінація TLS: оберіть місце і відповідайте за нього
Завершувати TLS на краю зазвичай зручно, бо це централізує сертифікати й тюнінг продуктивності. Але централізація також централізує відповідальність.
Плюс: менше рухомих частин. Мінус: одна неправильно налаштована набір шифрів може повалити весь флот.
Одна цитата про надійність, яку варто засвоїти
Сподівання — це не стратегія.
— перефразована ідея, яку часто приписують лідерам з операцій і надійності.
Перефразовано чи ні, суть операційно точна: не «надійтеся», що ваші таймаути вирівняються, що відновлення TLS спрацює,
або що налаштування HTTP/2 в порядку. Доведіть це тестами й дашбордами.
Динамічні додатки: PHP-FPM, проксі та реальність
Більшість «Nginx проти Apache» суперечок насправді — це «як ми запускаємо динамічний код?» суперечки. У 2026 році PHP-FPM
все ще поширений вибір, і різниця між стабільною системою та флапаючою зазвичай — це розмір пулу, таймаути і
зворотний тиск апстріму — а не бренд фронт-енд веб-сервера.
Що варто стандартизувати
- Ланцюг таймаутів: клієнт → edge proxy → рантайм додатка → БД. Встановіть їх свідомо, задокументуйте максимальний очікуваний час запиту.
- Зворотний тиск: що робити, коли додаток насичений? Черга? Відхилити? Скинути навантаження? Це продуктове рішення в костюмі SRE.
- Максимальний розмір тіла запиту: якщо ви приймаєте завантаження, накладайте ліміти в одному місці (edge) і перевіряйте повторно в додатку.
- Поля спостережуваності: request ID, timings апстріму, статус, передані байти і деталі TLS для дебагу.
Коли Apache — пристойний фронт-енд для додатка
Якщо у вас старий PHP-додаток, який залежить від поведінки специфічної для Apache, або у вас зріла внутрішня екосистема навколо модулів Apache,
зберегти Apache поруч із додатком може бути правильним. Але вам усе одно потрібен стабільний edge попереду — часто Nginx, іноді апаратний або хмарний LB —
щоб шар додатка не був вашим буфером для клієнтського шоку.
Спостережуваність, яка запобігає пошуку винних
Якщо у вас є тільки метрика «запитів за секунду», ви не спостерігаєте — ви рахуєте. Для Nginx/Apache мінімальний набір видимості має включати:
- Процентилі латентності (p50/p95/p99), розділені на час апстріму і час краю.
- Рівні помилок за кодами статусу і по апстрімах.
- Стани з’єднань (active, reading, writing, waiting/keepalive).
- Тиск на ресурси: CPU steal, пам’ять, диск IO latency, мережеві дропи/ретрансмісії.
- Події деплою/reload, скорельовані зі спайками помилок.
Хитрість: логувати те, що знадобиться, до того, як воно знадобиться. Додайте request ID і поля timing апстріму зараз.
Під час інциденту у вас не буде часу домовлятися з вашим минулим «я».
Практичні завдання: команди, вивід і рішення (12+)
Це завдання, які ви можете виконати на реальній Linux-машині. Кожне включає: команду, що означає вивід і яке рішення з нього випливає.
Використовуйте їх як виробничий ритуал, а не одноразовий туторіал.
1) Визначте, який сервер реально відповідає на трафік
cr0x@server:~$ sudo ss -ltnp | egrep ':(80|443)\s'
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=1294,fd=6))
LISTEN 0 511 0.0.0.0:443 0.0.0.0:* users:(("nginx",pid=1294,fd=7))
Значення: Nginx володіє портами 80/443 на цьому хості. Якщо ви очікували Apache, у вас архітектурна невідповідність або застарілий рукопис.
Рішення: Спрямовуйте тюнінг і логи на процес, що реально на краю. Також перевірте, чи Apache тільки upstream (наприклад, на 127.0.0.1:8080).
2) Підтвердьте синтаксичну коректність конфігу Nginx перед reload
cr0x@server:~$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Значення: Ви не зламали сервіс синтаксично при перезавантаженні.
Рішення: Продовжуйте до reload; якщо воно не вдасться, обробляйте це як інцидент управління змінами, а не як «операційна обережність».
3) Перевірте конфіг Apache і завантажені модулі
cr0x@server:~$ sudo apachectl -t -D DUMP_MODULES | head
Loaded Modules:
core_module (static)
so_module (static)
http_module (static)
mpm_event_module (shared)
proxy_module (shared)
proxy_fcgi_module (shared)
Значення: Apache використовує mpm_event і має proxy-модулі. Це натякає, що Apache використовується як зворотний проксі або фронт-енд додатка, а не обов’язково mod_php.
Рішення: Якщо ви бачите mpm_prefork і великий трафік, негайно дослідіть пам’ять і ліміти конкуренції.
4) Перевірте MPM Apache в runtime (модель конкурентності, за яку ви платите)
cr0x@server:~$ sudo apachectl -V | egrep 'Server MPM|MPM_NAME|MPM_DIR'
Server MPM: event
MPM_NAME: event
MPM_DIR: server/mpm/event
Значення: Ви на event MPM, зазвичай сучасний вибір для ефективності keep-alive.
Рішення: Налаштуйте ліміти потоків/процесів відповідно; не застосовуйте префорк-ерський фольклор «MaxClients».
5) Перевірте тиск на з’єднання в реальному часі (чи нас топить повільні клієнти?)
cr0x@server:~$ sudo ss -s
Total: 2234 (kernel 0)
TCP: 1947 (estab 812, closed 1001, orphaned 0, timewait 1001)
Transport Total IP IPv6
RAW 0 0 0
UDP 12 9 3
TCP 946 781 165
INET 958 790 168
FRAG 0 0 0
Значення: Високі TIME-WAIT можуть бути нормою, але тривале велике число встановлених з’єднань може свідчити про повільних клієнтів, надто лояльні keepalive або апстрім з високою затримкою.
Рішення: Якщо встановлені з’єднання ростуть разом з латентністю, дослідіть keepalive-налаштування і насичення апстріму; розгляньте увімкнення/регулювання буферизації та жорсткіших таймаутів.
6) Помітіть вичерпання дескрипторів файлів до загадкового відключення
cr0x@server:~$ sudo cat /proc/$(pidof nginx | awk '{print $1}')/limits | egrep 'Max open files'
Max open files 1024 1024 files
Значення: 1024 відкритих файлів — замало для завантаженого edge-проксі. Ви вдаритеся об це через сокети й логи під навантаженням.
Рішення: Підніміть ліміти через systemd overrides і worker_rlimit_nofile (Nginx) / відповідні сервісні ліміти для Apache.
7) Перевірте backlog прослуховування і симптоми SYN-тиску
cr0x@server:~$ sudo netstat -s | egrep -i 'listen|overflow|drop' | head
104 times the listen queue of a socket overflowed
104 SYNs to LISTEN sockets dropped
Значення: Черга accept переповнилася; клієнти можуть бачити відмови з’єднання або ретраї. Це часто поєднання навантаження + занадто малого backlog + повільного accept через тиск на CPU.
Рішення: Збільшіть somaxconn, перевірте Nginx listen ... backlog= де застосовано, і зменшіть латентність апстріму, щоб воркери швидше повернулися до accept.
8) Підтвердьте коефіцієнти ядра і ліміти файлів (системні guardrails)
cr0x@server:~$ sysctl net.core.somaxconn fs.file-max
net.core.somaxconn = 128
fs.file-max = 9223372036854775807
Значення: somaxconn=128 — консервативно для edge-сервера; це може сприяти втраченим SYN під вибуховим трафіком.
Рішення: Підніміть net.core.somaxconn (і вирівняйте з listen backlog); валідуйте через навантажувальні тести; не копіюйте величезні значення без потреби.
9) Підтвердьте, які версії HTTP узгоджуються (і чи клієнти застрягли на 1.1)
cr0x@server:~$ curl -skI --http2 https://localhost/ | head -n 5
HTTP/2 200
server: nginx
date: Tue, 04 Feb 2026 12:03:11 GMT
content-type: text/html
Значення: HTTP/2 працює локально; це не доводить, що він працює з Інтернету (існують middlebox), але дає базовий рівень.
Рішення: Якщо клієнти масово узгоджують HTTP/1.1, перевірте ALPN/TLS конфіг, можливості CDN/LB і чи випадково ви не вимкнули HTTP/2 у відповідному vhost.
10) Швидко перевірте сертифікат TLS і дату закінчення
cr0x@server:~$ echo | openssl s_client -servername example.com -connect 127.0.0.1:443 2>/dev/null | openssl x509 -noout -dates -subject
notBefore=Jan 10 00:00:00 2026 GMT
notAfter=Apr 10 00:00:00 2026 GMT
subject=CN = example.com
Значення: Сертифікат валідний зараз і закінчується 10 квітня. У вас є календар, але продакшен потребує автоматизації й алертів.
Рішення: Якщо закінчення близько — пріоритезуйте пайплайн відновлення; не плануйте геройські операції.
11) З’ясуйте, чи ви завантажені по CPU, IO або щось інше блокує
cr0x@server:~$ sudo pidstat -p $(pidof nginx | tr ' ' ',') 1 3
Linux 6.8.0 (server) 02/04/2026 _x86_64_ (8 CPU)
12:03:40 PM UID PID %usr %system %CPU CPU Command
12:03:41 PM 0 1294 18.00 6.00 24.00 2 nginx
12:03:41 PM 0 1295 21.00 7.00 28.00 3 nginx
12:03:41 PM 0 1296 20.00 6.00 26.00 4 nginx
Значення: Воркери Nginx споживають CPU, але не завантажують хост повністю. Якщо латентність висока — можливо, чекати треба апстріму, мережі або диска, а не чистої CPU-сатурації.
Рішення: Якщо CPU завантажений, зменшіть важку роботу на краю (регекси, Lua, рівень компресії), винесіть статичні файли і переконайтеся, що ви не виконуєте динамічну роботу у веб-шарі.
12) Виміряйте латентність диска, що перетворює «швидкий веб-сервер» на «повільний»
cr0x@server:~$ iostat -xz 1 2
Linux 6.8.0 (server) 02/04/2026 _x86_64_ (8 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
22.10 0.00 7.20 9.80 0.00 60.90
Device r/s rkB/s rrqm/s %rrqm r_await rareq-sz w/s wkB/s w_await wareq-sz aqu-sz %util
nvme0n1 210.0 8420.0 10.0 4.5 8.20 40.1 95.0 6120.0 18.40 64.4 2.10 92.0
Значення: Високе %util і підвищений w_await вказують на тиск диска. Статичні файли, тимчасові буфери й логи можуть усі це спричиняти.
Рішення: Перемістіть тимчасову буферизацію на швидший носій, зменшіть буферизацію відповідей на диск там, де доречно, відрегулюйте обсяг логів і перевірте здоров’я файлової системи та стореджу.
13) Перевірте насичення апстріму для PHP-FPM (мовчазна фабрика 504)
cr0x@server:~$ sudo ss -ltnp | grep php-fpm
LISTEN 0 128 127.0.0.1:9000 0.0.0.0:* users:(("php-fpm8.2",pid=2201,fd=9))
Значення: PHP-FPM слухає TCP 9000. Тепер перевірте, чи він є вузьким місцем через статус або логи.
Рішення: Якщо Nginx показує таймаути по апстріму, налаштуйте пул FPM (pm.max_children, таймаути) і виправляйте повільні запити замість нарощування кількості веб-воркерів.
14) Перевірте поля access log Nginx для timing апстріму (дебагуйте по фактах)
cr0x@server:~$ sudo tail -n 3 /var/log/nginx/access.log
203.0.113.10 - - [04/Feb/2026:12:03:51 +0000] "GET /api/cart HTTP/2.0" 200 512 "-" "Mozilla/5.0" rt=0.245 uct=0.002 uht=0.240 urt=0.241
203.0.113.11 - - [04/Feb/2026:12:03:52 +0000] "POST /upload HTTP/2.0" 413 166 "-" "curl/8.5.0" rt=0.003 uct=- uht=- urt=-
203.0.113.12 - - [04/Feb/2026:12:03:52 +0000] "GET /static/app.js HTTP/2.0" 200 183211 "https://example.com/" "Mozilla/5.0" rt=0.012 uct=- uht=- urt=-
Значення: rt (request time) і поля timing апстріму показують, де витрачено час. Для /api/cart майже весь час — апстрім.
Рішення: Не тюніть Nginx під проблему затримки апстріму. Ідіть до додатка/БД. Для 413 — свідомо відрегулюйте client_max_body_size (і застосуйте продуктово).
15) Підтвердіть, що Apache не виконує перехідні перевірки файлової системи на кожен запит через AllowOverride
cr0x@server:~$ sudo apachectl -t -D DUMP_VHOSTS | head -n 12
VirtualHost configuration:
*:80 is a NameVirtualHost
default server example.com (/etc/apache2/sites-enabled/000-default.conf:1)
port 80 namevhost example.com (/etc/apache2/sites-enabled/000-default.conf:1)
Значення: Виявлено розташування vhost-конфіг. Вам все ще потрібно інспектувати наявність AllowOverride у відповідних директоріях.
Рішення: Якщо ви знайдете AllowOverride All на шляхах з великим трафіком, розгляньте переміщення правил у центральний конфіг і встановіть AllowOverride None для продуктивності та управління.
Плейбук для швидкої діагностики
Коли сайт «повільний», не починайте з редагування конфігу. Почніть з локалізації вузького місця з мінімальною церемонією. Ось порядок, який виграє інциденти.
Спочатку: край чи апстрім?
- Перевірте латентність краю проти апстріму за логами (поля timing у Nginx або Apache %D/%{…}).
- Перевірте мікс кодів: спайки 499/504/502 кричать про проблеми проксі/апстріму, а не «веб-сервер повільний».
- Перевірте кількість з’єднань: багато встановлених з’єднань при стабільному RPS часто означає повільні клієнти або невірно налаштовані keepalive.
По-друге: чи є голод ресурсів на хості?
- CPU: високий %system може означати навантаження TLS/компресії або тиск ядра/мережі.
- Пам’ять: свапінг на веб-шарі — самостійний DoS. Якщо бачите активність свапу — тріть як P1 неправильну конфігурацію.
- Дисковий IO latency: високі await-часи можуть затримувати роздачу статичних файлів і буферизацію проксі.
По-третє: чи мережа вас обманює?
- Ретрансміти і дропи: втрата пакетів перетворює HTTP/2 на «одне з’єднання, що страждає».
- Переповнення backlog: втрачені SYN виглядають як випадкові клієнтські відмови.
- MTU/PMTUD дивності: особливо з VPN, корпоративними мережами та UDP/QUIC.
По-четверте: тільки потім торкайтеся конфігу
Коли ви ідентифікували, куди йде час, налагодьте компонент, який відповідальний за цей час. Якщо апстрім повільний — не «масштабуйте Nginx».
Це шлях до дорогого інциденту з кращими графіками.
Поширені помилки: симптом → причина → виправлення
1) Симптом: випадкові спайки 502/504 під час деплоїв
Причина: поведінка reload/restart і непроцесне дренування апстрімів; health checks занадто оптимістичні; таймаути не вирівняні.
Виправлення: впровадьте граціозні reload; забезпечте дренування апстрімів; вирівняйте proxy_read_timeout (Nginx) / ProxyTimeout (Apache) з таймаутами додатка; зменшіть blast radius при деплої.
2) Симптом: високе споживання пам’яті, OOM на Apache
Причина: prefork MPM з високою конкуренцією; завантажений mod_php; кожен процес важкий по пам’яті.
Виправлення: перейти на event MPM + PHP-FPM; обмежити воркерів/потоки; вимірювати RSS на воркер; перестати видавати пам’ять за безкоштовну.
3) Симптом: Nginx «працює», але завантаження не вдаються або повільні
Причина: буферизація тіла запиту на диск з повільним сховищем; client_max_body_size занадто мала; таймаути занадто агресивні для великих завантажень.
Виправлення: встановіть ліміти розміру свідомо; розмістіть тимчасові шляхи на швидшому накопичувачі; розгляньте пряму віддачу в object-storage; відрегулюйте client_body_timeout і таймаути апстріму.
4) Симптом: раптове збільшення TIME_WAIT і проблеми з епhemeral портами на апстрімі
Причина: keepalive вимкнено між проксі і апстрімом, що призводить до нових TCP-з’єднань на запит; або апстрім занадто агресивно закриває з’єднання.
Виправлення: увімкніть upstream keepalive pools (Nginx keepalive в upstream); переконайтеся, що сервер додатка це підтримує; тонко налаштуйте keepalive таймаути.
5) Симптом: «швидко локально, повільно для деяких користувачів» після ввімкнення HTTP/3
Причина: UDP блокується або обмежується в деяких мережах; поведінка fallback не протестована; сліпі місця в спостережуваності.
Виправлення: робіть поступовий rollout; забезпечте гарний fallback на HTTP/2; моніторьте per-protocol error rates і помилки handshake.
6) Симптом: CPU Apache спайки після «малих змін конфігу»
Причина: увімкнення складних rewrite-правил по директоріях; AllowOverride спричиняє файлові перевірки; regex-важкі перезаписи виконуються на кожен запит.
Виправлення: мігруйте правила в централізований конфіг; встановіть AllowOverride None де можливо; спростіть логіку rewrite; кешуйте статичні маршрути на краю.
7) Симптом: Nginx іноді віддає застарілий або неправильний контент
Причина: proxy caching налаштований без коректних cache key; пропущено обробку Vary; кешуються автентифіковані відповіді.
Виправлення: явно визначіть cache key; обходьте кеш при auth/cookies; перевірте cache-control заголовки; запустіть канарські перевірки для автентифікованих сторінок.
8) Симптом: клієнти бачать «connection reset» під навантаженням, логи виглядають чистими
Причина: переповнення backlog ядра, тиск conntrack або апстрімні reset-и; логи веб-сервера часто не захоплюють випадки, коли ядро відкидає SYNs.
Виправлення: перевірте статистику переповнення listen queue; підніміть backlog-налаштування; забезпечте запас CPU; перевірте фаєрвол/conntrack, якщо релевантно.
Три корпоративні історії з фронту
Міні-історія №1: Інцидент через хибне припущення
Середньостатистична SaaS-компанія мігрувала з одного Apache-сервера до «сучасного стеку». Вони поставили Nginx спереду, залишили
шар додатка майже без змін і оголосили перемогу після навантажувального тесту, який торкнувся лише головної сторінки. Припущення:
«Nginx краще витримає конкуренцію, тож додаток буде ок».
Через два тижні маркетингова кампанія принесла зміни в поведінку користувачів: більше завантажень, довші сесії і багато повільних мобільних клієнтів.
Nginx виконав свою роботу — він тримав з’єднання відкритими, ввічливо буферизував і пересилав запити. Але шар додатка був розрахований як у 2014:
пули PHP-FPM замалі, повільні запити без обмежень і іноді секунди на запити до бази.
Видимим симптомом стали 504 на краю. Команда звинуватила Nginx, бо він був новим. Вони підняли воркери, ліміти файлів і налаштували keepalive.
504 стали ще гіршими, бо проксі став краще годувати апстрім.
Виправлення було чесно базовим: додати timing апстріму в логи, капнути час запиту, тюнити PHP-FPM дітей на основі вимірюваної пам’яті на воркер
і додати circuit-breaking для повільних endpoint-ів. Nginx не був проблемою; проблемою було припущення, що «продуктивність краю = продуктивність системи».
Міні-історія №2: Оптимізація, що відпалила назад
Внутрішня платформа ентерпрайзу вирішила «стандартизувати», перевівши все на HTTP/2 скрізь і ввімкнувши агресивну компресію на краю.
Мета була благородна: менше з’єднань, швидші завантаження, менше трафіку. Вони розгорнули це після тестів, що показали зниження медіани латентності.
Потім вдарив slow tail. Підмножина користувачів на ненадійних VPN почала бачити зависання запитів. Не прямі відмови — а зависання. p99 різко виріс.
Підтримка отримувала скарги на «крутиться» і «іноді само проходить». Спостережуваність спочатку не допомагала, бо дашборди фокусувалися на середньому.
Причина: з мультиплексуванням HTTP/2 одне ненадійне з’єднання могло деградувати кілька одночасних запитів. У поєднанні з високим CPU для компресії
це створило ідеальний шторм: воркери витрачали більше часу на стиснення і менше — на прийом/обслуговування, а клієнти ретраїли, що посилювало навантаження.
Це не була помилка HTTP/2; це була взаємодія умов мережі, CPU headroom і конфігурації.
Виправлення не полягало в глобальному вимкненні HTTP/2. Вони знизили рівень компресії, виключили вже стиснуті типи, додали запасу потужності і
інструментували latency по протоколам. Урок — оптимізації, що покращують медіану, можуть нашкодити хвосту, а хвіст — це те, що вас викличе.
Міні-історія №3: Нудна, але правильна практика, що врятувала день
Команда фінпослуг тримала змішаний парк: Nginx на краю, Apache позаду для застарілого додатка й декілька нових сервісів. Нічого гламурного.
Але у них було правило: кожна зміна конфігу має пройти синтаксичний тест, деплоїтися через однаковий пайплайн і мати автоматичний шлях відкату.
Вони також стандартизували формат логів, включивши request ID і timings апстріму скрізь.
Одного пополудня оновлення сертифіката пройшло не так — не тому, що TLS складний, а тому що невеликий рефактор конфігу змінив шлях сертифіката в одному середовищі.
Край почав віддавати старий сертифікат на підмножині хостів. Деякі клієнти падали сильно, інші ретраїли, і служба підтримки загорілася.
Ось нудна частина, що їх врятувала: у них був алерт на термін придатності/коректність сертифіката і канаркова перевірка, що валідовувала subject і expiry
з різних мереж. Проблему помітили швидко. Кореляція логів по request ID також довела, що латентність додатка не причетна, тож інцидент залишився в межах.
Вони відкотилися за хвилини. Постмортем був майже розчаровуючим: ніяких героїв, ніякої таємниці. Просто контрольовані зміни, швидке виявлення і пайплайн,
що не вимагає від людини пам’ятати дванадцять кроків під стресом.
Чеклісти / покроковий план
Чекліст A: вибір Nginx, Apache або обох
- Визначте контракт краю: точка термінації TLS, максимальний розмір тіла, таймаути і які заголовки ви довіряєте.
- Рішення щодо перевизначень по директоріях. Якщо так — Apache може бути виправданий; якщо ні — надавайте перевагу централізованому конфігу (часто Nginx).
- Оберіть модель виконання додатка: PHP-FPM або сервер додатка за проксі. Уникайте зв’язування моделі веб-воркера з рантаймом додатка, якщо немає вагомих причин.
- Задокументуйте поведінку при відмові: що відбувається, коли апстрім повільний? Черга? Відхилення? Видача застарілого контенту? Це має бути явно.
- Виберіть базову спостережуваність: лог-поля, метрики, дашборди і алерти, що відповідають контракту.
Чекліст B: продакшн-хардінг для будь-якого сервера
- Встановіть ліміти дескрипторів файлів (сервісні і системні). Перевіряйте через
/proc/<pid>/limits. - Валідуйте конфіг в CI використовуючи
nginx -tабоapachectl -tперед деплоєм. - Стандартизуйте формати логів і включіть timing апстріму та request ID.
- Вирівняйте таймаути між краєм, апстрімом і додатком.
- Встановіть розумні keepalive між клієнтами і краєм, а також між краєм і апстрімом.
- Сплануйте стратегію reload і протестуйте її в робочий час на канарковому хості.
- Захистіть апстрім буферизацією/лімітами, щоб повільні клієнти не тримали ресурси додатка.
Чекліст C: план міграції (Apache → Nginx edge) без драми
- Інвентар rewrite-правил, механізмів аутентифікації і будь-яких Apache-only модулів, від яких ви залежите.
- Почніть з pass-through проксі (Nginx спереду, мінімальна логіка). Спочатку доведіть коректність.
- Перенесіть статичні ресурси і кешування на Nginx наступним кроком. Спостерігайте IO і cache headers.
- Міґруйте rewrites обережно. Паралельність regex — пастка; тестуйте на реальних зразках запитів.
- Розгортайте за відсотком (ваги LB) або за доменом/хостом. Тримайте відкат дешевим.
- Після стабільної роботи, вирішіть, чи лишається Apache як апстрім, чи його виводять з експлуатації.
FAQ
1) Що швидше: Nginx чи Apache?
Для більшості реальних стеків «швидше» домінує час додатка і бази даних. Nginx часто обробляє вищу конкуренцію з меншими ресурсами на краю,
але Apache з event MPM теж може бути відмінним. Обирайте за операційною моделлю і режимами відмов.
2) Чи варто запускати і Nginx, і Apache?
Часто — так: Nginx на краю, Apache позаду для застарілих додатків. Але не робіть цього випадково. Чітко вказуйте, хто володіє TLS, буферизацією і таймаутами.
3) .htaccess завжди поганий?
Не завжди — .htaccess є прагматичним інструментом для делегованого контролю. Він «поганий», коли вам потрібний централізований контроль змін,
узгоджена поведінка і відтворювані деплоя.
4) Який MPM варто використовувати у 2026?
Надавайте перевагу event для більшості сучасних налаштувань. Використовуйте prefork лише коли змушують не потокобезпечні модулі або застарілі вимоги, і тоді бюджетуйте пам’ять відповідно.
5) Чому я бачу 499 у логах Nginx?
499 означає, що клієнт закрив з’єднання до того, як Nginx встиг відповісти. Типові причини: таймаути клієнта, повільні апстріми, мобільні мережі або занадто агресивні таймаути на краю.
6) Яка найпоширеніша причина 504 Gateway Timeout?
Повільність або насичення апстріму: вичерпані ниті/воркери додатка, повільні запити, залежності з високою латентністю. Виправляйте спочатку апстрім-ємність і латентність;
потім вирівнюйте проксі-таймаути.
7) Чи варто вмикати HTTP/3 скрізь?
Вмикайте, коли можете виміряти ефект. Розгортайте поступово, забезпечте чистий fallback і слідкуйте за latency і error rates по протоколу. Деякі мережі трактують UDP підозріло.
8) Чи кращий Nginx для Kubernetes і мікросервісів?
Nginx часто використовується, але в кластерах вибір ingress/LB може мати більший вплив, ніж локальний веб-сервер. Принципи ті самі:
буферизація, таймаути, спостережуваність і контроль змін.
9) Чи може Apache так само добре робити reverse proxy?
Так, Apache може ефективно робити reverse proxy, особливо з event MPM і потрібними proxy-модулями. Операційна ергономіка зазвичай відрізняється:
конфіги Nginx частіше стандартизовані для ролей краю.
10) Який найпростіший безпечний дефолт для PHP-додатка?
Nginx на краю + PHP-FPM для виконання, з явними таймаутами, лімітами розміру запиту, upstream keepalive де доцільно і timing апстріму в логах.
Наступні кроки, які ви можете зробити цього тижня
- Визначте межу: хто завершує TLS, хто буферизує, хто ставить таймаути і де дозволені перевизначення по орендарю.
- Інструментуйте timing апстріму в логах, щоб відповісти «край чи додаток?» за 30 секунд.
- Запустіть практичні завдання вище на одному прод-хості і запишіть, що вас здивувало. Це здивування — місце, де живе ваш наступний інцидент.
- Вирівняйте таймаути між проксі і додатком. Усуньте невідповідності, що породжують фейкові 504 або зависання з’єднань.
- Вбивайте дрейф конфігів: забезпечте тести конфігів у CI, стандартизуйте процедури reload і припиніть дозволяти ad-hoc правки стати «нашими звичками».
Якщо ви хочете реальну відповідь 2026 року: оберіть сервер, який робить вашу систему більш спостережуваною, ваші зміни — контрольованими,
а режими відмов — передбачуваними. Усе інше — інтернет-аргументи.