Two layers sit in front of the database:
- An in-request memo — always on. It lives for one request or one queued job: it’s bound scoped in the container and also dropped when a queue job starts or Octane receives a request, so a long-running worker never keeps serving a value another process has since changed.
- A persistent cache — options.cache.enabled, on by default — in any Illuminate cache store. Writes update it and deletes drop the entry, so every process sees a change from its next request or job on.
A read checks the memo, then the persistent store, then the database (falling back to default()). set() writes the new raw value to both layers and forget() removes it from both — there is nothing else to invalidate.
Raw values, never casts
Both layers hold the raw stored string, never the cast value: an encrypted option stays ciphertext in the cache, and nothing but scalars is serialized, so Laravel’s unserialize hardening (cache.serializable_classes) can’t turn a cached Collection or Carbon into __PHP_Incomplete_Class. Each read casts the raw value.
OPTIONS_CACHE_ENABLED=true
OPTIONS_CACHE_STORE=redis # null = the app’s default store
OPTIONS_CACHE_TTL=600 # seconds; null caches forever
OPTIONS_CACHE_PREFIX=options
OPTIONS_CACHE_TAG=optionsFlushing
Options::flushCache(); // clears the in-request memo and the persistent entriesphp artisan options:clear-cacheflushCache() and options:clear-cache work on every store. Each cache key embeds a generation token and a flush moves to a new one, so no old entry is read again — by other processes too, from their next request or job on. A taggable store (Redis, Memcached) also deletes the old entries at once; on any other store (file, database) they expire by cache.ttl, and with a null TTL they stay until the store evicts them.
Cache keys
Persistent keys follow {prefix}:{generation}:options:{key}:{scope}, where scope is global or an md5 of the length-prefixed owner morph class and owner key — so no two owners can share a key. The generation itself is stored under {prefix}:generation.
Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.