Bali, Indonesia
Insights

Upgraded the PHP Version and memory_limit Went Back to 128M? Verify the Loaded php.ini

October 31, 2026
0:00
You switch a site to a newer PHP version, either through a version selector in the control panel or by installing a fresh FPM package on a VPS. A day later an import or a plugin update fails with Allowed memory size of 134217728 bytes exhausted. You check memory_limit and it reads 128M, even though you raised it to 512M a long time ago. Nothing reverted your change. The new version never read the file you edited. This guide walks through verifying which configuration PHP actually loads, from the shell and from the web server. It then covers finding where the old values were set and recreating them for the new version.
When several PHP versions live on one server, each one is a separate installation. Each has its own main php.ini file, its own directory of extra .ini files that it scans at startup, and, if it runs under PHP-FPM (the FastCGI Process Manager that most Nginx and many Apache setups use), its own pool configuration. Editing the php.ini for one version does nothing for another. On top of that, PHP reads different files depending on the SAPI, the server API it runs under. The command-line binary (CLI) and the FPM service usually have separate php.ini files even within the same version. On a Debian or Ubuntu server with packaged PHP, you typically see both /etc/php/8.2/cli/php.ini and /etc/php/8.2/fpm/php.ini. Version 8.2 here is only an illustrative example. A value set in one file is invisible to the other. After the main file, a value can be overridden in several places. The order roughly goes like this:
  1. The main php.ini, then any files in the scan directory (conf.d), loaded in alphabetical order.
  2. FPM pool directives such as php_value[memory_limit] or php_admin_value[memory_limit].
  3. Per-directory files: .user.ini for FPM and CGI, or php_value lines in .htaccess for handlers that support them, such as mod_php or LiteSpeed LSAPI.
  4. ini_set() calls in the application itself, unless the pool locked the value with php_admin_value.
If none of these set memory_limit, PHP falls back to its built-in default, which is 128M. That is why the value seems to snap back to 128M after an upgrade. It isn't a reset. It's the default showing through because nothing in the new version's chain mentions your setting.
The first stop is php --ini. It prints the directory PHP looks in for php.ini, the file it actually loaded, the scan directory, and every extra .ini file it parsed. The catch is that plain php runs whatever binary is first on your PATH, which may not be the version the site uses. Ask the versioned binary directly.
BASH
# Which version is the default php, and what does it load?
php -v
php --ini

# Ask the version the site actually uses (binary names vary by distro and panel)
php8.2 --ini
php8.2 -i | grep -E '^(memory_limit|upload_max_filesize|post_max_size) '

# The FPM binary has its own php.ini; -i prints its view (confirm with --help)
php-fpm8.2 -i | grep -E '^(Loaded Configuration File|memory_limit) '
In the php --ini output, the line to look at is Loaded Configuration File. If it says (none), that version found no php.ini at all and is running purely on built-in defaults plus whatever sits in the scan directory. If it points to a file, that file is what you should be editing, not the one you remember from the old version. The php -i lines show two values per directive, for example memory_limit => 128M => 128M. The first is the local value and the second is the master value. For CLI they are almost always the same. Keep in mind that none of this reflects FPM pool directives or .user.ini files. The FPM binary's -i output shows which php.ini the FPM SAPI loads, but pool settings are applied per pool when a worker starts, so they don't appear there. A very common support-desk mix-up starts exactly here. Someone checks memory_limit over SSH, sees 512M, concludes PHP is fine, and the website is actually served by a different version through FPM with a different config.
The only reliable answer to what the site sees comes from a request that goes through the same handler as the site. A small temporary script is enough. It is less noisy than a full phpinfo() page and exposes less information.
PHP
<?php
// Temporary diagnostic. Delete this file immediately after use.
header('Content-Type: text/plain');
echo 'SAPI: ', PHP_SAPI, PHP_EOL;
echo 'Version: ', PHP_VERSION, PHP_EOL;
echo 'Loaded php.ini: ', php_ini_loaded_file() ?: 'none', PHP_EOL;
echo 'Scanned ini files: ', php_ini_scanned_files() ?: 'none', PHP_EOL;
foreach (['memory_limit', 'upload_max_filesize', 'post_max_size', 'max_execution_time'] as $key) {
    echo key, ': ', ini_get(key), PHP_EOL;
}
Save it in the site's document root under a hard-to-guess name, open it in a browser or fetch it with curl, and then delete it. SAPI should read fpm-fcgi for PHP-FPM, litespeed for LSAPI, or apache2handler for mod_php. If the version or the SAPI isn't what you expected, the problem is the handler mapping, not the ini values. Fix that first. A word of caution. Diagnostic scripts, and phpinfo() pages in particular, reveal file paths, loaded extensions, and sometimes environment variables. Never leave one in a public directory. If you do use phpinfo(), look at the Local Value and Master Value columns for each directive. When they differ, something at the directory or script level changed the value after the main configuration loaded. That usually means a .user.ini, an .htaccess line, or ini_set() in the application.
Once you know the new version is missing the setting, find out where the old version got it. It may have been php.ini, a custom file in conf.d, the FPM pool, or a per-directory file. Each of those needs a different fix. Searching the old version's whole configuration tree is faster than guessing.
BASH
# Debian/Ubuntu layout; adjust version numbers and paths for your setup
grep -RnE 'memory_limit|upload_max_filesize|post_max_size' /etc/php/8.1/
grep -RnE 'memory_limit|upload_max_filesize|post_max_size' /etc/php/8.2/

# Per-directory overrides inside site roots
find /var/www \( -name '.user.ini' -o -name '.htaccess' \) -exec grep -l 'memory_limit' {} +
The grep output includes commented-out lines, which start with a semicolon in php.ini files. Ignore those. Hits under fpm/pool.d/ point to pool directives that need to be recreated in the new version's pool file. A hit in a .user.ini or .htaccess file is a different case. If that file is still in place and still being ignored, the new handler may not read that format. For example, php_value lines in .htaccess do nothing under PHP-FPM. Control panels add one more layer. They usually keep per-version files in their own directories, and their INI editors may write to php.ini, a conf.d file, or the pool, depending on the panel. Instead of memorizing those paths, run that version's binary with --ini, or use the web check above. Both tell you exactly which files are in play. If a value appears to be right in the file but still doesn't show up, check two things. First, FPM must be reloaded before it picks up php.ini or pool changes. Second, .user.ini files are cached according to user_ini.cache_ttl, which defaults to 300 seconds, so edits there can take a few minutes to apply.
It's tempting to copy the old php.ini over the new one. Usually that's a bad idea. Directives get removed or renamed between versions, extension lines may refer to modules that aren't installed for the new version, and you lose any defaults the new package shipped with. A cleaner approach is to keep your overrides in a small drop-in file and leave the packaged php.ini alone. On a Debian-style layout, that could be a file named 99-custom.ini in /etc/php/8.2/fpm/conf.d/, containing only the lines you changed, such as memory_limit = 512M. The 99- prefix makes it load last, so it wins over earlier files. Add a matching file under the cli tree if command-line tools like WP-CLI or cron jobs need the same values. If the old pool used php_admin_value or php_value lines, copy those into the new version's pool file instead, because pool directives don't belong in php.ini. Then reload the service. On Debian and Ubuntu that is typically sudo systemctl reload php8.2-fpm, and the service name varies on other setups. After the reload, run the web check again. It's the one that counts. While you're at it, keep post_max_size equal to or larger than upload_max_filesize, since the whole POST body has to fit. Also remember that the web server can reject large uploads before PHP ever sees them, for example through Nginx's client_max_body_size. Raising PHP limits won't fix that. The practical habit is short. After any PHP version switch, check php --ini for the exact version binary, confirm the live values through a request to the site, and keep custom settings in one small, clearly named file per version. Then the next upgrade becomes a five-minute copy of a known file, not an afternoon spent wondering why memory_limit went back to 128M.