When a web request writes a cached value which cron cannot read, check the PHP runtime and value format on both sides. Reaching the same Redis service is not enough. I make the serialisation format explicit and test a value written and read in both directions.
“Installed on the server” is not precise enough
A machine can have several PHP versions and separate configurations for command-line PHP and PHP-FPM. An extension available to one is not automatically loaded by the other. Choosing whichever serializer happens to be installed can therefore give the same key two incompatible meanings.
I now check the actual binary used by the scheduler, its loaded configuration and extensions, alongside the runtime serving the website. A shell’s default php command tells me about that shell; it does not prove what a web worker uses.
php --version
php --ini
php --modules
These are read-only checks. For the web side, I use a restricted diagnostic rather than publishing a PHP information page containing the server’s configuration.
Pick a format deliberately
For this cache I chose a format available in every supported PHP context. A specialised serializer can be a sensible performance choice, but then it becomes a deployment requirement which every writer and reader must meet. It should not change silently depending on where a request happens to run.
The stored entry also needs enough structure to recognise an unexpected format. A value the application cannot decode should be treated as a miss and rebuilt from its source. It must never be mistaken for valid page output or partly interpreted data.
Plan the transition
Changing the format does not change values already in Redis. I prefer a versioned envelope or namespace, with old entries expiring naturally, when that is practical. A tolerant reader can also reject the previous format and rebuild on demand. Either way, the transition temporarily increases source reads and needs capacity.
A full flush is not my automatic first move, especially on a shared service. It can replace a quiet compatibility problem with a very loud burst of database work. I first decide which keys belong to the application and whether gradual replacement is sufficient.
Test across the boundary
The useful test is a round trip: write from a web request, read from the scheduled-job runtime, then reverse it. Include arrays, false values, expiry and deletion. A successful Redis connection test cannot establish any of those things.
This is a small contract to document, but it saves a lot of head-scratching when a cache looks warm in one place and empty in another.