Сильнее всего WordPress ускоряет кеш страниц: на нашем тестовом стенде время до первого байта (TTFB) упало с 41 до 0,3 мс, а сервер стал отдавать не 44, а больше 14 тысяч страниц в секунду. Вторым по эффекту шагом стал OPcache (190 мс без него и 41 мс с ним), третьим поиск тормозящего плагина: его имитация добавила к каждому запросу около 265 мс. Дальше по убыванию влияния идут воркеры PHP-FPM, сжатие, изображения, object cache и только в конце чистка autoload: 3 МБ автозагружаемых опций добавили всего около 4 мс.
Как мы проверяли
Тестовый стенд RichHost, октябрь 2026: изолированный контейнер 2 vCPU / 8 ГБ RAM, Ubuntu 24.04, nginx 1.24, PHP 8.3-FPM, MariaDB 10.11, WordPress 6.7.2, тема Twenty Twenty-Five, 300 сгенерированных записей. Запросы отправлялись с того же сервера (127.0.0.1), поэтому сеть и TLS в цифры не входят. TTFB измеряли как медиану и 90-й перцентиль (p90) из 40 запросов curl после трех прогревочных, пропускную способность через ab (300 запросов по 10 одновременно), тестировали главную страницу и запись. «Тяжелый плагин»: наш mu-плагин, который делает 150 лишних SQL-запросов и 250 мс ждет внешний API. Меняли по одному фактору. Это лабораторные цифры стенда, а не показатели продакшн-серверов RichHost.
Результаты замеров
| Сценарий | TTFB, медиана (главная / запись) | TTFB, p90 | Запросов в секунду |
|---|---|---|---|
| OPcache выключен | 190 / 195 мс | 210 / 216 мс | 9,7 / 9,8 |
| OPcache включен | 41 / 45 мс | 45 / 51 мс | 44,1 / 41,6 |
| OPcache + Redis object cache* | 39,7 / 39,6 мс | 49,4 / 46,2 мс | 47,3 / 48,4 |
| OPcache + кеш страниц nginx | 0,3 / 0,3 мс | 0,4 / 0,3 мс | 21 581 / 14 749 |
| Тяжелый плагин, без кеша страниц | 309 / 311 мс | 325 / 323 мс | 15,3 / 15,0 |
| Тяжелый плагин + Redis object cache | 306 / 306 мс | 319 / 314 мс | 15,3 / 15,4 |
| Тяжелый плагин + кеш страниц | 0,2 / 0,3 мс | 0,3 / 0,3 мс | 18 703 / 15 202 |
| Администратор в системе (кеш в обход) | 44,8 / 45,9 мс | 49,6 / 56,2 мс | 39,8 / 38,8 |
| +3 МБ autoload-опций | 45,4 / 45,4 мс | 59,5 / 59,0 мс | 42,3 / 39,3 |
* Строки с Redis измерены отдельной серией, где базовый вариант без object cache дал 43,7 / 46,8 мс.

Из таблицы следуют два неочевидных вывода. Первый: кеш страниц не лечит медленный плагин, а прячет его от анонимных посетителей. Администратор, покупатель с корзиной WooCommerce или любой посетитель с кукой входа получает страницу в обход кеша, то есть те же 45 мс на чистом сайте и больше 300 мс с тяжелым плагином. Второй: раздутый autoload, который во многих советах стоит первым, на стенде почти не повлиял на скорость. Из чего складывается TTFB и почему работает сжатие, мы разобрали в статье TTFB, кеш и сжатие, здесь только практика.
Шаг 1. Кеш страниц
Без кеша WordPress на каждый запрос запускает PHP, выполняет 22-29 SQL-запросов (столько насчитал счетчик на главной и на странице записи) и собирает HTML заново. Кеш страниц отдает готовый HTML, поэтому TTFB снизился с 41-45 до 0,2-0,3 мс, причем одинаково и для чистого сайта, и для сайта с тяжелым плагином. На реальном сайте добавится сеть, но работа сервера почти исчезает.
На стенде мы проверили такой конфиг nginx fastcgi_cache. Он кеширует только анонимные GET-запросы и пропускает мимо кеша POST, адреса с параметрами, админку, REST API, а также посетителей с кукой входа, комментария или корзины WooCommerce:
fastcgi_cache_path /var/cache/nginx/wp levels=1:2 keys_zone=WPCACHE:64m max_size=1g inactive=60m use_temp_path=off;
server {
# ... listen, server_name, root, index ...
set $skip_cache 0;
if ($request_method = POST) { set $skip_cache 1; }
if ($query_string != "") { set $skip_cache 1; }
if ($request_uri ~* "/wp-admin/|/wp-json/|/xmlrpc.php|wp-.*\.php|/feed/|sitemap(_index)?\.xml") { set $skip_cache 1; }
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_logged_in|woocommerce_items_in_cart|woocommerce_cart_hash") { set $skip_cache 1; }
location / { try_files $uri $uri/ /index.php?$args; }
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_cache WPCACHE;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_valid 200 301 10m;
fastcgi_cache_use_stale error timeout updating http_500 http_503;
fastcgi_cache_background_update on;
fastcgi_cache_lock on;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
add_header X-Cache $upstream_cache_status always;
}
}
Проверка правил (заголовок X-Cache показывает, откуда пришла страница):
$ curl -sI http://127.0.0.1:8081/post-293/ | grep X-Cache
X-Cache: MISS
$ curl -sI http://127.0.0.1:8081/post-293/ | grep X-Cache
X-Cache: HIT
$ curl -sI -b wordpress_logged_in_abc=x http://127.0.0.1:8081/post-293/ | grep X-Cache
X-Cache: BYPASS
$ curl -sI http://127.0.0.1:8081/post-293/?utm_source=x | grep X-Cache
X-Cache: BYPASS
О двух вещах стоит знать заранее. Страница хранится в кеше 10 минут (fastcgi_cache_valid), так что после правки записи анонимные посетители могут видеть старую версию до 10 минут, если не настроить очистку кеша, например плагином Nginx Helper. А fastcgi_cache_use_stale и fastcgi_cache_lock не дают сотням посетителей одновременно запускать PHP, когда запись в кеше устарела. На виртуальном хостинге доступа к nginx обычно нет, поэтому ту же роль выполняет плагин: WP Super Cache, W3 Total Cache или LiteSpeed Cache, если сервер работает на LiteSpeed. Какие еще бывают уровни кеширования, описано в материале про кеш на хостинге.
Шаг 2. OPcache
OPcache держит скомпилированный PHP-код в памяти, чтобы не разбирать тысячи файлов WordPress на каждый запрос. С выключенным OPcache стенд дал TTFB 190-195 мс и 9,7 запроса в секунду, с включенным 41-45 мс и 42-44 запроса, то есть примерно в 4,5 раза быстрее. Именно эту скорость получают все, кого обходит кеш страниц: администраторы, редакторы, покупатели.
Проверяйте OPcache для сайта, а не в терминале: консольный PHP и PHP-FPM могут отличаться. На стенде php -v показывает PHP 8.4, а сайт работает на PHP 8.3-FPM, и для консоли OPcache там выключен. Надежнее создать в корне сайта временный файл со строкой <?php var_dump(opcache_get_status(false)['opcache_enabled'] ?? false);, открыть его в браузере (на стенде он показал bool(true)) и сразу удалить. Стандартных настроек пакета Ubuntu на стенде хватило.
Шаг 3. Найдите плагин, который тормозит
Имитация тяжелого плагина подняла TTFB с 41-45 до 309-311 мс. Найти виновника можно тремя способами.
Query Monitor. Плагин для администратора, который на верхней панели показывает количество и время SQL-запросов с разбивкой по плагинам, а также внешние HTTP-запросы.
wp profile. Команда из пакета wp-cli/profile-command (устанавливается через wp package install wp-cli/profile-command) показывает, на каком этапе загрузки тратится время. Реальный вывод со стенда с включенной имитацией:
$ wp profile stage --url=http://127.0.0.1:8080/post-293/ --fields=stage,time,query_time,query_count
stage time query_time query_count
bootstrap 0.2059s 0.0017s 4
main_query 0.2701s 0.0107s 155
template 0.0751s 0.0062s 20
total (3) 0.5512s 0.0186s 179
$ wp profile stage main_query --spotlight --url=http://127.0.0.1:8080/post-293/ --fields=hook,time,query_time,query_count
hook time query_time query_count
pre_get_posts:before 0.2779s 0.0151s 150
wp 0.2765s 0.0151s 150
Без имитации этап main_query занимал 0,005 с и 5 запросов, с ней 0,27 с и 155, а --spotlight сузил поиск до хука wp. Абсолютные времена здесь выше, чем через браузер, потому что WP-CLI работает без OPcache, но сравнивать этапы это не мешает. Подкоманда wp profile hook, которая называет конкретную функцию, на WP-CLI 2.12 со стенда не запустилась: ей нужна более новая версия WP-CLI.
Медленный лог PHP-FPM. Если есть доступ к настройкам пула, две строки заставят FPM записывать стек вызовов каждого запроса дольше секунды:
; /etc/php/8.3/fpm/pool.d/www.conf
request_slowlog_timeout = 1s
slowlog = /var/log/php8.3-fpm-slow.log
Для проверки мы добавили тестовую функцию, которая 1,5 с «ждет API». Лог сразу показал и функцию, и файл:
[24-Oct-2026 23:45:18] [pool www] pid 17625
script_filename = /var/www/bench/index.php
[0x00007f56fc215510] usleep() /var/www/bench/wp-content/mu-plugins/r1-slowapi.php:3
[0x00007f56fc2154c0] r1_bench_fetch_remote_rates() /var/www/bench/wp-content/mu-plugins/r1-slowapi.php:4
[0x00007f56fc215440] {closure}() /var/www/bench/wp-includes/class-wp-hook.php:324
...
[0x00007f56fc215100] wp() /var/www/bench/wp-blog-header.php:16
Что делать с виновником: обновить, заменить более легким аналогом или попросить разработчика кешировать ответ внешнего API (например, в transient), чтобы сайт не ждал его при каждом открытии страницы.
Шаг 4. Воркеры PHP-FPM
Воркер PHP-FPM обрабатывает один запрос за раз, остальные ждут в очереди. Мы подали 20 одновременных медленных запросов (тяжелый плагин, без кеша) при pm.max_children = 5 и 20.

С 20 воркерами медиана упала с 1272 до 846 мс, а пропускная способность выросла с 14,0 до 18,8 запроса в секунду. Однако p95 почти не изменился (1693 и 1642 мс): ядер процессора осталось два, и воркеры начали за них конкурировать. К тому же каждый воркер на стенде занимал 40-42 МБ памяти, так что 20 воркеров это около 0,8 ГБ только на PHP. Ориентировочное правило: pm.max_children равен памяти, которую можно отдать PHP, деленной на размер одного воркера:
$ ps --no-headers -o rss,cmd -C php-fpm8.3
10644 php-fpm: master process (/etc/php/8.3/fpm/php-fpm.conf)
42888 php-fpm: pool www
41148 php-fpm: pool www
Больше воркеров только сокращают очередь, а не ускоряют код. Другие параметры стека описаны в материале про настройку хостинг-серверов.
Шаг 5. Сжатие gzip
HTML главной страницы стенда весил 56,8 КБ без сжатия и 12,3 КБ с gzip, в 4,6 раза меньше. Подвох в том, что стандартный nginx.conf в Ubuntu включает gzip только для HTML: строка gzip_types там закомментирована. Из-за этого файл стилей блоков ядра WordPress (style.min.css) отдавался несжатым, 114 706 байт. После добавления gzip_types тот же файл весил 15 608 байт:
gzip on;
gzip_comp_level 5;
gzip_min_length 1024;
gzip_vary on;
gzip_proxied any;
gzip_types text/css application/javascript application/json image/svg+xml text/xml application/xml application/rss+xml;
Проверить свой сайт можно, сравнив размер ответа с запросом сжатия и без него:
$ curl -s -o /dev/null -w "%{size_download}\n" http://127.0.0.1:8080/
56776
$ curl -s -o /dev/null -H "Accept-Encoding: gzip" -w "%{size_download}\n" http://127.0.0.1:8080/
12319
Шаг 6. Изображения и CDN
Изображения не влияют на TTFB, но чаще всего именно они составляют основной вес страницы. Мы пропустили два реальных фото в формате PNG через редактор изображений WordPress (GD) с качеством по умолчанию, без изменения размера:
| Фото | PNG | JPEG (качество 82) | WebP (86) | AVIF (82) |
|---|---|---|---|---|
| 741×500 пикселей | 630 КБ | 84,4 КБ | 76,3 КБ | 86,3 КБ |
| 600×400 пикселей | 456 КБ | 50,1 КБ | 49,0 КБ | 52,5 КБ |
Главный выигрыш дает отказ от PNG для фотографий: в 7-9 раз. А вот переход с JPEG на WebP при стандартных настройках WordPress сэкономил лишь 2-10%, AVIF через GD с качеством 82 получился даже больше JPEG. Так что WebP стоит включать, но без ожидания чуда. Больше дают правильный размер картинок (WordPress сам уменьшает оригиналы шире 2560 пикселей и создает промежуточные размеры) и встроенная ленивая загрузка. Большие фото с телефона и CDN мы не измеряли: у локального стенда нет сетевой задержки, которую сокращает CDN.
Шаг 7. Object cache (Redis)
Redis object cache хранит результаты запросов к базе между открытиями страниц. На стенде (Redis 7.0, php-redis и минимальный drop-in) количество SQL-запросов упало с 22-29 до нуля, TTFB с 43,7-46,8 до 39,6-39,7 мс, пропускная способность выросла на 10-20%. Тяжелый плагин Redis не спас: его 150 прямых запросов и ожидание API никуда не делись, TTFB 306 мс против 311-313 мс без Redis. База на стенде маленькая и локальная, поэтому на большом магазине или с удаленной БД выигрыш может быть больше. Полезнее всего object cache там, где не работает кеш страниц: личные кабинеты, корзина, админка.
Шаг 8. Autoload: проверьте, но не начинайте с него
Опции с пометкой autoload WordPress загружает на каждом запросе. Мы добавили 60 опций по 50 КБ (всего около 3 МБ), и медианный TTFB вырос лишь на 0,4-4,4 мс, p90 на 8-14 мс. Значит, autoload стоит чистить, когда он достигает десятков мегабайт или когда раздел «Здоровье сайта» предупреждает о его размере, но не вместо кеша и OPcache. Проверить размер и самые крупные опции:
$ wp option list --autoload=on --format=total_bytes
44236
$ wp db query "SELECT option_name, LENGTH(option_value) bytes FROM wp_options WHERE autoload IN ('yes','on','auto','auto-on') ORDER BY bytes DESC LIMIT 5"
option_name bytes
_transient_wp_core_block_css_files 20490
_transient_wp_styles_for_blocks 10690
rewrite_rules 8495
wp_user_roles 3133
cron 1027
44 КБ: норма для чистого сайта. Если же вверху списка оказались сотни килобайт от давно удаленного плагина, такую опцию можно убрать из автозагрузки командой wp option set-autoload имя_опции off, заранее сделав резервную копию базы.
Виртуальный хостинг или VPS: что вы можете сделать
| Шаг | Виртуальный хостинг | VPS |
|---|---|---|
| Кеш страниц | Плагин кеша (WP Super Cache, W3 Total Cache, LiteSpeed Cache на LiteSpeed) | nginx fastcgi_cache с конфигом выше |
| OPcache | Проверить тестовым файлом; если выключен, включить в настройках PHP в панели или через поддержку | opcache.enable=1 в php.ini именно для FPM |
| Медленные плагины | Query Monitor | Query Monitor, wp profile, медленный лог PHP-FPM |
| Воркеры PHP | Лимиты задает хостер; если сайт в них упирается, нужен другой тариф | pm.max_children по памяти, как в шаге 4 |
| Сжатие | Обычно уже включено, проверьте через curl | gzip_types в nginx |
| Object cache | Только если хостинг предоставляет Redis или Memcached | redis-server, php-redis и плагин object cache |
Если после кеша, OPcache и разбора плагинов страницы без кеша все равно отвечают медленно, а воркеров не хватает в часы пик, это повод посмотреть на более мощный тариф или VPS; как понять, какой тип хостинга выбрать, мы объясняем отдельно. Требования WordPress к серверу собраны в обзоре хостинг для WordPress, а тарифы RichHost представляют собой виртуальный хостинг на NVMe-дисках с собственной панелью управления и ИИ-помощником и бесплатным SSL Let’s Encrypt.
Частые вопросы
Нужен ли плагин кеша, если на сервере уже есть кеш nginx?
Нет. Два кеша страниц одновременно только усложняют очистку. Оставьте один: серверный на VPS или плагин на виртуальном хостинге.
Почему PageSpeed Insights почти не изменился после кеша?
PageSpeed оценивает всю страницу (изображения, скрипты, шрифты) и измеряет с серверов Google, то есть с сетевой задержкой. Кеш сокращает только серверную часть, остальное дают шаги 5 и 6.
Сколько плагинов: это слишком много?
Количество плагинов мы не измеряли, но один плагин со 150 запросами и обращением к API стоил около 265 мс на каждый запрос. Важно не количество, а то, что каждый плагин делает при каждом открытии страницы; это показывают Query Monitor и wp profile.



