Increasing PHP memory_limit keeps legitimate workloads such as imports, image processing, archive creation, report generation, and queue jobs from failing with Allowed memory size exhausted when a request needs more RAM than the current cap allows. Raising it carefully also avoids turning one runaway request into unnecessary memory pressure across every worker.
The effective limit comes from the PHP runtime that actually serves the request, not from whichever binary appears first in PATH. The main php.ini sets the baseline, additional scanned .ini files can change it, PHP-FPM pools can override it with php_value[] or php_admin_value[], CGI or FastCGI deployments can apply per-directory .user.ini files, and Apache module deployments can set it again with php_value or php_admin_value directives in the web-server configuration.
The example flow below uses PHP-FPM on Ubuntu or Debian because that packaging layout is common, but the same directive applies elsewhere once the winning configuration layer is identified. memory_limit accepts shorthand sizes such as 256M, -1 removes the cap entirely, and current PHP documentation notes that it should generally stay larger than post_max_size when large POST bodies or uploads are involved. When the effective change is in .user.ini, remember that the default user_ini.cache_ttl is 300 seconds, so the new value may not appear immediately.
Steps to increase PHP memory limit:
- Create a temporary diagnostic script in the same document root or application path that needs more memory.
$ sudo tee /var/www/billing-portal/current/public/php-runtime-probe-c7f29e.php >/dev/null <<'PHP' <?php header('Content-Type: text/plain'); printf("SAPI=%s\n", PHP_SAPI); printf("Loaded php.ini=%s\n", php_ini_loaded_file() ?: 'none'); printf("memory_limit=%s\n", ini_get('memory_limit')); printf("user_ini.filename=%s\n", ini_get('user_ini.filename')); printf("user_ini.cache_ttl=%s\n", ini_get('user_ini.cache_ttl')); PHPKeep the script name unguessable or place it in a restricted path when the site is public, and remove it after the new limit is confirmed because it exposes runtime details.
- Request the diagnostic script through the same URL path, virtual host, or PHP-FPM pool that serves the application.
$ curl -s https://billing-portal.example.net/php-runtime-probe-c7f29e.php SAPI=fpm-fcgi Loaded php.ini=/etc/php/8.3/fpm/php.ini memory_limit=128M user_ini.filename=.user.ini user_ini.cache_ttl=300
If the response shows apache2handler, follow the Apache configuration tree for the effective change. If it shows fpm-fcgi or cgi-fcgi, check for PHP-FPM pool overrides and per-directory .user.ini files before assuming the main php.ini is the last layer.
Related: How to find PHP configuration files
- Search PHP-FPM pool files for an active memory_limit override before changing the main php.ini file.
$ sudo grep -REn '^[[:space:]]*php(_admin)?_value\[memory_limit\]' /etc/php/8.3/fpm/pool.d
No output means the pool files are not currently overriding memory_limit. If the command returns a line such as php_admin_value[memory_limit] = 256M, change that file instead because it wins for that pool, and PHP does not let ini_set() override an admin-level value.
- Search the request path for per-directory .user.ini files when the site runs through CGI or FastCGI and the previous step finds no pool override.
$ find /var/www/billing-portal/current/public -name .user.ini -print /var/www/billing-portal/current/public/.user.ini
PHP reads .user.ini only for CGI or FastCGI SAPIs and walks upward from the requested script directory to the document root. A nearer file can override only that part of the site, and changes are re-read on the reported user_ini.cache_ttl interval instead of immediately.
- Back up the file that currently controls the effective limit.
$ sudo cp /etc/php/8.3/fpm/php.ini /etc/php/8.3/fpm/php.ini.bak-$(date +%Y%m%d%H%M%S)
Back up the pool file instead when the previous step found an active pool-level override. If the narrowest safe change is a new .user.ini file in the application path, keep the change isolated there instead of raising the global limit for every site.
Keep the timestamped backup until the new limit is confirmed from the same request path.
- Open the file that actually wins for the request.
$ sudoedit /etc/php/8.3/fpm/php.ini
Open the discovered pool file instead of php.ini when the active value comes from /etc/php/8.3/fpm/pool.d/*.conf, or open the application's .user.ini file when the runtime is using a per-directory override.
Related: How to find PHP configuration files
- Set memory_limit in the active layer to the smallest value that still fits the workload.
; In php.ini or .user.ini memory_limit = 256M ; In a PHP-FPM pool file php_admin_value[memory_limit] = 256M ; In Apache module configuration php_value memory_limit 256M
Use the existing syntax for the layer being changed. Current PHP behavior also allows application code to raise memory_limit with ini_set() when the directive is not locked by php_admin_value or php_admin_flag, but a persistent site-level change belongs in the effective configuration layer instead of the application code path.
Keep memory_limit larger than post_max_size for large form posts or uploads, and reserve memory_limit = -1 for tightly controlled maintenance jobs because it removes the cap entirely.
- Test the PHP-FPM configuration before reloading the service when the change is in php.ini or a pool file.
$ sudo php-fpm8.3 -t [25-Mar-2026 23:05:50] NOTICE: configuration file /etc/php/8.3/fpm/php-fpm.conf test is successful
Use the matching binary name such as php-fpm or php-fpm8.4 when the installed package uses a different branch. If the only change is in .user.ini, skip this syntax test and re-check the site after the reported user_ini.cache_ttl interval.
Do not reload the service until the configuration test succeeds.
- Reload the runtime that serves the application so new workers pick up the updated limit.
$ sudo systemctl reload php8.3-fpm
Reload Apache instead, for example with sudo systemctl reload apache2, when the diagnostic script reported apache2handler. If the change lives only in .user.ini, re-check after the cache interval shown by the probe because that file is re-read on the user_ini.cache_ttl schedule.
- Request the same diagnostic script again and confirm the higher limit from the site runtime.
$ curl -s https://billing-portal.example.net/php-runtime-probe-c7f29e.php SAPI=fpm-fcgi Loaded php.ini=/etc/php/8.3/fpm/php.ini memory_limit=256M user_ini.filename=.user.ini user_ini.cache_ttl=300
If the old value still appears, check for a later PHP-FPM pool override, a nearer .user.ini file, a web-server PHP_VALUE or PHP_ADMIN_VALUE FastCGI parameter, or an Apache php_value or php_admin_value override in the virtual host or directory configuration.
Related: How to find PHP configuration files
- Remove the temporary diagnostic script after the new limit is confirmed.
$ sudo rm /var/www/billing-portal/current/public/php-runtime-probe-c7f29e.php
Leaving the file in place keeps the site's SAPI, loaded configuration path, and active runtime limit exposed to anyone who can reach the URL.
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.
