The most common LiteSpeed ticket after a cPanel cutover is not a performance complaint. It is "I changed memory_limit in the MultiPHP INI Editor and nothing happened." That is by design: since LSWS 5.3, PHP runs in detached mode, so lsphp processes outlive web server restarts and keep the php.ini they loaded at startup.
This guide covers how LiteSpeed Enterprise runs PHP on a cPanel server, how to restart PHP per account or server-wide without dropping traffic, and which LSAPI settings are worth changing on a dense shared box. It assumes LSWS is already serving traffic. If not, start with installing LiteSpeed on cPanel.
How LSWS runs PHP on cPanel
LSWS does not use PHP-FPM or mod_lsapi on cPanel. It reads the MultiPHP Manager (or CloudLinux PHP Selector) assignment for each domain and launches the matching ea-phpXX or alt-phpXX binary over the LSAPI protocol. Two independent settings decide how those processes behave.
Process mode — how PHP processes are created:
| Mode | Parent processes | OPcache | Custom php.ini | Typical use |
|---|---|---|---|---|
| ProcessGroup | One per user | Per user | Yes | Default for shared hosting |
| Worker | None | None | Yes | Legacy, very low-traffic accounts |
| Daemon | One server-wide | Shared across users | No | Single-tenant servers only |
Detached mode — whether PHP survives an LSWS restart. It layers on top of the process mode and is enabled by default on control panel installs.
For shared hosting, ProcessGroup plus detached is the right combination. Each account gets its own parent lsphp process holding a warm OPcache, and children are forked from it instead of spawned from scratch. Daemon mode is faster on paper, but a single shared OPcache across all users is a cross-tenant risk and breaks per-user php.ini. Don't use it on a box with more than one customer.
Restart PHP for a single account
When a customer changes a PHP setting, restart only their PHP. Touch the restart marker in their home directory:
touch /home/exampleuser/.lsphp_restart.txt
The file's timestamp is the signal. On the next request, LSWS sees a newer timestamp than its running parent, stops it, and starts a fresh one with the new php.ini. Touch the file again every time you need another restart — it doesn't matter that it already exists.
Confirm the new value took effect:
sudo -u exampleuser /opt/cpanel/ea-php83/root/usr/bin/php -i | grep memory_limit
curl -s https://example.com/phpinfo-check.php | grep -i memory_limit
The CLI check only proves the ini file is correct. The curl against a temporary phpinfo() page proves the web-facing lsphp picked it up. Delete that file afterwards.
On CloudLinux servers, touch /home/exampleuser/mod_lsapi_reset_me works too. LSWS honours the mod_lsapi marker for compatibility, so existing customer docs written for mod_lsapi keep working after a switch.
Restart PHP server-wide
After a server-level change, such as an EasyApache PHP update, a global php.ini edit, or a new PHP extension, restart every account's PHP. There are two ways to do it.
Gradual restart (preferred)
touch /usr/local/lsws/admin/tmp/.lsphp_restart.txt
Each handler restarts the next time it's used. Busy accounts pick up the change within seconds. Idle accounts pick it up on their next hit. There is no thundering herd of 300 parents rebuilding OPcache at the same moment. This is the same as Actions → Restart Detached PHP Processes in the LSWS WebAdmin console.
Immediate restart
pkill lsphp
Every PHP process dies immediately, including requests in flight. Use this only when you need a clean slate right now — for example after a PHP security update where a vulnerable binary must not keep serving, or when lsphp processes are stuck and a graceful restart isn't recycling them.
/usr/local/lsws/bin/lswsctrl restart does not restart PHP in detached mode. That is the single most common misdiagnosis: the admin restarts LiteSpeed, sees no change, and assumes the ini file is wrong.
Tune the LSAPI process limits
The defaults are sized for a general-purpose server. On shared hosting the numbers that matter are how many children each account can fork and how long idle processes stay alive.
Server-level PHP settings live in the WebAdmin console under Configuration → Server → PHP. Per-process LSAPI behaviour is set with environment variables on the lsphp external app.
| Variable | Default | What it controls |
|---|---|---|
LSAPI_CHILDREN | 35 | Max children per parent. 1 switches to Worker mode |
LSAPI_MAX_REQS | 10000 | Requests before a child exits, which caps memory leaks |
LSAPI_MAX_IDLE | 300 s | How long an idle child waits before exiting |
LSAPI_MAX_IDLE_CHILDREN | CHILDREN / 3 | Idle children kept warm |
LSAPI_MAX_PROCESS_TIME | 3600 s | Hard kill for a single runaway request |
LSAPI_PGRP_MAX_IDLE | forever | How long an idle parent (and its OPcache) lives |
LSAPI_SLOW_REQ_MSECS | 0 (off) | Logs requests slower than this |
On a dense box with a few hundred mostly idle accounts, three changes pay off:
- Set
LSAPI_PGRP_MAX_IDLEto something like1800. By default an account that got one request last week still holds a parent and its OPcache segment in memory. Letting idle parents exit reclaims that RAM, and the first request after half an hour of silence costs one cold start. - Lower
LSAPI_MAX_PROCESS_TIMEto300. No legitimate shared-hosting web request runs for an hour, but a stuck one holds a child slot the whole time. - Turn on
LSAPI_SLOW_REQ_MSECS=5000while you're investigating load. Slow requests are written to the LSWS error log with the script path, which is faster than attachingstraceto guess.
PHP suEXEC Max Conn caps concurrent PHP connections per account. It is the real per-customer concurrency limit, and it's also per LSWS worker process: two workers with a value of 10 allow 20 lsphp processes for that account. Set it with that multiplication in mind, not as if it were a server total.
CloudLinux and LVE limits
On CloudLinux, every forked child counts against the account's NPROC and entry process (EP) limits. If PHP suEXEC Max Conn is higher than the LVE EP limit, the customer hits a 508 Resource Limit Is Reached error before LSWS ever queues the request. Keep suEXEC Max Conn at or slightly under EP, and keep NPROC comfortably above both. The same arithmetic is covered in more depth in the mod_lsapi tuning guide, and it applies unchanged to LSWS.
Per-user php.ini and .user.ini
cPanel's MultiPHP INI Editor writes a php.ini into the account's docroot or home. In ProcessGroup mode, each account's parent reads its own ini at startup, so per-user overrides work. They just need the restart described above.
.user.ini files are not read by lsphp by default. If customers are used to them from PHP-FPM hosting, enable support by setting the environment variable on the lsphp external app:
LSPHP_ENABLE_USER_INI=on
This needs PHP LSAPI 6.10 or newer, which every current ea-php build ships. Without it, WordPress plugins that drop a .user.ini to raise upload_max_filesize silently do nothing, and the customer blames the plugin.
Troubleshooting quick reference
- Changed php.ini, no effect → touch
~/.lsphp_restart.txtfor that user. - Updated a PHP version via EasyApache, old version still in
phpinfo()→ touch/usr/local/lsws/admin/tmp/.lsphp_restart.txt. - Hundreds of idle
lsphpparents eating RAM → setLSAPI_PGRP_MAX_IDLE. - Random 503s under load on one account → suEXEC Max Conn is too low for that account, or it has hit the LVE EP limit. Check LVE Manager statistics first.
.user.iniignored →LSPHP_ENABLE_USER_INI=on.
Why are my php.ini changes not taking effect on LiteSpeed?+
How do I restart PHP on a LiteSpeed cPanel server?+
Does restarting LiteSpeed restart PHP?+
Should I use ProcessGroup or Daemon mode for shared hosting?+
Does LiteSpeed support .user.ini files?+
Next steps
- Put LSCache in front of PHP so most requests never reach
lsphp— see enable LSCache for WordPress on cPanel. - Size your LVE limits against these PHP settings with CloudLinux LVE tuning.
- Weighing LSWS against Apache with PHP-FPM? Read PHP handlers on cPanel compared, then pick a tier on the LiteSpeed license page.