
Чому WordPress гальмує навіть на швидкому хостингу: де шукати реальне вузьке місце
Потужний сервер не гарантує швидкий WordPress. NVMe, запас оперативної пам’яті та кілька швидких ядер допомагають лише тоді, коли сайт справді впирається саме в ці ресурси. Якщо PHP чекає сторонній API, база виконує невдалий запит, плагін запускає важку операцію на кожному відкритті сторінки або черга PHP workers уже заповнена, апгрейд сервера може майже нічого не змінити.
Тут легко піти хибним шляхом і відразу почати міняти тариф. Корисніше спочатку знайти, де саме губиться час. У WordPress це зазвичай один із кількох шарів: мережа, генерація HTML у PHP, база даних, плагіни, зовнішні запити, cron/AJAX, кеш або самі серверні ресурси. Діагностика працює краще, коли кожна гіпотеза перевіряється вимірюванням.
Швидкий сервер є, а сторінка все одно відкривається повільно: з чого почати діагностику
Якщо WordPress повільний на потужному сервері, спочатку треба виміряти не «швидкість хостингу», а час до першого байта та загальний час відповіді. Це швидко показує, чи затримка виникає ще до отримання HTML, чи браузер уже довго завантажує CSS, JavaScript, шрифти та зображення.
Для базової перевірки достатньо DevTools у браузері або звичайного curl. У вкладці Network дивляться насамперед на Waiting або Server Response. З командного рядка можна порівняти час до першого байта і повний час запиту:
1 curl -o /dev/null -s -w "TTFB: %{time_starttransfer}\nTotal: %{time_total}\n" https://example.com/
Коли time_starttransfer займає більшу частину всього запиту, проблема, найімовірніше, знаходиться до браузера: у PHP, SQL, зовнішньому HTTP-запиті, черзі PHP-FPM або серверному оточенні. Якщо HTML приходить швидко, а сторінка ще кілька секунд «домальовується», дивитися треба вже на фронтенд і мережевий waterfall.
Корисно перевіряти різні сценарії. Головна сторінка для гостя може бути миттєвою, а wp-admin — повільним. Інколи гальмує лише каталог WooCommerce, пошук або сторінка після входу. Це підказка: однакова повільність багатьох URL частіше вказує на системний шар, а проблеми окремої групи сторінок — на конкретну логіку WordPress.
PageSpeed Insights або Lighthouse тут доречні як додаткові інструменти. Вони добре показують клієнтські проблеми, але не скажуть, який PHP-hook або SQL-запит забрав 800 мс. Спочатку треба зрозуміти, де саме губиться час, а вже потім щось масштабувати.
PHP може чекати довше, ніж реально працювати
Низьке завантаження CPU не означає, що PHP-запит виконується швидко. PHP-процес може більшу частину wall-clock time не рахувати код, а чекати базу даних, DNS, файлову систему, блокування або відповідь іншого сервісу. У моніторингу сервер при цьому виглядає майже вільним.
Типовий приклад — плагін робить синхронний HTTP-запит до зовнішнього API. Сам PHP витрачає мало процесорного часу, але сторінка не може завершити генерацію, доки не прийде відповідь. Те саме відбувається з повільним SQL або файловою операцією. Простою мовою: PHP у цей момент не рахує — він стоїть і чекає.
Шукати такі затримки зручно через Query Monitor, APM на кшталт New Relic, PHP slow log або статус PHP-FPM. Профайлер допоможе побачити функції та виклики, де накопичується час. У PHP-FPM також варто перевірити чергу: навіть швидкий окремий запит чекатиме, якщо всі PHP-процеси зайняті.
Не слід плутати це з нестачею ядер. Якщо CPU стабільно вільний, а один і той самий динамічний URL відповідає повільно навіть без навантаження, додатковий процесор навряд чи буде першим правильним кроком. Спочатку треба знайти операцію, на якій PHP фактично простоює.
Заодно варто перевірити OPcache. Він не виправить повільний SQL або зовнішній API, але без нього PHP частіше компілює скрипти заново. Це окремий шар оптимізації, а не універсальна відповідь на будь-яку повільність WordPress.
База даних: проблема не в кількості запитів, а в тому, які саме запити виконує WordPress
Кількість SQL-запитів у WordPress менш важлива, ніж їхній сумарний час і наявність окремих повільних запитів. Дві сотні коротких SELECT можуть виконатися швидше, ніж один невдалий meta_query, який змушує MySQL переглядати великий обсяг даних.
Багато запитів не завжди означає повільну базу
Query Monitor показує не тільки query count, а й тривалість, джерело виклику та дублікати. Саме total query time дає першу відповідь. Якщо SQL займає лише невелику частину TTFB, немає сенсу починати «оптимізацію бази» тільки через кілька сотень звернень.
І навпаки, один запит на сотні мілісекунд уже заслуговує уваги. Часті причини — невдалий WP_Query, складні умови по wp_postmeta, великі вибірки WooCommerce, відсутній потрібний індекс або плагін, що повторює важку операцію під час кожного завантаження сторінки.
Коли варто дивитися EXPLAIN та індекси
Якщо знайдено конкретний повільний SELECT, наступний крок — EXPLAIN. Він допомагає зрозуміти, як MySQL читає таблиці, які індекси використовує і чи не робить зайвий full scan. Для складних сайтів корисний також slow query log MySQL/MariaDB: він фіксує запити, що реально виходять за заданий поріг часу.
Окремої перевірки заслуговує wp_options і autoload. Коли плагіни роками накопичують автоматично завантажувані опції, ці дані підтягуються на великій кількості запитів WordPress. Проблема тут не в самій таблиці, а в тому, який обсяг інформації доводиться читати постійно.
Симптом | Що перевірити | Ймовірний напрямок |
|---|---|---|
Сотні запитів, але малий total query time | Загальний SQL time | База, ймовірно, не головне вузьке місце |
Один SQL займає значну частину TTFB | Query Monitor, slow query log | Запит, індекс або плагін |
Великий autoload у wp_options | Обсяг autoload | Застарілі або надмірні опції плагінів |
Повільний каталог WooCommerce | meta_query, wp_postmeta | Структура запиту та обсяг даних |
Лічильник запитів сам по собі ще нічого не доводить. Оптимізувати треба конкретний повільний SQL або його джерело, а не абстрактно «зменшувати кількість запитів».
Плагін може гальмувати сайт навіть тоді, коли його функція на цій сторінці не використовується
Плагін WordPress може виконувати код на кожному запиті через глобальні hooks, навіть якщо його видима функція потрібна лише на кількох сторінках. Один невдалий hook іноді коштує більше часу, ніж десяток простих плагінів, тому рахувати лише кількість розширень мало корисно.
Так поводяться не лише очевидно важкі компоненти. Плагіни безпеки, статистики, резервного копіювання, SEO, інтеграції з CRM, розширення WooCommerce і конструктори сторінок можуть підключатися до загальних подій WordPress. У wp-admin окрема проблема — важкі admin hooks, що запускаються при відкритті списку записів, замовлень або налаштувань.
Надійний спосіб перевірки — staging-копія та поетапне відключення підозрілих компонентів із повторним вимірюванням TTFB і часу виконання PHP. На бойовому сайті без плану так робити ризиковано: можна зачепити checkout, авторизацію або інтеграцію й отримати хибний висновок через прогрітий кеш.
Query Monitor і APM тут особливо корисні, бо показують джерело виклику. Якщо після відключення одного плагіна час генерації сторінки різко зменшився, варто зрозуміти, що саме він робив: запускав важкий SQL, звертався до API, читав великий файл чи створював багато об’єктів.
На практиці проблема часто не у кількості встановлених плагінів, а в одному компоненті, який виконує важку операцію на кожному запиті. Шукати треба не список плагінів, а того, хто «з’їдає» час запиту.
Зовнішні API, шрифти та сервіси: коли WordPress залежить від чужого сервера
Повільний зовнішній API здатний збільшити TTFB WordPress навіть тоді, коли сам сервер майже не навантажений. Так буває, коли плагін під час генерації сторінки виконує wp_remote_get() або wp_remote_post() до CRM, платіжного шлюзу, ліцензійного сервера, антиспам-системи чи іншого зовнішнього сервісу.
Серверні HTTP-запити
Тут є проста підказка: затримка виникає ще до отримання HTML. У Query Monitor варто відкрити HTTP API Calls і подивитися URL, кількість звернень та їхню тривалість. Якщо один зовнішній виклик стабільно займає значну частину TTFB, його треба кешувати, переносити у фонове виконання або прибирати з критичного шляху генерації сторінки.
Такі проблеми можуть бути нестабільними. Сайт працює нормально, поки сторонній сервіс відповідає за 100–200 мс, і раптом починає «підвисати», коли той самий endpoint відповідає кілька секунд. Ваш сервер може бути швидким, але він не може прискорити API, на яке чекає PHP.
Сторонні ресурси у браузері
Google Fonts, analytics, chat widgets, рекламні скрипти та сторонній JavaScript теж можуть сповільнювати сторінку, але це інший рівень. Вони часто не збільшують серверний TTFB, зате затримують рендеринг або завантаження після отримання HTML. Тут дивляться Network waterfall у DevTools, а не PHP slow log.
Ці два випадки краще не змішувати. Спочатку визначте, чи WordPress чекає зовнішню відповідь на сервері, чи вже браузер чекає сторонній ресурс. Інакше легко витратити час на оптимізацію не того шару.
WP-Cron, admin-ajax.php і Heartbeat: фонові операції, які раптом стають не фоновими
Періодичні гальмування WordPress часто створює не основний page request, а cron, AJAX або Action Scheduler, що запускаються паралельно. Через це проблема виглядає випадковою: десять відкриттів проходять швидко, а одинадцяте потрапляє на важку фонову операцію.
WP-Cron
WP-Cron — це pseudo-cron. За типової конфігурації WordPress перевіряє заплановані події під час звичайних відвідувань. Якщо накопичилися задачі резервного копіювання, імпорту, синхронізації або розсилки, черговий запит користувача може збігтися з їхнім запуском.
Перевірити події можна через WP Crontrol або команду wp cron event list. Для WooCommerce окремо варто дивитися Action Scheduler: великий backlog запланованих дій здатний створювати хвилі навантаження.
Рішення не в тому, щоб бездумно вимкнути WP-Cron. Якщо сайт має стабільний системний cron, псевдокрон можна перенести на керований запуск за розкладом, але спочатку треба зрозуміти, які саме задачі створюють затримку.
admin-ajax.php та Heartbeat
admin-ajax.php використовується багатьма плагінами та самим WordPress для фонових дій. Heartbeat регулярно звертається до сервера в адмінці, а деякі плагіни запускають власні AJAX-запити ще частіше. Якщо одна така дія важка, кілька відкритих вкладок можуть помітно навантажити PHP-FPM.
У такій ситуації варто звірити час уповільнення з access log, PHP-FPM log і Network у браузері. Якщо в ті самі секунди повторюються wp-cron.php, admin-ajax.php або scheduled actions, з’являється конкретний напрямок для подальшої діагностики.
Кеш маскує проблему, але не завжди її вирішує
Швидка кешована сторінка не доводить, що динамічна частина WordPress працює добре. Full-page cache часто взагалі обходить більшу частину PHP-логіки, тому головна сторінка для гостя може відкриватися миттєво, а wp-admin, кошик, checkout або особистий кабінет — залишатися повільними.
Page cache
Page cache зберігає готовий HTML. Якщо відповідь віддається як cache HIT, WordPress може не виконувати звичайний набір PHP-функцій і SQL-запитів. Для діагностики треба порівнювати cached і uncached request: перший запит, повторний запит, авторизованого користувача та URL, який свідомо проходить повз кеш.
Корисно перевіряти response headers, де кешувальний шар часто позначає HIT, MISS або BYPASS. Якщо HIT швидкий, а MISS повільний, проблема не зникла — її просто сховав кеш.
Object cache та Redis
Object cache працює інакше: він зберігає результати об’єктів та окремих звернень, а не готову сторінку. Redis може суттєво допомогти сайтам із повторюваними дорогими операціями, але не є універсальним прискорювачем. Якщо WordPress чекає зовнішній API або виконує невдалий SQL, Redis не гарантує помітного ефекту.
OPcache — ще один рівень: він кешує скомпільований PHP-код і зменшує витрати на повторну компіляцію скриптів. Тому page cache, object cache і OPcache вирішують різні задачі.
Кеш може сховати повільний PHP, але не зробити його швидшим. Якщо мета — знайти реальне вузьке місце, залишайте хоча б один контрольований uncached-сценарій для перевірки.
Коли справді винен хостинг: як відрізнити дефіцит ресурсів від проблеми самого WordPress
Збільшення ресурсів хостингу має сенс лише тоді, коли моніторинг показує, що WordPress реально впирається у CPU, RAM, I/O або чергу PHP workers. Повільний TTFB сам по собі не доводить, що серверу бракує потужності.
Коли бракує CPU або RAM
Якщо під навантаженням CPU стабільно близький до межі, load average росте, а разом із ним збільшується час відповіді, тут уже справді може бракувати CPU. Якщо система активно використовує swap, варто перевірити RAM: робота зі swap може додавати відчутні затримки навіть без повного падіння сервісу.
Високий iowait вказує на іншу проблему: процесор значну частину часу чекає операції вводу-виводу. Тут доречні vmstat, iostat, моніторинг дискової latency та перевірка навантаження на базу даних і файлову систему.
Коли проблема у PHP workers або I/O
Навіть нормальний за тривалістю PHP-запит стане повільним для користувача, якщо йому доводиться чекати в черзі. У PHP-FPM варто дивитися зайняті workers, queue та параметр pm.max_children. Якщо всі процеси постійно зайняті під час піку, збільшення їх кількості може допомогти — але лише якщо сервер має достатньо RAM і CPU.
Після перевірки коду, SQL, cron і плагінів варто оцінити середовище виконання: версію PHP, OPcache, доступні ресурси, кешування, конфігурацію бази та серверні ліміти. Приклад набору параметрів для такого середовища можна подивитися на сайті UkrLine і зіставити їх із уже знайденим вузьким місцем.
Метрика | Що видно | Що це означає |
|---|---|---|
CPU майже постійно зайнятий | Високе CPU usage під навантаженням | Може бракувати CPU або код занадто важкий |
Високий iowait | CPU чекає I/O | Перевірити диск, БД і файлові операції |
Активно використовується swap | Дані витісняються з RAM | Можлива нестача оперативної пам’яті |
Усі PHP workers зайняті | Запити стають у чергу | Перевірити pm.max_children і тривалість PHP-запитів |
Ресурси вільні, але один URL повільний | Немає системного дефіциту | Шукати код, SQL або зовнішню залежність |
На практиці перехід на потужніше середовище допомагає тоді, коли є вимірюваний дефіцит ресурсу. Якщо ж один PHP-запит просто чекає зовнішній API дві секунди, додаткові ядра цього не виправлять. Масштабувати потрібно той ресурс, у який сайт реально впирається.
Де шукати вузьке місце: короткий порядок перевірки
- Виміряти TTFB проблемної сторінки.
- Відокремити серверну затримку від CSS, JavaScript, шрифтів і зображень.
- Перевірити час виконання PHP та наявність черги PHP-FPM.
- Подивитися SQL-запити та їхній сумарний час.
- Перевірити HTTP API Calls.
- Знайти важкі плагіни, hooks або окремі функції.
- Перевірити
wp-cron.php,admin-ajax.phpта Action Scheduler. - Порівняти cached і uncached request.
- Подивитися CPU, RAM, swap, I/O та зайняті PHP workers.
- Змінювати лише той компонент, для якого знайдено вимірювану проблему.
- Повторити ті самі заміри після зміни.
Найгірша стратегія — оптимізувати WordPress навмання: одночасно змінити PHP, поставити Redis, вимкнути кілька плагінів, перенести cron і після цього не знати, що саме допомогло. Набагато надійніше працює схема «симптом → вимірювання → одна зміна → повторний тест».
Не варто починати з апгрейду сервера лише тому, що сайт повільний. Спочатку знайдіть операцію, на якій реально втрачається час. Коли вузьке місце підтверджене метрикою, рішення стає очевиднішим: оптимізувати SQL, прибрати синхронний API-виклик, виправити плагін, розвантажити cron, налаштувати кеш або вже додати той ресурс, якого справді бракує.



