1. What PHP 8.4 and Valkey 8 actually changed
Two releases from late 2024 are now standard on many PHP stacks, and both are often oversold.
Valkey: the open-source continuation of Redis
Valkey was forked from Redis 7.2.4 in March 2024, after Redis moved away from its BSD licence, and is developed under the Linux Foundation. It speaks the same protocol, so WordPress and Laravel cache drivers written for Redis work unchanged. The milestones relevant to a PHP host are:
- Valkey 8.0 (September 2024): reworked I/O threading, so reading requests from the network and writing replies can run on separate threads while commands still execute on the main thread; dual-channel replication for faster, lighter full syncs; and per-slot metrics for cluster users.
- Valkey 8.1 (2025): a new hashtable implementation that reduces per-key memory overhead. If you read that “Valkey 8 uses less memory”, this is mostly the release that delivered it.
- Valkey 9.0 (late 2025): further cluster-focused features. For a single-node object cache, 8.1 or later gives you the memory improvements; check which version your host actually runs.
Redis itself added an AGPLv3 licensing option with Redis 8 in 2025, so both projects remain available. For a WordPress or Laravel object cache, the choice rarely affects application code.
PHP 8.4: a rebuilt JIT that is off by default
PHP 8.4 (November 2024) moved the JIT compiler onto a new intermediate-representation (IR) framework. It also changed the defaults: opcache.jit now defaults to disable and opcache.jit_buffer_size to 64M. In other words, upgrading to PHP 8.4 does not turn the JIT on. You have to set opcache.jit=tracing (or another mode) yourself. PHP 8.5 followed in November 2025; the tuning approach below applies to both.
2. Set expectations: what the JIT can and cannot speed up
OPcache, which caches compiled bytecode, is what makes PHP fast for web applications, and it has been essential for years. The JIT goes further by compiling hot code paths to machine code, which pays off for CPU-heavy work: maths, image manipulation, parsers, long loops.
A typical WordPress, WooCommerce or Laravel request spends much of its time elsewhere: waiting on MySQL, talking to the object cache, building templates and running framework code that the JIT struggles to optimise. The PHP JIT RFC itself reported large gains on synthetic CPU tests and little change for typical web applications. So treat the JIT as a free, small, workload-dependent gain that you verify, not as a headline number you can plan capacity on.
The object cache is usually the bigger lever. On a WooCommerce store, cart and checkout pages cannot be served from a full-page cache, so every request runs PHP; a persistent Valkey or Redis object cache removes repeated database queries for options, sessions and product data.
3. Sizing memory: PHP-FPM workers, OPcache and Valkey
Memory is the resource that most often caps a PHP server. Work it out in three parts.
PHP-FPM workers
pm.max_children ≈ memory available for PHP ÷ average worker memory (RSS)
Illustrative example for an 8 GB server: reserve 1 GB for the operating system, 2 GB for MySQL or MariaDB, 1 GB for Valkey and 0.5 GB for OPcache plus the JIT buffer. That leaves 3.5 GB, or 3,584 MB, for PHP. If your workers average 80 MB each, 3,584 ÷ 80 ≈ 44 workers. Measure your real average with the ps command in Section 6; WooCommerce sites with many plugins often run heavier workers than a lean Laravel API.
OPcache and the JIT buffer
OPcache memory and the JIT buffer are shared by all workers in a pool; they are not multiplied per worker. Size opcache.memory_consumption so that opcache_get_status() shows free memory after a full warm-up, and set opcache.max_accelerated_files above the number of PHP files in your codebase.
Valkey
Valkey memory ≈ number of keys × (key size + value size + per-key overhead)
Illustrative example: 500,000 cached objects with 60-byte keys, 1,000-byte serialized values and roughly 50 bytes of per-key overhead need about 500,000 × 1,110 = 555,000,000 bytes, or about 555 MB. Set maxmemory with headroom for fragmentation (for example 768 MB in this case) and use an eviction policy such as allkeys-lru when Valkey is used purely as a cache. Then check reality with INFO memory, because serialization format and compression change value sizes a lot.
4. Estimating request throughput before you load-test
Two limits apply at once, and the lower one wins:
- Worker limit ≈ number of workers ÷ wall-clock time each request holds a worker
- CPU limit ≈ number of vCPUs ÷ CPU time each request consumes
Illustrative example: 44 workers on a 4-vCPU server, with uncached requests that hold a worker for 0.12 seconds of wall-clock time and use 0.06 seconds of CPU. The worker limit is 44 ÷ 0.12 ≈ 367 requests per second; the CPU limit is 4 ÷ 0.06 ≈ 67 requests per second. The CPU limit wins, so adding workers would not help. Now suppose the JIT trimmed CPU time by a hypothetical 5%, to 0.057 seconds: the CPU limit rises to about 70 requests per second. If instead an object cache cut database waiting so requests held workers for less time, the worker limit would rise, but the server would still be CPU-bound. This is why measuring CPU time per request on your own pages matters more than any published JIT percentage.
5. Managed platform or self-managed VPS?
| Setup | PHP version and OPcache/JIT | Object cache | Who handles updates and security | Best for |
|---|---|---|---|---|
| Managed cloud platform (e.g. Cloudways) | PHP version selectable from the panel; some php.ini and PHP-FPM settings exposed, others only via support | Redis-compatible cache available as a server service; check whether it runs Redis or Valkey and which version | The platform, for the stack; you, for the application | Agencies and store owners who want WordPress/WooCommerce/Laravel without running Linux |
| Self-managed VPS (e.g. UltaHost) | Full control: any PHP build, any ini setting, JIT on or off | Install the Valkey version you want and configure it yourself | You | Developers comfortable with Linux who want the latest versions and every setting |
On managed platforms, check which add-ons cost extra. CDN tiers and commercial plugins such as Object Cache Pro may be paid add-ons or limited to certain plans, and resource limits (RAM, PHP-FPM workers) scale with the server size you pick, so test on the plan size you intend to run in production, not on the entry tier.
6. Configuration and measurement commands
# 1. /etc/php/8.4/fpm/conf.d/10-opcache.ini (self-managed servers)
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=32
opcache.max_accelerated_files=20000
; only disable timestamp checks if your deploy script resets OPcache
opcache.validate_timestamps=0
; the JIT is off by default in PHP 8.4; turn it on explicitly
opcache.jit=tracing
opcache.jit_buffer_size=64M
# 2. Confirm what PHP-FPM (not the CLI) actually loaded
php-fpm8.4 -i | grep -E 'opcache.jit|opcache.memory_consumption'
# 3. Average PHP-FPM worker memory (RSS)
ps --no-headers -o rss -C php-fpm8.4 | \
awk '{s+=$1; n++} END {printf "%.0f MB average over %d processes\n", s/n/1024, n}'
# 4. Valkey settings in valkey.conf for a single-node object cache
# io-threads 4
# maxmemory 768mb
# maxmemory-policy allkeys-lru
# 5. Inspect real Valkey memory use
valkey-cli INFO memory | grep -E 'used_memory_human|mem_fragmentation_ratio'
valkey-cli --bigkeys
# 6. Load-test a staging copy of your site, JIT off and then JIT on
wrk -t4 -c64 -d60s https://staging.example.com/shop/
Run step 6 twice, once with opcache.jit=disable and once with tracing, restarting PHP-FPM in between, and compare requests per second and CPU usage on the same pages. Use pages that reflect real traffic, including uncached ones such as cart and checkout. For the cache server itself, valkey-benchmark shows the raw capacity of Valkey, but pipelined synthetic numbers are far higher than what a PHP application issuing one command at a time will ever ask of it.
Caveats
- JIT compatibility. Some extensions and debuggers (for example Xdebug) disable or conflict with the JIT. Keep it off on development machines where you debug, and test on staging before enabling it in production.
- Managed platforms limit tuning. You may not be able to set every OPcache, JIT or Valkey option yourself, and supported versions arrive on the platform’s schedule, not on release day.
- A self-managed VPS means self-managed security. Firewall, SSH hardening, PHP and Valkey updates, backups and monitoring are all your responsibility.
- The examples are examples. Worker memory, CPU time per request and cache value sizes vary enormously between sites. Replace every number in Sections 3 and 4 with your own measurements.
7. Verdict
- Enable OPcache properly first, then add a persistent Valkey or Redis object cache. On dynamic WooCommerce and Laravel workloads, these two usually matter far more than the JIT.
- Turn the PHP 8.4 JIT on deliberately and measure it. It is free to try, but the gain depends entirely on how CPU-bound your code is.
- Choose managed hosting if you want the stack patched and tuned for you and can accept some limits on settings. Choose a VPS if you need the newest Valkey and PHP versions and full control over every ini line.
Managed cloud hosting for WordPress, WooCommerce and Laravel
Verified technical partner. Direct secure access.
Explore Cloudways managed hosting →Self-managed NVMe VPS with root access
Verified technical partner. Direct secure access.
See UltaHost VPS plans →