Laravel cache, sessions, and Redis integration
Status: Complete. Last reviewed 2026-08-27.
Precise mental model
Section titled “Precise mental model”Laravel presents cache and session contracts over several stores, but the common API does not make their operational guarantees identical. A cache is disposable derived state: a miss, eviction, or flush must affect performance or freshness, not correctness or authorization. A session is server-side continuity for a browser conversation and may contain authentication, CSRF, flash, and workflow state; losing it is a user-visible event. Redis is a data system that can back cache, sessions, queues, rate limiters, and locks. Sharing one deployment couples their capacity and failure modes.
Choose the store from the required guarantee. Laravel 13 fresh applications default to the database cache store. File storage works on one host but is normally unsuitable for horizontally scaled coordination. Database storage can be operationally simple but adds database load. Redis enables shared low-latency state and atomic primitives, while requiring explicit memory, persistence, failover, connection, and eviction decisions.
Cache keys, lifetime, and invalidation
Section titled “Cache keys, lifetime, and invalidation”Cache::remember() implements cache-aside: read the cache; on a miss compute from the source of truth and store the result. It does not serialize concurrent misses. A hot key that expires can therefore send many requests to the database at once. Cache::flexible() supports stale-while-revalidate: serve fresh data in the first interval, serve stale data and defer refresh in the second, then recompute synchronously after both intervals. This trades bounded staleness for smoother latency; refresh still needs observability and, for expensive work, coordination.
A production key is a compact dependency declaration. Include every dimension that changes the result: resource identity, tenant, locale, role or permission version where representation differs, algorithm/schema version, and sometimes deployment version. Never cache an authorized response under only project:{id} if two actors can see different fields. Prefer caching authorization-neutral records and applying current policy after retrieval. If authorization decisions are cached, use short lifetimes and explicit invalidation on membership changes.
TTL is a maximum permitted age, not an invalidation strategy. Cache-aside commonly combines event-driven invalidation after a successful database commit with a finite TTL as repair. Versioned keys can make broad invalidation cheap. Cache tags provide grouped invalidation only on supporting drivers and introduce namespace bookkeeping; do not assume tags are portable. flush() may clear the entire backing store regardless of the application’s key prefix, so it is a dangerous substitute for scoped invalidation.
“Forever” means no requested expiry, not permanent storage. A backend can evict data, an operator can flush it, and a deployment can change prefixes. Negative caching can protect a database from repeated misses, but use a short TTL so newly created records become visible. Add jitter to high-volume TTLs so related keys do not expire simultaneously.
Atomic operations, locks, and stampedes
Section titled “Atomic operations, locks, and stampedes”Cache::add() stores only when absent and is atomic. Increment, decrement, locks, and rate limiters likewise depend on backend atomic operations. Use one shared lock-capable store across all participants; a local file or array cache cannot coordinate separate hosts.
Cache::lock($name, $seconds) is a lease. The owner receives the lock for a bounded interval and may release it; an owner token can transfer release responsibility. Expiry recovers from a crashed owner, but it also means the old owner can still run after the lease expires while a new owner begins. Laravel 13 can refresh supported locks, yet renewal can fail during a pause or network partition. A lock reduces overlap; it does not prove exactly-once execution. Set lease duration from measured work, bound waits, use owner-safe release, and make the protected business effect idempotent or guarded by a database constraint or conditional update.
For a hot miss, use stale-while-revalidate or let one lock holder refresh while other callers serve stale data, retry briefly, or fall back deliberately. Do not make every caller wait indefinitely. Record hit ratio, compute latency, lock contention, refresh errors, and source load; a high hit ratio can still conceal dangerously stale values.
Session lifecycle and concurrency
Section titled “Session lifecycle and concurrency”The browser normally carries only the session identifier cookie. Laravel’s session middleware reads the configured driver, makes data available to the request, then persists changes on the response path. Cookie sessions store encrypted data in the cookie instead; their size, replay, and invalidation characteristics differ. File sessions are host-local unless storage is shared. Database and Redis sessions support multiple application nodes. The array driver is non-persistent and useful in tests.
Expiry combines server configuration and client behavior. A cookie may disappear when the browser closes while server data remains until garbage collection; server data may expire while a browser still presents an identifier. Some drivers require probabilistic garbage collection. Treat configured lifetime as policy, not a precise timer observed simultaneously by every component.
Regenerate the identifier after authentication or privilege elevation to prevent fixation. On logout, invalidate the session and regenerate the CSRF token; deleting only the browser cookie can leave stolen server-side state usable. Session encryption does not replace TLS or secure cookie attributes. Scope domain, path, Secure, HttpOnly, and SameSite to the topology, including reverse-proxy scheme detection.
Two requests with the same session can run concurrently by default. They may read the same initial value and the last write can overwrite the other. Laravel route-level session blocking acquires a lock for drivers that support atomic locks; configure lock and wait durations so a crash recovers and a legitimate request does not silently overlap after expiry. Avoid putting independent API calls behind a shared session when they do not need it, and keep slow external I/O outside the locked section.
Redis boundaries and shared-dependency failure
Section titled “Redis boundaries and shared-dependency failure”Laravel can use PhpRedis or Predis and supports named connections. Separate logical databases or prefixes reduce key collisions but do not isolate CPU, memory, network, connections, failover, or an instance-wide eviction policy. A queue burst can consume memory and cause cache eviction; session writes can compete with cache traffic; long commands can increase request latency; one outage can log users out, disable rate limiting, release locks, and stop queues.
Decide whether workloads with different durability and latency requirements deserve separate deployments. Cache data may tolerate eviction; sessions usually must not be casually evicted; queues need their own persistence and recovery analysis. Avoid unbounded key cardinality and large serialized graphs. Monitor memory headroom, evictions, command latency, blocked clients, connections, replication lag, persistence errors, and queue age per workload.
Laravel 13 cache failover can try an ordered list of stores when an operation throws. That can improve availability for disposable reads, but it changes coherence: a write to one store is not automatically copied to another, and a recovered primary can contain older values. Treat failover as a measured degraded mode with short-lived values and an explicit return-to-primary strategy, not transparent strong consistency.
Production review checklist
Section titled “Production review checklist”- Identify the source of truth and prove correctness on a miss.
- Namespace keys by application, environment, tenant, representation, and schema version as needed.
- Document maximum staleness, invalidation triggers, TTL repair, and stampede behavior.
- Keep session availability and eviction requirements separate from disposable cache requirements.
- Make lock-protected effects safe after lease expiry, process death, or retry.
- Capacity-test combined Redis workloads and define behavior when Redis is slow or unavailable.
Current and legacy context
Section titled “Current and legacy context”Current: Laravel 13 includes database cache by default in fresh applications, stale-while-revalidate, cache memoization, lock refreshing, cache failover, and route-level session blocking. Common: Laravel 11–12 applications use the same core contracts but may have different generated configuration. Legacy: older applications often assume file cache/session storage, one web host, or one Redis database for every subsystem. Verify configuration rather than inferring behavior from version.
Interview practice
Section titled “Interview practice”- LARAVEL-CACHE-01 — Design a safe cache key and invalidation plan
- LARAVEL-CACHE-02 — Explain why a cache lock is a lease
- LARAVEL-CACHE-03 — Control a hot-key stampede
- LARAVEL-CACHE-04 — Trace session concurrency and regeneration
- LARAVEL-CACHE-05 — Separate Redis workloads and failure domains
Primary sources
Section titled “Primary sources”Generic cache coherence, eviction, and Redis reasoning belongs in cache and Redis.