It always happens at the worst time: you click “Update” in wp-admin, the spinner spins, and then you get a fatal error about memory. Or the admin turns into a blank white page and your phone starts ringing like you just deleted the database on purpose.
This problem is rarely solved by blindly “adding more RAM.” It’s solved by understanding what memory WordPress is actually allowed to use, what PHP is actually using, and what’s quietly chewing through it: plugins, image processing, imports, cron jobs, and the occasional theme that thinks recursion is a lifestyle.
What the error really means (and what it doesn’t)
The classic message looks like:
Fatal error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 20480 bytes)
Translate it like an SRE:
- “Allowed memory size” is the PHP process memory cap (
memory_limit), not the server’s physical RAM. - The number in bytes tells you the limit at the moment of failure (268,435,456 bytes = 256M).
- The “tried to allocate …” is the last straw, not the total missing amount. You might be 20KB short or 200MB short. You don’t know yet.
- Where it happens matters: admin requests, WP-CLI, cron, AJAX, REST, and image processing can each run under different PHP SAPI/pool configs with different limits.
What it doesn’t mean:
- It doesn’t automatically mean WordPress “needs more memory.” Sometimes it needs fewer plugins, fewer autoloaded options, or fewer gigantic arrays built from poorly paginated queries.
- It doesn’t mean you should set
memory_limit = -1unless you enjoy turning small problems into large incidents. - It doesn’t mean more server RAM fixes it. You can have 128GB RAM and still cap PHP at 128M, then wonder why WooCommerce reports die mid-request.
Here’s the operational truth: WordPress is a PHP app with a plugin ecosystem that can and will exceed reasonable limits unless you measure and enforce. Your job is to make the limit appropriate and make the workload sane.
Interesting facts and a little history
These aren’t trivia-night party tricks. They explain why the failure modes are so common.
- PHP’s
memory_limithas existed since early PHP 4 as a guardrail against runaway scripts in shared hosting. WordPress grew up in that world. - The “white screen of death” in WordPress was historically caused by fatal PHP errors with display disabled. Memory exhaustion is one of the top causes.
- WordPress defines two memory constants:
WP_MEMORY_LIMIT(front-end) andWP_MAX_MEMORY_LIMIT(admin). Many people set one and assume both. - WooCommerce and page builders changed the admin workload: “admin” stopped being a few forms and became a single-page app that does heavy API calls and large object graphs.
- OPcache can reduce memory churn (fewer recompilations) but it also consumes its own shared memory. Tuning it wrong can produce bizarre “it fails only sometimes” behavior.
- Image processing got heavier over the years as “responsive images” and multiple sizes became default. One upload can mean many resizes, plus EXIF parsing.
- Composer autoloaders and modern PHP libraries crept into plugins. Great for engineering, occasionally terrible for memory if vendors are bundled repeatedly.
- Some hosts run separate PHP-FPM pools per site or per user. That’s good isolation, but it means your “I changed php.ini” fix often hits the wrong pool.
- WordPress cron isn’t a real cron by default; it’s traffic-triggered. That means heavy jobs can run at the worst possible time: right when an admin is trying to update plugins.
Fast diagnosis playbook
If you want to stop bleeding quickly, you need a deterministic order of checks. Don’t start by editing three configs and hoping. Do this:
1) Confirm where the request runs and what PHP config it uses
- If it happens in wp-admin, you’re likely hitting PHP-FPM via Nginx/Apache proxy, or mod_php on Apache.
- If it happens in WP-CLI, you’re using CLI PHP (different ini, different memory limit).
- If it happens during cron/import, it might run under PHP-FPM but on a different endpoint or even a different pool.
2) Read the logs that contain the truth
- PHP-FPM error log (memory exhaustion stack traces, pool name).
- Web server error log (request path, upstream, timeouts).
- WordPress debug log (if enabled) for the last executed plugin/theme code.
3) Measure real memory use per request
- If one request spikes to the cap: you have a heavy page (often plugin-driven).
- If memory climbs over time across requests: you may have a leak pattern (more common with persistent workers + caching objects in static variables).
4) Apply the smallest safe mitigation
- Raise
memory_limitmoderately (256M → 512M is common for complex admin stacks). - Increase only for the pool/site that needs it, not the entire server.
- Re-test the exact failing action (plugin update, media upload, report generation).
5) Fix the underlying load
- Disable or replace the memory hog plugin.
- Fix autoloaded options bloat.
- Paginate queries, reduce admin dashboard widgets, and fix import/export tooling.
Rule: memory tuning is a bandage until you prove the workload is healthy.
Root causes you can actually fix
Cause A: You changed the wrong knob
There are multiple “memory limits” in play:
- PHP
memory_limit: the real cap. Set in php.ini, pool config, or runtime overrides. WP_MEMORY_LIMIT/WP_MAX_MEMORY_LIMIT: WordPress requests a memory limit, but PHP can refuse if configured lower.- Hosting control panel values: often write to one ini location but your actual FPM pool loads another.
- Container limits (cgroups): if you’re in Docker/Kubernetes, the container might be limited even if PHP says “512M”.
Cause B: Plugin or theme builds massive arrays (often accidentally)
Common patterns:
- Loading all posts/users/orders without pagination (“just for the dropdown”).
- Running expensive analytics in PHP instead of SQL.
- Fetching remote APIs and caching entire responses in memory.
- Recursive rendering or nested shortcodes that explode content size.
Cause C: Autoloaded options bloat
WordPress loads all autoload = 'yes' options on every request. If that row set becomes megabytes of serialized junk, every request pays. The admin pays extra because it does more. This is the quiet killer on “it used to work” sites.
Cause D: Media processing and large uploads
Image resizing can allocate large buffers. So can PDF thumbnail generation, EXIF parsing, and “optimize images on upload” plugins. Memory spikes are normal; repeated spikes that hit your cap are not.
Cause E: Cron collisions and background jobs
If WP-Cron triggers heavy work during admin activity, you get memory contention and worker exhaustion. The error may show up in unrelated admin pages because the pool is under stress and workers recycle at bad times.
Cause F: PHP-FPM pool sized like a fantasy novel
If each PHP-FPM worker can use up to 512M, and you allow 20 children, you’ve promised the kernel 10GB of memory it may not have. Linux will enforce reality with swapping, OOM kills, and sadness. Your WordPress memory issue becomes a server outage.
Cause G: OPcache misconfiguration
OPcache helps, but mis-sizing it leads to frequent restarts or cache thrash. That can amplify memory spikes during recompilation and increase request latency, causing more concurrent workers (and therefore more memory usage).
One paraphrased idea from Werner Vogels (Amazon CTO): Everything fails, so design systems that expect failure and recover quickly.
That mindset applies here: build limits that prevent a plugin from taking the whole site down.
Practical tasks: commands, outputs, decisions (12+)
These tasks assume a typical Linux server with Nginx + PHP-FPM or Apache. Adjust paths for your distro. Every task includes: command, example output, what it means, and what decision you make.
Task 1: Identify which PHP binary you’re using (CLI)
cr0x@server:~$ php -v
PHP 8.2.12 (cli) (built: Oct 10 2024 10:11:05) (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
Meaning: This is CLI PHP. WP-CLI uses this unless configured otherwise.
Decision: If the error occurs in WP-CLI (imports, updates), fix the CLI ini path and memory limit too—not just FPM.
Task 2: Find which ini files CLI PHP loads
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
/etc/php/8.2/cli/conf.d/20-mysqli.ini
Meaning: This is where CLI memory_limit is coming from.
Decision: If CLI jobs fail, edit /etc/php/8.2/cli/php.ini (or add an override ini) rather than changing FPM settings and wondering why nothing changes.
Task 3: Check current CLI memory_limit
cr0x@server:~$ php -r 'echo ini_get("memory_limit"), PHP_EOL;'
128M
Meaning: CLI jobs are capped at 128M.
Decision: For WP-CLI heavy operations, set it higher (often 512M or 1024M), or use per-command overrides.
Task 4: Verify PHP-FPM service and version
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)
Active: active (running) since Fri 2025-12-27 08:41:10 UTC; 2h 11min ago
Docs: man:php-fpm8.2(8)
Main PID: 1134 (php-fpm8.2)
Tasks: 34 (limit: 18970)
Memory: 612.3M
Meaning: PHP-FPM is running; memory here is total across workers.
Decision: If the service is restarting often or memory is huge, you likely have pool sizing issues or a memory hog request pattern.
Task 5: Locate the PHP-FPM pool config actually serving the site
cr0x@server:~$ grep -R "listen =" -n /etc/php/8.2/fpm/pool.d
/etc/php/8.2/fpm/pool.d/www.conf:41:listen = /run/php/php8.2-fpm.sock
/etc/php/8.2/fpm/pool.d/siteA.conf:33:listen = /run/php/php8.2-fpm-siteA.sock
Meaning: There are multiple pools. Your site might not be using www.
Decision: Identify the socket your vhost uses, then tune the correct pool. Editing the wrong pool is a classic “I swear I changed it” outage.
Task 6: Confirm Nginx is pointing to the expected FPM socket
cr0x@server:~$ sudo nginx -T 2>/dev/null | grep -n "fastcgi_pass" | head
218: fastcgi_pass unix:/run/php/php8.2-fpm-siteA.sock;
401: fastcgi_pass unix:/run/php/php8.2-fpm.sock;
Meaning: Different server blocks use different pools.
Decision: Apply memory_limit and pool sizing changes to the pool actually used by the WordPress vhost.
Task 7: Check FPM pool memory limit overrides
cr0x@server:~$ sudo grep -nE "php_admin_value\[memory_limit\]|php_value\[memory_limit\]" /etc/php/8.2/fpm/pool.d/siteA.conf
55:php_admin_value[memory_limit] = 256M
Meaning: The pool hard-caps PHP at 256M regardless of wp-config.php.
Decision: If admin actions exceed 256M, raise this value cautiously (e.g., 512M) and recalc FPM max_children to avoid OOM risk.
Task 8: Reload PHP-FPM safely after changes
cr0x@server:~$ sudo systemctl reload php8.2-fpm
Meaning: Reload applies config without dropping all connections (usually).
Decision: Prefer reload to restart in production. If reload fails, check syntax and logs before escalating to restart.
Task 9: Confirm memory_limit seen by FPM via a temporary endpoint
cr0x@server:~$ printf '%s\n' '/dev/null
cr0x@server:~$ curl -sS http://127.0.0.1/mem.php
256M
Meaning: The web-executed PHP sees 256M.
Decision: If you expected 512M and got 256M, you’re still editing the wrong config file, the wrong pool, or caching/proxying the wrong vhost.
Task 10: Inspect PHP-FPM slowlog and error log for memory exhaustion traces
cr0x@server:~$ sudo tail -n 30 /var/log/php8.2-fpm.log
[27-Dec-2025 10:42:18] WARNING: [pool siteA] child 20211, script '/var/www/siteA/public/wp-admin/admin-ajax.php' (request: "POST /wp-admin/admin-ajax.php") executing too slow (5.123 sec), logging
[27-Dec-2025 10:42:18] PHP Fatal error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 65536 bytes) in /var/www/siteA/public/wp-content/plugins/some-plugin/includes/report.php on line 812
Meaning: The failing endpoint and offending plugin file are named. This is gold.
Decision: Don’t just raise memory. Investigate the plugin action (report generation via AJAX) and decide whether to disable, patch, or change its settings.
Task 11: Disable plugins without wp-admin (WP-CLI)
cr0x@server:~$ cd /var/www/siteA/public
cr0x@server:~$ sudo -u www-data wp plugin list --status=active
+----------------------+----------+-----------+---------+
| name | status | update | version |
+----------------------+----------+-----------+---------+
| woocommerce | active | none | 8.5.2 |
| some-plugin | active | none | 3.1.0 |
| cache-plugin | active | available | 2.9.1 |
+----------------------+----------+-----------+---------+
cr0x@server:~$ sudo -u www-data wp plugin deactivate some-plugin
Plugin 'some-plugin' deactivated.
Meaning: You can recover admin access without clicking around in a broken UI.
Decision: If deactivating stops memory exhaustion, you’ve isolated the culprit. Keep it off until you can reproduce in staging and fix properly.
Joke 1: Disabling a plugin to fix production feels like turning off the smoke alarm because the kitchen’s on fire. It works, but please also stop the fire.
Task 12: Check WordPress memory constants (wp-config.php)
cr0x@server:~$ grep -nE "WP_MEMORY_LIMIT|WP_MAX_MEMORY_LIMIT" /var/www/siteA/public/wp-config.php
91:define('WP_MEMORY_LIMIT', '256M');
92:define('WP_MAX_MEMORY_LIMIT', '512M');
Meaning: WordPress is requesting 512M for admin.
Decision: If PHP-FPM is still at 256M, raise FPM’s memory_limit. If PHP-FPM is already at 512M and you still crash, fix the workload.
Task 13: Detect autoloaded options bloat in MySQL
cr0x@server:~$ mysql -N -e "SELECT ROUND(SUM(LENGTH(option_value))/1024/1024,2) AS autoload_mb FROM wp_options WHERE autoload='yes';"
8.74
Meaning: Nearly 9MB of autoloaded options are loaded on every request. That’s not a rounding error.
Decision: Anything above ~1–2MB is worth investigating. Above ~5MB, expect performance and memory pain. Find the biggest offenders and stop autoloading them.
Task 14: Find the worst autoload offenders
cr0x@server:~$ mysql -N -e "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;"
some_plugin_cache 3.12
builder_global_settings 1.47
woocommerce_sessions 0.88
theme_mods_mytheme 0.62
Meaning: A few options dominate the footprint.
Decision: For options that don’t need to be autoloaded, flip autoload to ‘no’ and ensure the plugin can handle it. If it can’t, replace the plugin or patch it.
Task 15: Flip autoload off for a specific option (carefully)
cr0x@server:~$ mysql -e "UPDATE wp_options SET autoload='no' WHERE option_name='some_plugin_cache';"
cr0x@server:~$ mysql -N -e "SELECT option_name, autoload FROM wp_options WHERE option_name='some_plugin_cache';"
some_plugin_cache no
Meaning: The option will no longer be loaded on every request.
Decision: Test admin flows that depended on it. If anything breaks, revert and handle differently (plugin setting, cache backend, or replacement).
Task 16: Inspect PHP-FPM process memory in the real world
cr0x@server:~$ ps -o pid,pmem,rss,cmd -C php-fpm8.2 --sort=-rss | head
PID %MEM RSS CMD
20211 2.6 214336 php-fpm: pool siteA
20219 2.5 208912 php-fpm: pool siteA
20205 1.8 146220 php-fpm: pool siteA
Meaning: RSS shows real resident memory. Workers are around ~200MB each right now.
Decision: Use this to size pm.max_children. If each child is ~200MB and you can spare 2GB for PHP workers, don’t run 20 children.
Task 17: Check cgroup/container memory limits (if applicable)
cr0x@server:~$ cat /sys/fs/cgroup/memory.max 2>/dev/null || true
1073741824
Meaning: The process is capped at 1GB by cgroups (value is bytes). That’s the ceiling for everything in the container.
Decision: If you set PHP to 512M and allow multiple workers, you’ll hit container OOM. Adjust container limits or worker counts.
Task 18: Verify OPcache sizing and behavior
cr0x@server:~$ php -r 'print_r(opcache_get_status(false)["memory_usage"]);'
Array
(
[used_memory] => 78120384
[free_memory] => 26345472
[wasted_memory] => 4128768
[current_wasted_percentage] => 4.72
)
Meaning: OPcache has limited free memory; wasted is moderate.
Decision: If free memory is near zero and wasted climbs, increase opcache.memory_consumption and/or tune revalidate settings. If OPcache resets frequently, your request latency and peak concurrency can rise, increasing memory pressure.
Three corporate mini-stories from the trenches
Mini-story 1: The incident caused by a wrong assumption
The company had a “simple” WordPress install: marketing site, a few landing pages, and a blog. Then they added WooCommerce “just for a few products.” Nobody changed the hosting tier because it was “only a plugin.”
Two weeks later, finance asked for an orders report. A well-meaning manager clicked “Export CSV” from the admin. The admin page hung, then crashed with the memory exhaustion fatal error. They tried again. Same result. Then they tried again, because humans are consistent like that.
The on-call engineer raised WP_MAX_MEMORY_LIMIT to 512M, but the crash continued. They raised it to 1024M. Still. They concluded the server was “too small” and requested a larger VM.
The real issue was that PHP-FPM had a pool-level php_admin_value[memory_limit] = 256M override from the original shared hosting migration. WordPress was politely asking for more memory and being politely ignored.
Once the team fixed the correct pool config and raised the limit to 512M, the export succeeded—but it took ages and spiked worker memory. That led to the second lesson: the export method was loading all orders into PHP arrays. They later replaced it with a paginated export job that streamed rows. Memory stopped being a recurring incident.
Mini-story 2: The optimization that backfired
A different org decided to “optimize” by tightening memory limits across all PHP pools. The logic sounded reasonable: lower limits prevent runaway scripts. They set memory_limit to 128M everywhere and congratulated themselves for enforcing discipline.
For a month, everything looked fine. Then a seasonal campaign launched and editors uploaded lots of high-resolution images. WordPress started generating multiple image sizes, a couple of plugins did “smart compression,” and PDF previews were generated for media kits.
Suddenly uploads failed intermittently with memory exhaustion. Intermittently is the key word: small images worked, large ones died. The support team couldn’t reproduce unless they used the exact same images.
The “optimization” increased failure rate because it removed the burst capacity needed for legitimate workloads. They eventually raised memory for the media-processing pool to 512M and offloaded heavy transforms to a queue-based worker with more headroom.
They kept the lower limit on front-end pools. That part was correct. The backfire was assuming one number fits every workload.
Mini-story 3: The boring but correct practice that saved the day
A larger company ran dozens of WordPress sites behind standardized Nginx and PHP-FPM pools. Nothing fancy. The secret sauce was boring: per-site pools, explicit limits, and metrics on worker RSS.
When a site began throwing memory exhaustion errors after a plugin update, the on-call didn’t debate it in Slack for hours. They checked the pool’s recent RSS distribution and saw worker memory had doubled after the update. That narrowed the search from “WordPress is broken” to “this plugin changed behavior.”
They rolled back the plugin version (also boring), restored service, and then reproduced the issue in staging with the same dataset. The plugin was caching a large API response in an autoload option—so every request paid for it.
Because they already had a checklist for “autoload bloat,” they spotted it quickly, fixed it, and implemented a guardrail: an automated check that alerts when autoloaded options exceed a threshold.
It didn’t win them awards. It did prevent a 3 a.m. firefight. That’s the kind of success you only appreciate after you’ve had the opposite.
Common mistakes: symptom → root cause → fix
1) Symptom: You set WP_MEMORY_LIMIT but the error still shows the old byte value
Root cause: PHP is capped lower than WordPress constants (pool override, php.ini for FPM, or hosting panel mismatch).
Fix: Confirm memory_limit via a web endpoint (Task 9) and change the correct FPM pool config (Task 7), then reload FPM (Task 8).
2) Symptom: WP-CLI commands fail with memory exhaustion, but wp-admin is fine
Root cause: CLI php.ini has a lower memory_limit than FPM.
Fix: Check php --ini and php -r 'ini_get(...)' (Tasks 2–3). Raise CLI memory_limit or use php -d memory_limit=... for specific jobs.
3) Symptom: Only media uploads fail; regular admin pages work
Root cause: Image/PDF processing spikes memory; plugins add extra transforms.
Fix: Increase memory limit for the pool handling uploads; reduce image optimization aggressiveness; offload transforms; verify post_max_size and upload_max_filesize are reasonable (not covered by this error but often co-occurs).
4) Symptom: Random admin pages die after “a while,” especially under traffic
Root cause: FPM pool overcommitted; too many children; swapping; OOM kills; or memory growth across worker lifetime.
Fix: Measure worker RSS (Task 16), set pm.max_children based on memory budget, enable pm.max_requests to recycle workers, and watch for a plugin that accumulates memory in persistent workers.
5) Symptom: After enabling a cache plugin, memory errors get worse
Root cause: Object caching in PHP arrays, autoload bloat, or caching full page fragments in memory per request.
Fix: Inspect autoload size (Tasks 13–15), configure a proper external object cache backend if needed, and avoid caching entire datasets in options.
6) Symptom: Increasing memory_limit fixed it… for a week
Root cause: Underlying data growth or a slow leak pattern (autoloaded options growing, logs stored in options, transient bloat, plugin update).
Fix: Trend autoloaded options size, worker RSS distribution, and error counts. Identify growing tables/options and purge/repair the source.
7) Symptom: You set memory_limit very high and now the server is unstable
Root cause: You raised per-process caps without reducing concurrency. The kernel can’t pay the promised memory bill.
Fix: Reduce FPM pm.max_children, set realistic memory_limit, and use queues for heavy jobs. Unlimited memory is a performance anti-pattern wearing a trench coat.
Joke 2: Setting memory_limit = -1 is like removing the speedometer because you don’t like speeding tickets. The wall still exists.
Checklists / step-by-step plan (permanent fixes)
Step-by-step plan: stabilize, then make it stay fixed
Phase 1: Get wp-admin back (15–30 minutes)
- Find the failing endpoint and culprit in PHP-FPM logs (Task 10). If you don’t know what failed, you’re guessing.
- Disable the suspected plugin via WP-CLI (Task 11) or temporarily move its directory out of
wp-content/plugins. - Confirm actual memory_limit used by the site with the
mem.phpcheck (Task 9), then delete that file. - Raise pool memory_limit conservatively (256M → 512M) if needed (Task 7), reload FPM (Task 8).
Phase 2: Make memory predictable (same day)
- Measure worker RSS and set
pm.max_childrenusing reality, not hope (Task 16). - Add worker recycling with
pm.max_requests(start around 300–1000 depending on code stability). This limits long-lived growth patterns. - Stop autoload bloat: measure size (Task 13), list offenders (Task 14), change autoload for non-critical blobs (Task 15), and fix the plugin behavior.
- Separate pools for heavy workloads (admin/media/import) if you can. Different caps, different concurrency, fewer surprise interactions.
Phase 3: Fix the workload (week 1)
- Reproduce in staging with production-like data. Most “it only fails in prod” memory issues are data-size issues.
- Replace or patch the memory hog. Plugins that load everything into memory should be treated like a production risk, not a feature.
- Stream exports/imports: chunk reads, paginate queries, write output incrementally, and avoid building giant arrays.
- Move heavy jobs off the request path using real cron and a queue/worker approach. Requests should be quick; jobs can be heavy.
Checklist: PHP-FPM pool sizing that won’t OOM your box
- Measure typical and peak RSS per worker (
ps, Task 16). - Decide a memory budget for PHP workers (e.g., 40–60% of RAM after DB, cache, OS).
- Compute
pm.max_children≈ budget / peak RSS (round down). - Set
pm = dynamicwith sanepm.start_servers,pm.min_spare_servers,pm.max_spare_servers. - Set
pm.max_requeststo recycle. - Keep
memory_limithigh enough for legitimate admin actions, but not so high one request can starve the host.
Checklist: WordPress-specific hygiene that prevents memory blowups
- Keep autoloaded options lean; alert when autoload MB grows past a threshold.
- Audit plugins quarterly: remove abandoned ones, replace heavy ones, and delete feature-overlap.
- Use WP-CLI for controlled bulk operations with explicit memory limits.
- Turn WP-Cron into real cron so jobs run on schedule, not during user requests.
- Watch admin-ajax usage; it’s where “just a small report” turns into a 500MB request.
FAQ
1) Is “Allowed memory size exhausted” a WordPress limit or a PHP limit?
It’s a PHP limit. WordPress can request more memory via constants, but PHP enforces the actual cap.
2) I set define('WP_MEMORY_LIMIT','512M'). Why does it still fail?
Because PHP is still capped lower (pool override, php.ini for FPM, or container memory). Verify with a web endpoint (Task 9) and fix the correct pool (Tasks 5–7).
3) What’s a sane memory_limit for WordPress admin?
For a simple site: 256M is often fine. For WooCommerce/page builders/analytics-heavy admin: 512M is common. Above that, treat it as a smell and look for bloat.
4) Should I set WP_MAX_MEMORY_LIMIT higher than WP_MEMORY_LIMIT?
Yes. Front-end requests should be lighter and more predictable. Admin can legitimately need more for updates, media, exports, and dashboards.
5) Can OPcache cause memory exhaustion errors?
OPcache doesn’t count against PHP memory_limit the same way (it uses shared memory), but poor OPcache settings can increase latency and concurrency, indirectly increasing total PHP worker memory pressure.
6) If I increase memory_limit, can that make performance worse?
Yes, if you don’t adjust concurrency. Larger per-worker caps with the same pm.max_children can push the host into swapping or OOM. Tune as a system.
7) Why does it only happen on certain admin pages?
Those pages trigger heavier code paths: report generation, batch operations, media transforms, or plugins that query too much data. Logs (Task 10) usually reveal the file responsible.
8) What’s the fastest safe way to regain access if wp-admin is dead?
Disable the suspect plugin via WP-CLI (Task 11) or move its plugin directory out of place. Then fix the root cause before re-enabling.
9) Can database bloat cause PHP memory exhaustion?
Indirectly, yes. Huge option blobs (especially autoloaded ones) and unbounded queries can pull large result sets into PHP memory. Measure autoload size (Task 13) and fix offenders (Task 14).
10) How do I prevent this from coming back after plugin updates?
Use staging tests with real data, monitor worker RSS trends, alert on autoload MB growth, and enforce plugin governance. The “install anything” phase ends when production starts.
Conclusion: what to do next
If you want this fixed for good, stop treating memory exhaustion as a single setting. It’s a system behavior.
- Today: Use logs to identify the failing endpoint and plugin, verify actual PHP memory_limit for web and CLI, and stabilize with a conservative increase if necessary.
- This week: Measure worker RSS, set PHP-FPM concurrency based on budget, recycle workers, and clean up autoloaded options bloat.
- Ongoing: Treat plugin changes like code changes—test, measure, and roll back quickly. Add alerts for autoload growth and memory error rates.
Do that, and “Allowed memory size exhausted” goes back to what it should be: a rare guardrail, not a recurring calendar event.