Ця фатальна помилка «Allowed memory size exhausted» не просто дратує. Це та аварія, яка з’являється о 2-й ночі, відразу після оновлення плагіна й напередодні старту кампанії. Сайт працює… поки не перестає. І тоді він тягне за собою адміністративну частину, оформлення замовлень або cron.
Виправлення рідко буває «просто підняти wp-config». Пам’ять WordPress — це стек лімітів по PHP, PHP-FPM, контейнерах, cgroups і інколи невидимого обмеження хостингу. Якщо піднімете не той рівень, нічого не зміниться. Якщо піднімете правильний, не розібравшись чому це потрібно, ви приховаєте витік, поки він не спричинить відмову.
Що насправді означає помилка (і чого вона не означає)
Канонічний збій WordPress виглядає так:
- «Фатальна помилка: Закінчився дозволений обсяг пам’яті X байт (спроба виділити Y байт)»
Це повідомлення походить від PHP, а не від WordPress. WordPress лише повідомник, який підловив «цеглину». PHP досяг жорсткої межі і перервав запит. Ця межа зазвичай — memory_limit, але підлягаюча причина може бути дуже різною:
- Плагін/тема завантажує в пам’ять занадто багато даних (поширено: звіти WooCommerce, конструктори сторінок, імпортери).
- Цикл або рекурсія, що створює нескінченно зростаючі масиви/об’єкти.
- Шлях обробки зображень, що використовує Imagick/GD і тримає кілька повнорозмірних бітмапів.
- Фрагментація OPcache або надто малий OPcache у великому екосистемі плагінів (може виглядати як випадкові затримки або 502, але це той же клас відмов).
- Контейнер або ВМ був вбитий ядром через OOM killer (немає дружньої фатальної помилки PHP; просто мертвий воркер).
- Обмеження тарифного плану хостингу: ви підвищуєте пам’ять у PHP, але провайдер все одно відрублює або пригнічує процес.
Ось ключове: підвищення пам’яті не є умовою перемоги. Це інструмент. Ви підвищуєте пам’ять, щоб (a) безпечно відновити роботу, а потім (b) зробити профіль пам’яті запиту розумним, щоб можна було знизити її знову. Якщо ви робите тільки крок (a), ви відкладете аварію й зробите її дивнішою.
Цитата, щоб не забувати реальність: «Надія — не план»
(загальний операційний афоризм, часто приписується різним інженерним лідерам; перефразований вислів.)
Цікаві факти й контекст (бо ця проблема має історію)
- За замовчуванням memory_limit PHP колись був малим. Старі версії PHP часто постачалися з 128M, що підходило для блогів і було смішно недостатнім для сучасних стеків WordPress.
- У WordPress є два поняття «пам’яті». Константи
WP_MEMORY_LIMITіWP_MAX_MEMORY_LIMITможуть запитувати вищі ліміти, але вони не можуть перевищити те, що дозволяє PHP. - WooCommerce змінив очікування. E‑commerce перетворив «сайт» на «додаток», і навантаження адміністратора/звітування стало настільки даноємким, що потребує серйозної пам’яті.
- PHP-FPM зробив нормою ліміти на пул. До домінування PHP-FPM налаштування лімітів по сайтах було складнішим; тепер ви можете ізолювати сайти через конфіги пулу (коли контролюєте хост).
- OPcache став стандартною фічею продуктивності. Але він також ввів новий режим відмов: виснаження пам’яті кешу коду і фрагментація, що може виглядати як випадкові збої.
- Контейнери змінили правила гри. Контейнер може мати достатній
memory_limitPHP, але все одно бути вбитим через нижчий ліміт cgroup. - Спільний хостинг додає невидимі стелі. Провайдери часто накладають обмеження на обліковий запис (RSS, CPU seconds, entry processes); підвищивши
memory_limit, ви можете робити це церемоніально. - WP‑Cron — це не «реальний cron». WP‑Cron запускається трафіком вебу; коли він виконує важкі завдання всередині запитів, піки пам’яті трапляються в невідповідний час.
Жарт на завершення: помилки пам’яті WordPress — як офісна кава: коли ви нарешті помічаєте проблему, вже пізно й усі незадоволені.
Швидкий план діагностики (перевірка перша/друга/третя)
Це чекліст «припиніть гадати». На більшості систем його можна пройти менш ніж за 15 хвилин.
Перше: це PHP memory_limit, чи ОС/контейнер вас вбиває?
- Якщо ви бачите явну PHP фатальну «Allowed memory size exhausted», це майже завжди
memory_limit(або константа WordPress, яка не змогла його підняти). - Якщо ви бачите 502/504 без PHP фатальної, перевірте логи PHP‑FPM і події ядра/cgroup OOM. Це інший напрямок.
Друге: який SAPI і яка конфігурація фактично використовуються (FPM проти CLI)?
php -i— це CLI. Ваші веб‑запити можуть використовувати іншийphp.iniпід PHP‑FPM.- Використайте ендпоїнт або логи, щоб підтвердити runtime‑параметри для веб‑SAPI.
Третє: ідентифікуйте шлях запиту та винуватця
- Чи це тільки wp‑admin? Тільки оформлення замовлення? Тільки WP‑Cron? Тільки один ендпоїнт?
- Увімкніть цілеспрямоване логування, відтворіть один раз і зніміть стек викликів або список плагінів, що корелюють зі спайком.
Четверте: оберіть правильний рівень усунення
- Аварійний режим: підніміть ефективний ліміт на контролюючому шарі, щоб відновити роботу.
- Стабілізація: ізолюйте через налаштування пулу PHP‑FPM, зменшіть одночасність за потреби.
- Виправлення кореня: баг плагіна/теми, розмір запитів, розмір батчів імпорту, стратегія кешування, розклад WP‑Cron.
Де живуть ліміти пам’яті: стек, що визначає вашу долю
Уявіть пам’ять WordPress як набір воріт. Переможуть найменші ворота. Ви можете намалювати «512M» на ворітці WordPress скільки завгодно; якщо ворота PHP — 128M, ви все одно не пройдете.
Ворота 1: константи WordPress (запити, а не гарантії)
WP_MEMORY_LIMIT: призначено для фронтенду.WP_MAX_MEMORY_LIMIT: призначено для адміністративних задач (оновлення, імпорт тощо).
Ці константи можуть підняти ліміт до межі PHP, залежно від того, чи дозволяє PHP змінювати memory_limit у runtime.
Ворота 2: налаштування runtime PHP (жорстка межа)
memory_limit — це налаштування PHP, яке задається через php.ini, конфіг пулу FPM, конфіг Apache або локальні переоприділення (залежно від SAPI і прав). Саме це зазвичай породжує повідомлення «Allowed memory size exhausted».
Ворота 3: конфігурація пулу PHP‑FPM (ізоляція по сайтах)
Якщо ви керуєте власним хостом (ВМ/безпечна машина), пул PHP‑FPM дозволяє встановити ліміти та поведінку по сайтах. Ви можете примусово задавати php_admin_value[memory_limit] (неперезаписуваний скриптами) або дозволяти php_value (перезаписуваний).
Ворота 4: обмеження менеджера процесів (конкурентність)
Виснаження пам’яті — це не лише «один запит великий». Часто це «багато запитів помірно великих». Налаштування FPM, як-от pm.max_children, вирішують, скільки воркерів може працювати одночасно. Якщо кожен воркер може використовувати до 512M, а ви дозволяєте 20 воркерів, ви обіцяєте ОС 10 GB пам’яті. ОС цього не схвалить.
Ворота 5: ОС, cgroups і OOM killer
У контейнерах і багатьох керованих платформах фактична межа — це ліміт cgroup. Ядро може вбити воркерів PHP‑FPM (або весь контейнер) без фатального повідомлення PHP. У Kubernetes ви побачите OOMKilled. У службах під systemd ви можете бачити облік пам’яті й примусове застосування лімітів.
Ворота 6: політика хостинг‑провайдера
Спільний хостинг і деякі керовані WordPress‑платформи вводять ліміти по обліковому запису (RSS, CPU seconds, entry processes). Ви можете успішно встановити memory_limit в 512M і все одно бути вбитими або пригніченими, бо кап провайдера нижчий або план не дозволяє такого.
Практичні завдання (команди, виводи та рішення)
Це перевірки рівня production. Кожна містить: команду, приклад виводу, що це означає, і рішення.
Завдання 1: Підтвердьте версію PHP і SAPI, що використовується в CLI (базова лінія)
cr0x@server:~$ php -v
PHP 8.2.12 (cli) (built: Oct 12 2024 10:11:21) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.12, Copyright (c) Zend Technologies
with Zend OPcache v8.2.12, Copyright (c), by Zend Technologies
Значення: Це CLI PHP. Корисно для WP‑CLI задач, але не вирішує поведінку веб‑запитів.
Рішення: Якщо помилка виникає через веб‑трафік, не припускайте, що ця конфігурація застосовується. Перейдіть до перевірок FPM/веб.
Завдання 2: Знайдіть, який php.ini використовує CLI (щоб уникнути конфігураційних ілюзій)
cr0x@server:~$ php --ini
Configuration File (php.ini) Path: /etc/php/8.2/cli
Loaded Configuration File: /etc/php/8.2/cli/php.ini
Scan for additional .ini files in: /etc/php/8.2/cli/conf.d
Additional .ini files parsed: /etc/php/8.2/cli/conf.d/10-opcache.ini
Значення: Тепер ви знаєте, звідки CLI читає конфіг.
Рішення: Якщо WP‑CLI не виконує імпорти через помилку пам’яті, можна тут налаштувати. Якщо веб падає — далі перевіряйте FPM.
Завдання 3: Прочитайте ефективний memory_limit для CLI
cr0x@server:~$ php -r 'echo ini_get("memory_limit").PHP_EOL;'
128M
Значення: CLI обмежений 128M.
Рішення: Якщо WP‑CLI імпорти або cron‑задачі падають, підвищте memory_limit для CLI (або запускайте з -d memory_limit=... для одноразових завдань).
Завдання 4: Підтвердьте, що служба PHP‑FPM присутня і працює (веб‑ланка)
cr0x@server:~$ systemctl status php8.2-fpm --no-pager
● php8.2-fpm.service - The PHP 8.2 FastCGI Process Manager
Loaded: loaded (/lib/systemd/system/php8.2-fpm.service; enabled; preset: enabled)
Active: active (running) since Fri 2025-12-27 08:41:10 UTC; 2h 11min ago
Docs: man:php-fpm8.2(8)
Main PID: 1042 (php-fpm8.2)
Tasks: 23 (limit: 18963)
Memory: 612.4M
Значення: FPM запущено; можна переглянути конфіги пулів і логи.
Рішення: Якщо тут великий «Memory:» і ви близькі до лімітів вузла, перегляньте pm.max_children і пам’ять на воркер.
Завдання 5: Знайдіть активні конфіги пулів FPM
cr0x@server:~$ grep -R "^\[" -n /etc/php/8.2/fpm/pool.d/*.conf
/etc/php/8.2/fpm/pool.d/www.conf:1:[www]
/etc/php/8.2/fpm/pool.d/site.conf:1:[site]
Значення: У вас декілька пулів. Це добре для ізоляції; також добре для плутанини.
Рішення: Визначте, який пул обслуговує WordPress‑віртуальний хост, і налаштуйте саме його, а не інший.
Завдання 6: Перевірте memory_limit веб‑SAPI через налаштування пулу FPM
cr0x@server:~$ grep -R "memory_limit" -n /etc/php/8.2/fpm/pool.d/*.conf
/etc/php/8.2/fpm/pool.d/site.conf:38:php_admin_value[memory_limit] = 256M
Значення: Цей пул примушує 256M, і скрипти не можуть підняти його вище, бо це адміністративне значення.
Рішення: Якщо WordPress просить 512M, але все одно падає на 256M, ось чому. Змініть тут і перезавантажте FPM.
Завдання 7: Підтвердьте, чи помилка в логах PHP (не тільки в браузері)
cr0x@server:~$ sudo tail -n 50 /var/log/php8.2-fpm.log
[27-Dec-2025 10:38:55] WARNING: [pool site] child 2517 said into stderr: "PHP Fatal error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 1048576 bytes) in /var/www/html/wp-includes/class-wpdb.php on line 2345"
Значення: Це авторитетний запис: досягнуто межу 256M (268,435,456 байт) під час роботи з базою даних.
Рішення: Підніміть web‑memory_limit (або виправте запит/плагін). Також розгляньте, чому wpdb завантажує так багато (звіти, пошук, величезні autoload опції).
Завдання 8: Перевірте OOM‑вбивства ядром (сценарій «немає PHP фаталу»)
cr0x@server:~$ sudo dmesg -T | tail -n 20
[Sat Dec 27 10:41:02 2025] Out of memory: Killed process 2517 (php-fpm8.2) total-vm:1462256kB, anon-rss:912324kB, file-rss:0kB, shmem-rss:0kB, UID:33 pgtables:3112kB oom_score_adj:0
[Sat Dec 27 10:41:02 2025] oom_reaper: reaped process 2517 (php-fpm8.2), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB
Значення: Ядро вбило PHP‑FPM воркер. Це не подія memory_limit PHP; це тиск пам’яті вузла/контейнера.
Рішення: Зменшіть конкурентність (pm.max_children), збільшіть пам’ять хоста, зменшіть per‑worker memory_limit, або виправте використання пам’яті в запиті. Якщо в контейнерах — підніміть ліміти cgroup.
Завдання 9: Інспектуйте ліміт пам’яті cgroup контейнера (Docker / systemd / cgroups v2)
cr0x@server:~$ cat /sys/fs/cgroup/memory.max
536870912
Значення: Група процесів обмежена 512MB загалом. Якщо ви встановите PHP memory_limit 512M і дозволите кілька воркерів, ви отримаєте OOM‑вбивства.
Рішення: Або підніміть ліміт cgroup, або встановіть нижчий PHP memory_limit (наприклад, 256M) і налаштуйте конкурентність FPM.
Завдання 10: Виміряйте реальне використання пам’яті на PHP‑FPM child (перестаньте гадати)
cr0x@server:~$ ps -o pid,rss,cmd -C php-fpm8.2 --sort=-rss | head -n 8
PID RSS CMD
2519 412980 php-fpm: pool site
2518 356112 php-fpm: pool site
2516 198344 php-fpm: pool site
1042 65244 php-fpm: master process (/etc/php/8.2/fpm/php-fpm.conf)
Значення: RSS — фактична resident пам’ять. У вас воркери в діапазоні 200–400MB.
Рішення: Використовуйте високий перцентиль RSS (не найкращий випадок) для розрахунку pm.max_children. Якщо два воркери вже можуть досягти 400MB кожен, не запускайте 10 на вузлі з 2GB.
Завдання 11: Перевірте вид WordPress на пам’ять (інформативно, не авторитетно)
cr0x@server:~$ wp --path=/var/www/html option get home
https://example.internal
Значення: WP‑CLI може звертатися до кодової бази сайту. Тепер ви можете запускати діагностику.
Рішення: Якщо WP‑CLI сам падає з помилкою пам’яті, тимчасово запускайте його з вищим лімітом для діагностики.
cr0x@server:~$ wp --path=/var/www/html --info
OS: Linux 6.5.0-1022-aws #24~22.04.1-Ubuntu SMP
Shell: /bin/bash
PHP binary: /usr/bin/php8.2
PHP version: 8.2.12
php.ini used: /etc/php/8.2/cli/php.ini
WP-CLI root dir: /home/cr0x/.wp-cli
WP-CLI version: 2.10.0
Значення: Ще раз підтверджує, що це CLI. Корисно, але не плутайте з поведінкою вебу.
Рішення: Якщо продукційна аварія лише веб‑орієнтована, зосередьтеся на налаштуваннях FPM і веб‑логах.
Завдання 12: Швидко визначте важкі плагіни (і безпечно відключіть, якщо потрібно)
cr0x@server:~$ wp --path=/var/www/html plugin list --status=active
+--------------------------+--------+-----------+---------+
| name | status | update | version |
+--------------------------+--------+-----------+---------+
| woocommerce | active | available | 8.6.1 |
| elementor | active | none | 3.20.2 |
| wordfence | active | none | 7.11.2 |
| wp-mail-smtp | active | none | 4.4.0 |
+--------------------------+--------+-----------+---------+
Значення: У вас знайомий набір: ecommerce, конструктор сторінок, плагін безпеки. Будь‑який з них може збільшувати пам’ять на певних ендпоїнтах.
Рішення: Якщо потрібне аварійне відновлення, відключіть ймовірний винуватець (по одному) після створення знімка/резервної копії і повідомлення про вплив.
Завдання 13: Перевірте розмір автозавантажених опцій (тихий пожирач пам’яті)
cr0x@server:~$ wp --path=/var/www/html db query "SELECT ROUND(SUM(LENGTH(option_value))/1024/1024,2) AS autoload_mb FROM wp_options WHERE autoload='yes';"
+------------+
| autoload_mb|
+------------+
| 12.47 |
+------------+
Значення: 12.47MB автозавантажених опцій — це багато. Autoload опції завантажуються на багатьох запитах, підвищуючи базовий використ пам’яті.
Рішення: Аудит великих опцій, зменшення autoload там, де безпечно, і розгляд об’єктного кешу.
Завдання 14: Знайдіть топ автозавантажених опцій (цілі для очищення)
cr0x@server:~$ wp --path=/var/www/html db query "SELECT option_name, ROUND(LENGTH(option_value)/1024/1024,2) AS mb FROM wp_options WHERE autoload='yes' ORDER BY LENGTH(option_value) DESC LIMIT 10;"
+------------------------------+------+
| option_name | mb |
+------------------------------+------+
| _transient_timeout_wc_report | 3.21 |
| elementor_css | 2.44 |
| wordfence_waf_options | 1.18 |
| rewrite_rules | 0.94 |
+------------------------------+------+
Значення: Транзієнти і бінарні блоби конструктора живуть в autoload. Це збільшує пам’ять кожного разу при ініціалізації WordPress.
Рішення: Виправте джерело (налаштування плагіна), очистіть/перебудуйте там, де потрібно, і переконайтеся, що транзієнти не стають постійними автозавантаженими даними.
Завдання 15: Перевірте стан OPcache (коли «пам’ять» — насправді тиск кешу коду)
cr0x@server:~$ php -r 'print_r(opcache_get_status(false)["memory_usage"]);'
Array
(
[used_memory] => 118901488
[free_memory] => 1562032
[wasted_memory] => 4381656
[current_wasted_percentage] => 3.55
)
Значення: OPcache має ~1.5MB вільного простору. Це тісно. При частих деплоях або багатьох плагінах можна вдаритися в стелю.
Рішення: Збільшіть opcache.memory_consumption і розгляньте opcache.max_accelerated_files. Також перегляньте стратегію перезавантаження, щоб зменшити фрагментацію.
Завдання 16: Підтвердіть поточні налаштування менеджера процесів FPM (математика конкурентності)
cr0x@server:~$ grep -nE "^(pm\.|php_admin_value\[memory_limit\])" /etc/php/8.2/fpm/pool.d/site.conf
23:pm = dynamic
24:pm.max_children = 20
25:pm.start_servers = 4
26:pm.min_spare_servers = 4
27:pm.max_spare_servers = 8
38:php_admin_value[memory_limit] = 256M
Значення: Ви можете запускати 20 воркерів, кожному дозволено 256M. Теоретично це 5GB у найгіршому випадку, плюс накладні витрати.
Рішення: На хості 2–4GB це аварія в очікуванні. Зменшіть pm.max_children або зменшіть пам’ять на воркер, потім тестуйте навантаження.
Завдання 17: Безпечно перезавантажте FPM після змін (не рестартуйте продакшн без потреби)
cr0x@server:~$ sudo systemctl reload php8.2-fpm
Значення: FPM перезавантажує конфіг плавно; існуючі запити завершаться, нові використовуватимуть оновлені налаштування.
Рішення: Вдень намагайтеся використовувати reload замість restart, якщо тільки не потрібно жорстке скидання (наприклад, завислі воркери).
Завдання 18: Підтвердьте ефективний memory_limit через веб‑запит (ґрунтова правда)
cr0x@server:~$ curl -sS -H "Host: example.internal" http://127.0.0.1/wp-admin/admin-ajax.php?action=heartbeat | head
0
Значення: Веб відповідає. Це не показує memory_limit напряму, але швидка перевірка після змін.
Рішення: Якщо помилка була на адміністративних ендпоїнтах, відтворіть точну дію, що падала, і моніторте логи на фатали пов’язані з пам’яттю.
Підвищення лімітів правильно: рецепти за моделлю хостингу
Правило: встановлюйте ліміти якомога ближче до шару, який їх застосовує. Константи WordPress підходять для підштовхування. Вони — не контроль.
Сценарій A: Ви контролюєте ВМ/фізичний сервер (Nginx/Apache + PHP‑FPM)
1) Встановіть memory_limit на пулі (рекомендовано)
Редагуйте файл пулу (приклад: /etc/php/8.2/fpm/pool.d/site.conf):
- Використовуйте
php_admin_value[memory_limit] = 256M(або 384M/512M), коли хочете примусового застосування. - Використовуйте
php_value[memory_limit] = 256M, якщо хочете дозволити додаткам перевизначати (зазвичай цього не роблять).
Потім перезавантажте FPM і підтвердіть, що логи перестали показувати виснаження пам’яті.
2) Налаштуйте конкурентність через pm.max_children
Підвищення memory_limit без налаштування конкурентності — це як перетворити помилку одного запиту у повний OOM вузла. Зробіть математику:
- Виміряйте реальний RSS воркерів (Завдання 10).
- Виберіть безпечний бюджет: лишіть місце для кешу ОС, бази даних і веб‑серверу.
- Встановіть
pm.max_children, щоб worst‑case RSS × children укладався в бюджет.
3) Тримайте константи WordPress скромними (і чесними)
У wp-config.php можна встановити:
define('WP_MEMORY_LIMIT', '256M');define('WP_MAX_MEMORY_LIMIT', '512M');
Це допомагає WordPress просити більше пам’яті для адміністративних завдань, не давши кожному фронтенд‑запиту безконтрольну суму. Якщо ваш пул PHP‑FPM примушує 256M, встановлення WP_MAX_MEMORY_LIMIT на 512M не допоможе. Ця невідповідність — сигнал: вирішіть, чи адміністративно потрібно 512M, або чи звіт/плагін треба виправити.
Сценарій B: Спільний хостинг (типу cPanel) з обмеженим контролем
Тут поради з інтернету часто не працюють. Ви можете не контролювати пула PHP‑FPM. Провайдер може запускати suPHP, LSAPI або власну обгортку.
Порядок дій:
- Перевірте, що ви можете змінювати (MultiPHP INI Editor, налаштування PHP по домену тощо).
- Спробуйте підняти
memory_limitчерез UI провайдера (краще). - Якщо дозволено, додайте або відредагуйте
.user.iniзmemory_limit = 256M. Увага: зміни можуть застосовуватися кілька хвилин. - Якщо використовується Apache mod_php і дозволено, використайте директиви в
.htaccess(часто вимкнені на сучасних хостах). - Якщо нічого з цього не працює — прийміть реальність: ви дісталися межі плану. Оптимізуйте або оновлюйте/мігруйте.
Дві попередження:
- Не виставляйте сліпо 1024M, бо знайшли форумний пост 2016 року. Це не вирішить провайдерський ліміт і приховає витік, поки ваш обліковий запис не обмежать.
- Не припускайте, що логи повні. Спільний хостинг може приховувати ключові сигнали. Використовуйте логування на рівні додатку, коли можливо.
Сценарій C: Docker / Compose
У контейнерах у вас мінімум два ліміти: PHP memory_limit і ліміт пам’яті контейнера. Їх потрібно узгоджувати.
Як має виглядати правильно:
- Ліміт пам’яті контейнера розраховано на пікову конкурентність.
- Кількість воркерів PHP‑FPM обмежена, щоб уникнути OOM‑вбивств cgroup.
- PHP
memory_limitвстановлено нижче порогу «занадто великий, щоб провалитися» для воркера.
Якщо ваш контейнер обмежений 512MB, встановлення PHP memory_limit у 512M — як купити валізу рівно під допустимий ліміт авіакомпанії, а потім покласти цеглину. Вона закривається до моменту, коли не закривається.
Сценарій D: Kubernetes (WordPress за Ingress)
У Kubernetes пам’ять — це контракт ресурсів:
- Requests/limits визначають розміщення і застосування. Якщо limit низький, pod буде OOMKilled під навантаженням.
- Встановіть конкурентність PHP‑FPM відповідно до того, що ваш pod може витримати.
- Моніторте OOMKilled події, цикли рестартів і спалахи 502 від upstream‑таймаутів.
Якщо ви не можете зробити пам’ять передбачуваною, ймовірно, у вас є плагін‑ендпоїнт без меж: занадто багато рядків, занадто багато згенерованого HTML або експорт, що намагається побудувати весь файл в пам’яті.
Коли підвищення лімітів — неправильне рішення: плагіни, теми та реальні витоки
Більшість інцидентів «memory exhausted» починаються зі зміни: оновлення плагіна, новий звіт, масовий імпорт або невинна функція теми, що виконується на кожному запиті.
Як визначити, що ви ховаєте витік
- Використання пам’яті поступово зростає з часом по всіх воркерах, а не лише під час одного ендпоїнта.
- Один і той самий запит іноді успішний, іноді ні, залежно від кешованого стану або шляхів OPcache/коду.
- Підвищення пам’яті «виправляє» проблему на кілька днів, а потім вона повертається ще гірша.
Типові винуватці (і патерн за ними)
- Генератори звітів: завантажують цілі таблиці в PHP‑масиви. Виправлення — сторінкова видача, обмеження запитів, потокова генерація експортів або перенесення роботи в асинхронні завдання.
- Імпортери: читають весь CSV/XML в пам’ять. Виправлення — чанкована обробка і менші розміри батчів.
- Конструктори сторінок: масиви post meta і JSON‑блоки. Виправлення — обрізання шаблонів, кешування і контроль ревізій.
- Плагіни безпеки: важкі скани, правила WAF, часті записи в опції. Виправлення — налаштування, планування сканів поза піком і переведення кешів з autoload.
- Неміряні транзієнти: «тимчасові» дані, що стають постійними. Виправлення — очищення і правильне встановлення термінів життя.
Практичний підхід: стабілізувати, потім ізолювати
У продакшні ви не починаєте з видалення половини плагінів. Ви починаєте з того, щоб зробити систему стабільною для налагодження.
- Підніміть ефективний ліміт лише настільки, щоб зупинити крах.
- Зменшіть конкурентність, якщо хост ризикує OOM.
- Відтворіть помилку на staging з тими самими даними.
- Відключайте підозрілі плагіни по одному, вимірюючи пам’ять і час запиту.
- Виправте корінь або замініть плагін. «Але ми за нього заплатили» — не стратегія продуктивності.
OPcache і схожі на «memory exhausted» випадки
Іноді користувачі повідомляють «memory exhausted», але насправді бачите 502, повільну адмінку та логи про OPcache. Інший симптом, той же клас: тиск пам’яті.
Режим відмови OPcache, який треба розпізнати
- Після багатьох деплоїв або оновлень плагінів OPcache фрагментується.
- Нові PHP‑файли не кешуються, продуктивність падає, і CPU воркерів зростає.
- Перезавантаження FPM тимчасово «виправляє» проблему, бо скидає OPcache.
OPcache не опціональний для завантажених WordPress‑сайтів. Але йому потрібна достатня пам’ять і слоти файлів, щоб кешувати кодову базу. Сучасний WordPress з WooCommerce і кількома десятками плагінів легко може перевищити консервативні значення за замовчуванням.
Три корпоративні міні‑історії з поля бою
1) Інцидент через неправильне припущення
Вони щойно мігрували портфель WordPress‑сайтів зі старого спільного хостингу на блискучу нову ВМ. Команда зробила очевидне: задали define('WP_MEMORY_LIMIT','512M'); у wp-config.php по всьому парку сайтів. Також залишили запис: «Проблеми з пам’яттю вирішено».
Два тижні потому, під час вікна оновлення плагінів, половина сайтів почала повертати 502. На виклику не було повідомлення «Allowed memory size exhausted», і команда почала шукати в таймаутах Nginx, upstream keepalive та DNS. Це був повний тур усіх можливих місць, крім істинного.
Корінь був банальний: у пулах PHP‑FPM було php_admin_value[memory_limit] = 128M, успадковане від базових жорстких налаштувань. WordPress не міг його перевизначити. Адмін‑запити на оновлення вичерпували пам’ять і падали воркери. Nginx повідомляв 502, бо upstream помирав під час запиту.
Виправлення зайняло десять хвилин, коли глянули в правильне місце: підняли ліміт пулу до 256M для уражених сайтів, перезавантажили FPM і повторили оновлення. Реальний урок зайняв більше часу: ніколи не вважайте константи WordPress джерелом правди. Вони — запит; платформа вирішує.
2) Оптимізація, що відвернулась боком
Менеджер з інженерії хотів підвищити пропускну спроможність під час запуску продукту. Команда агресивно збільшила pm.max_children. Більше воркерів — більше паралельних запитів, правда? CPU у тестах витримав, і головна сторінка стала швидшою. Перемога, приблизно на день.
Потім вийшов маркетинговий емейл. Трафік на оформлення замовлень підскочив, і пам’ять теж. Деякі ендпоїнти WooCommerce під реальними корзинами і плагінами підіймалися до декількох сотень мегабайт на запит. З більшим числом дітей вузол швидко вичерпав RAM. Ядро почало вбивати воркерів. Запити повторювалися. Навантаження росло. Система скотилася в самонавмисний DoS.
Вони відкочували pm.max_children і підняли PHP memory_limit «щоб було безпечніше». Це трохи допомогло, але лише тому, що зменшило частоту фаталів PHP, тримаючи вузол у зоні ризику.
Кінцева стабільна конфігурація була нудною: виміряти пік RSS на воркері, встановити pm.max_children згідно бюджету хоста і обмежити memory_limit, щоб один нестримний запит не міг з’їсти весь вузол. Також важку генерацію звітів винесли в фонові черги.
3) Нудна, але правильна практика, що врятувала день
Інша компанія запускала WordPress у складі більшої платформи. Нічого блискучого: окремі пули на сайт, консервативні значення за замовчуванням і процес змін, що вимагав одного перед налаштуванням — вимірювання.
У них був простий скрипт, що логував хай‑ватери пам’яті для повільних запитів і корелював їх з шляхами ендпоїнтів. Це не було fancy APM. Але для їхніх потреб цього вистачило. Коли нова версія плагіна почала споживати більше пам’яті на wp-admin/admin-ajax.php, команда помітила зміни за кілька годин.
Замість того, щоб піднімати 512M для всіх сайтів, вони підвищили пам’ять лише для ураженого пулу, зменшили його конкурентність і відкрили тикет вендору з відтворюваними даними. Тим часом решта флоту залишилася стабільною і дешево працювала.
У день запуску, коли трафік подвоївся, нової поведінки пам’яті не з’явилося. Вони вже знали межі. Сайт залишився вгору. Ніхто не писав героїчного постмортему — і це найвища похвала для операцій.
Поширені помилки: симптом → корінь → виправлення
1) «Я встановив WP_MEMORY_LIMIT на 512M, але все одно вмирає на 128M»
Симптом: Фатал каже 134,217,728 байт вичерпано (128M) незважаючи на конфіг WordPress.
Корінь: Пул PHP‑FPM використовує php_admin_value[memory_limit] або глобальний php.ini нижчий; runtime‑зміни блокуються.
Виправлення: Підніміть memory_limit у контролюючому шарі (FPM пул/php.ini/інтерфейс хоста), перезавантажте FPM, підтвердіть через логи.
2) «Отримуємо 502/504, немає PHP фаталу»
Симптом: Nginx повідомляє про upstream‑помилки; логи PHP тихі.
Корінь: Воркер вбитий OS OOM, FPM впав або upstream таймаутнув. Це не подія memory_limit PHP.
Виправлення: Перевірте dmesg на OOM‑вбивства, дивіться логи FPM, зменшіть pm.max_children, узгодьте ліміти контейнера і виправте важкі ендпоїнти.
3) «Тільки wp‑admin падає, фронтенд в порядку»
Симптом: Адмін‑оновлення/імпорти/звіти падають; відвідувачі можуть переглядати сайт.
Корінь: Адмін‑задачі використовують більші дані і можуть просити WP_MAX_MEMORY_LIMIT, але пул PHP має занадто низький ліміт або адмін‑шлях викликає важкі плагіни.
Виправлення: Встановіть вищий бюджет пам’яті для адмінки, якщо це виправдано, і оптимізуйте конкретний адмін‑потік (батчинг, пагінація, експорт).
4) «Почалось після ввімкнення плагіна безпеки»
Симптом: Випадкові фатали пам’яті, повільні запити, велика таблиця опцій.
Корінь: Функції сканування/WAF збільшують накладні витрати на запит; опції/транзієнти зберігаються погано.
Виправлення: Налаштуйте плагін, плануйте скани поза піком, перемістіть кеші з autoload, подумайте про object cache.
5) «Підвищення пам’яті виправило… до наступного дня»
Симптом: Повторювані інциденти зі зростаючою базовою пам’яттю або нові сторінки тригерять це.
Корінь: Поведінка схожа на витік (необмежені масиви, великі autoload опції, шествуючі cron‑задачі) або зростання набору даних.
Виправлення: Визначте ендпоїнт, профілюйте пам’ять, виправте ріст даних (очищення autoload), і встановіть запобіжники на імпорти/звіти.
6) «WP‑CLI працює, сайт все ще падає»
Симптом: CLI команди успішні; веб‑запити падають.
Корінь: Різні php.ini і memory_limit між CLI і FPM.
Виправлення: Налаштуйте FPM пул/php.ini для веб‑запитів; розглядайте CLI як окремий runtime.
Ще один короткий жарт: Встановити memory_limit в 2G без вимірювань — як лагодити протікаючу трубу, купивши більший підвал.
Чеклісти / покроковий план
Аварійне відновлення (повернути сайт без погіршення ситуації)
- Підтвердьте режим відмови. PHP фатал проти OOMKilled проти таймауту.
- Підніміть ефективний ліміт в шарі, що його застосовує. Для FPM: конфіг пулу. Для контейнера: cgroup плюс PHP.
- Перезавантажте конфіг плавно, не рестартуйте. Зменшіть вплив на користувачів.
- Зменшіть конкурентність, якщо ви близько до лімитів хоста. Понизьте
pm.max_children, щоб уникнути OOM вузла. - Зберіть доказ. Лінія логу з байтами вичерпано, ендпоїнт і контекст плагіна.
Стабілізація (зробити поведінку передбачуваною)
- Виміряйте розподіл RSS воркерів. Використовуйте
psдля реальних хай‑ватерів. - Підійдіть до розміру пулу. Встановіть
pm.max_childrenна основі пам’яті, а не надії. - Встановіть розумний memory_limit. Типові production‑значення: 256M–512M залежно від навантаження, але лише після вимірювання.
- Перевірте autoload опції. Зменшіть базове надування пам’яті.
- Перегляньте розміри OPcache. Уникайте виснаження кешу коду.
Виправлення кореня (де ви справді перемагаєте)
- Визначте ендпоїнт. Admin‑ajax? Звіти? Імпорт? Пошук продуктів?
- Тестуйте відключення підозрілих плагінів. Один за одним, з контрольованим відкатом.
- Оптимізуйте доступ до даних. Додайте пагінацію, обмежте розміри експортів, уникайте завантаження всіх результатів одразу.
- Перенесіть важку роботу в асинхронне виконання. Фонові завдання замість синхронних адмін‑запитів.
- Перегляньте обмеження хостингу. Якщо ви на спільному хостингу й досягаєте невидимих капів — плануйте міграцію.
Поширені питання (FAQ)
1) Чи завжди «Allowed memory size exhausted» фіксується підвищенням memory_limit?
Ні. Це фіксується тим, що запит використовує менше пам’яті, ніж ліміт. Підвищення ліміту може бути правильним тимчасовим заходом, але витоки й необмежені навантаження потребують виправлення коду/даних.
2) Який розумний memory_limit для WordPress у 2025 році?
256M — типовий базовий рівень для не‑ecommerce сайтів. 384M–512M — звичні для WooCommerce і важкого адмін/звітування. Якщо вам регулярно потрібно 1G — розглядайте це як симптом і розслідуйте.
3) Чому wp-config.php іноді не працює?
Тому що PHP‑FPM (або хост) може примусово встановлювати memory_limit через php_admin_value або політику провайдера. WordPress може лише запитувати підвищення, якщо PHP дозволяє.
4) Чому фатал показує байти замість мегабайт?
PHP звітує в байтах. 128M = 134,217,728 байт; 256M = 268,435,456 байт; 512M = 536,870,912 байт. Використовуйте це, щоб ідентифікувати реальну межу.
5) Сайт падає тільки під час імпортів. Чи піднімати пам’ять назавжди?
Краще запускати імпорти меншими батчами або через CLI з тимчасово вищим лімітом. Постійно високі ліміти збільшують радіус ураження від помилок і піків трафіку.
6) Як визначити, що ліміт контейнера — справжня проблема?
Якщо ви бачите OOMKilled події, рестарти контейнерів або логи ядра OOM без PHP фаталів — ви потрапляєте в ліміт cgroup/ОС. Узгодьте пам’ять контейнера, PHP memory_limit і конкурентність FPM.
7) Чи OPcache може викликати «memory exhausted» помилки?
Виснаження OPcache відрізняється від PHP request memory_limit, але може спричиняти нестабільність і падіння продуктивності, що виглядає як випадкові збої. Розмір OPcache має відповідати footprint плагінів/тем.
8) Чи варто ставити WP_MAX_MEMORY_LIMIT вищим за WP_MEMORY_LIMIT?
Так, часто варто. Фронтенд‑запити мають бути обмежені; адмін‑задачі справедливо вимагають більше простору. Але це працює тільки якщо PHP дозволяє і ваш хост має достатньо RAM.
9) Якщо я на спільному хостингу й не можу змінити memory_limit — що робити?
Тоді ваш реальний ліміт — це ваш тариф. Оптимізуйте навантаження (відключіть важкі плагіни, зменшіть autoload‑надування, пакетну обробку імпортів) і плануйте оновлення або міграцію, якщо бізнес цього потребує.
10) Чи підвищення pm.max_children — гарне виправлення помилок пам’яті?
Зазвичай навпаки. Більше дітей збільшує загальне споживання пам’яті. Збільшуйте його лише коли виміряли RSS кожного воркера і маєте запас RAM.
Наступні кроки, які ви можете зробити сьогодні
- Визначте, яку відмову ви маєте: PHP memory_limit фатал проти ОС/контейнер OOM проти таймауту.
- Знайдіть шар, що застосовує ліміт: пул PHP‑FPM, php.ini, ліміт контейнера або кап хостингу.
- Підніміть правильний ліміт, мінімально: достатньо, щоб відновити роботу, але не настільки, щоб приховувати витік місяцями.
- Зробіть математику конкурентності: per‑worker RSS × max_children має вміститися в коробці з запасом.
- Пошукайте реального винуватця: важкі плагіни, autoload‑надування, необмежені звіти/імпорти або поведінка cron.
Якщо ви нічого більше не зробите, зробіть це: припиніть вважати налаштування пам’яті WordPress авторитетними. Платформа вирішує. Ваше завдання — зробити це рішення явним, виміряним і безпечним.