Skip to content

PHP and performance

OPanel runs PHP 7.4 through 8.5 side by side, co-installed on every web server. A site picks its branch independently of every other site on the same server; switching a site’s version just swaps its FPM unit’s binary and nginx upstream — no shared php.ini to fight over. EOL branches (7.4, 8.0, 8.1; 8.2 after 2026-12-31) are flagged in the console, and operators can restrict which branches customers may choose.

Every PHP site gets its own PHP-FPM master, running as that site’s own Unix user inside its sandbox, with its own OPcache. This is the difference between OPanel and a shared php-fpm pool: one site’s opcode cache can never be poisoned or evicted by another’s, and one runaway site cannot starve another’s PHP workers — cgroup limits apply per site, not per server.

A site’s PHP-FPM master stops itself after a period with no requests — it sleeps — and the next request starts it again automatically, with no error and no dropped connection: systemd owns the site’s socket, so requests queue for the moment it takes to start the master, rather than failing. A sleeping site uses no PHP memory at all, which is what lets a small server comfortably host many low-traffic sites.

  • Plans set the default sleep time, in limits.phpSleepMinutes: 0 means the platform default of 15 minutes, -1 keeps PHP always on, and it can go up to 1440 (24 hours).
  • Sites can set a shorter time than their plan allows, or, if the plan includes the “PHP always on” feature, keep their own PHP always on.
  • Cron jobs, WP-CLI, SSH, SFTP and the file manager never need the master, so none of them wake a sleeping site — only an actual request does (including a cron job that fetches the site over HTTP).
  • A busy shop or a site whose very first visitor must never wait should be set to always on.

The console shows each site’s current state (awake/asleep), how long it’s been awake, and its wake history; node-level metrics show total memory saved by sleeping sites.

Every site gets its own Valkey instance, or an ACL user restricted to its own key prefix on a shared pool. Plans set a cache size limit (limits.cacheMB); 0 means no cache.

The edge proxy is written in Go and terminates HTTP/1.1, HTTP/2 and HTTP/3 (QUIC) with automatic, on-demand TLS certificates. Enabling HTTP/3 needs generous kernel UDP buffers; opanel doctor checks for this and warns if the kernel’s limits are too low. Reloads and upgrades of the edge hand the listening sockets to a new process without dropping a connection — normal HTTP requests drain for up to 5 minutes, HTTP/3 (which cannot migrate mid-connection) for up to 5 seconds, after which browsers reconnect over HTTP/2.

Customers adjust a site’s own PHP settings — memory_limit, upload_max_filesize, max_execution_time and more — from an allow-list, capped by ceilings the plan sets:

Plan limit Governs
phpWorkers Maximum FPM worker processes for the site
phpMemoryLimitMB Ceiling for the site’s memory_limit
maxUploadMB Ceiling for upload_max_filesize / post_max_size
maxExecutionSeconds Ceiling for max_execution_time
phpSleepMinutes Default and shortest sleep time the site may set

Operators can also disable specific PHP functions cluster-wide (disableFunctions in platform settings) — useful for functions you never want any tenant calling, regardless of plan.

Every plan carries a full set of per-subscription and per-site limits, enforced by cgroups: cpuPercent, memoryMB, tasks (process/thread ceiling) and ioWeight. See Plans for the complete list and sensible defaults.