You deploy to your usual staging box and the feature flags work. You push the same code to Lambda, or a container with a read-only root filesystem, and the app dies on boot with a cache write failure.
Here is the line from the Eppo PHP quickstart that does it:
use Eppo\EppoClient;
$eppoClient = EppoClient::init(
'<your_api_key>', // SDK key, first arg
'<base_url>', // optional, defaults to the Eppo CDN
$assignmentLogger, // optional
$cache, // optional PSR-16 cache. skip it and FileSystem cache is used
$httpClient, // optional PSR-18, else auto-discovered
$requestFactory, // optional PSR-17, else auto-discovered
);
See $cache. Optional means nobody passes it. The default is a FileSystem cache, which is fine everywhere you tested and fatal on any box where the process cannot write. The error surfaces on boot, before any flag config matters, so the first dead end people chase is the SDK key or the network. It is neither.
The fix is to stop treating those init args as optional in production:
use Eppo\EppoClient;
use Symfony\Component\Cache\Adapter\RedisAdapter;
use Symfony\Component\Cache\Psr16Cache;
$redisCache = new Psr16Cache(RedisAdapter::createConnection('redis://localhost'));
$eppoClient = EppoClient::init(
$_ENV['EPPO_SDK_KEY'], // SDK key first
null, // leave the base URL unset unless you run a custom endpoint
null, // assignment logger, if you have one
$redisCache, // explicit PSR-16 cache, Redis or Memcached in prod
$httpClient, // your own PSR-18 client, not discovery's guess
$requestFactory, // your own PSR-17 factory
);
That last point is the quiet part of the same bug: letting HTTP client discovery pick whatever is installed is fine locally and a lottery in production. Pin it.
The agent-readable version of this, fetchable via curl, lives on Vectle:
https://vectle.com/skills/skl_1TDVbXyxhKSxkxHObep0VQ
(Source: Eppo PHP quickstart, docs.geteppo.com/sdks/server-sdks/php/quickstart)
Top comments (0)