
September 09, 2026
12 min read
By Kokil Thapa | Last reviewed: September 2026
Your database slows down long before your traffic justifies a bigger server. Redis: Caching and Data Structures solves that gap by keeping hot data in memory and giving you native types beyond a plain key-value blob. On production Laravel and PHP stacks, Redis 8.10 sits beside MySQL or PostgreSQL as the first line of defence against repeated queries, session bloat, and queue backlogs. This guide walks through setup, structure choice, and the failure modes I see on real deployments.
What is Redis used for in web application caching?
Redis is an in-memory data store that speaks a simple protocol over TCP. Most teams install it for cache, but the same server also powers sessions, job queues, and real-time counters. That dual role is why I reach for Redis before Memcached on custom Laravel applications and WooCommerce stacks.
Cache entries are usually strings: serialised PHP arrays, JSON API responses, or HTML fragments. Redis evicts keys when memory fills, using policies you configure in redis.conf. The default maxmemory-policy allkeys-lru drops least-recently-used keys—a sensible starting point for read-heavy sites.
A typical win looks like this: a product category page runs eight Eloquent queries per request. Cache the rendered fragment for five minutes and MySQL load drops sharply. Pair that with speed optimisation work on indexes and you often delay a costly vertical scale.
Core caching commands every developer should know
These commands cover ninety percent of day-to-day cache work:
SET key value EX 300— store a string with a 300-second TTLGET key— fetch a value; returns nil on missDEL key— invalidate one entryEXISTS key— cheap existence check before a heavy rebuildINCR counter— atomic integer bump for rate limitsTTL key— debug remaining lifetime during incidents
Official command reference lives in the Redis command documentation. Keep a REPL handy during outages—redis-cli beats guessing from application logs.
How do you configure Redis caching in Laravel 13?
Laravel ships first-class Redis support through the predis/predis package or the phpredis PECL extension. On production Ubuntu servers I prefer phpredis for lower latency. Laravel 13 requires PHP 8.3 or higher; PHP 8.5 is the current anchor version and runs Redis clients without issue.
Install Redis on Ubuntu 24.04:
sudo apt update
sudo apt install redis-server php8.5-redis
sudo systemctl enable redis-server
redis-cli ping
# Expected: PONG Point Laravel at Redis in .env:
CACHE_STORE=redis
REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
REDIS_CACHE_DB=1 Separate logical databases—or better, key prefixes—for cache, sessions, and queues. On the booking platform behind Adventure Third Pole Trek, queue workers and page cache share one Redis instance but use different DB indexes to simplify flush operations.
Cache-aside with the Laravel Cache facade
The cache-aside pattern keeps your database authoritative. Application code reads Redis first; on miss it loads from SQL and writes back with a TTL.
use Illuminate\Support\Facades\Cache;
$categories = Cache::remember('shop:categories:v3', 600, function () {
return Category::query()
->withCount('products')
->orderBy('name')
->get();
}); For config, routes, and views, Laravel has dedicated drivers. See Laravel caching strategies for config, route, view, and data for the full matrix. Run php artisan config:cache and php artisan route:cache on deploy—those files belong in your CI/CD pipeline, not only on manual SSH sessions.
Tagged cache invalidation
When one admin action invalidates dozens of related keys, tags beat manual DEL lists. Redis supports tags through Laravel's tag implementation:
Cache::tags(['products', 'category:12'])->put(
'product:list:cat:12',
$products,
3600
);
// After an update:
Cache::tags(['products', 'category:12'])->flush(); Memcached cannot do this natively. If your catalogue changes often, that alone may justify Redis. Compare trade-offs in Laravel cache tags with Redis vs Memcached.
Which Redis data structures fit common web application patterns?
Strings work for simple cache blobs, but Redis earns its keep when the data model maps to a native type. Picking the wrong structure creates serialisation overhead or awkward key sprawl. The diagram below maps types to typical use cases.
Strings and hashes
Strings store serialised objects. Hashes store field maps under one key—ideal when you update single attributes without rewriting a whole JSON blob.
# Hash example: cart summary per user
HSET cart:8842 item_count 3
HSET cart:8842 subtotal_npr 4500
HSET cart:8842 updated_at 1699999999
HGETALL cart:8842 On eCommerce projects like Quick And Easy Nepalese Grocery, hashes hold lightweight session cart metadata while the authoritative cart lives in MySQL. If the Redis key expires, the next page load rebuilds from SQL—acceptable for non-checkout views.
Lists, sets, and sorted sets
Lists give FIFO queues at the data-structure level—though Laravel queues use Redis lists internally via a higher-level API. Sets enforce uniqueness: tag IDs, online user IDs, or "already notified" tokens. Sorted sets (ZSET) pair a member with a score; perfect for leaderboards and time-ordered rankings.
# Top contributors this week (score = points)
ZADD leaderboard:2026w36 1200 "user:101"
ZADD leaderboard:2026w36 980 "user:442"
ZREVRANGE leaderboard:2026w36 0 9 WITHSCORES Need deeper coverage? Read Redis data structures beyond cache for streams and HyperLogLog use cases.
Streams and pub/sub for real-time features
Streams persist event logs with consumer groups—useful for audit trails and async fan-out. Pub/sub pushes ephemeral messages to subscribers with no persistence. Laravel broadcasting and websocket scaling often combine Redis pub/sub with websocket workers. Do not confuse pub/sub with a durable queue; dropped messages are expected if no subscriber is connected.
How do you prevent cache stampede and stale data in Redis?
A cache stampede hits when a hot key expires and hundreds of concurrent requests rebuild it at once. Your database spikes, Redis memory churns, and p99 latency jumps. I have seen this take down category pages on high-traffic WooCommerce stores during flash sales.
Practical stampede defences
- Probabilistic early expiry — refresh hot keys before hard TTL under load
- Mutex via SET NX — one worker rebuilds; others wait or return stale data
- Stale-while-revalidate — serve old value while async job refreshes
- Request coalescing — Laravel
Cache::lock()wraps the rebuild closure
use Illuminate\Support\Facades\Cache;
$value = Cache::remember('report:daily', 900, function () {
return Cache::lock('lock:report:daily', 10)->block(5, function () {
return DB::table('orders')->selectRaw('DATE(created_at) as d, COUNT(*) as c')
->groupBy('d')->get();
});
}); Stale data is a product decision, not only a technical one. A price list cached for an hour may be fine for a blog sidebar but wrong for checkout. Document TTL rules per domain object. Query-level patterns are covered in database query caching strategies.
Invalidation strategy checklist
Cache bugs are often stale-data bugs. Tie invalidation to write paths:
- Flush tagged groups when admin updates a catalogue
- Version keys (
products:v4) instead of deleting unknown dependents - Publish invalidation events on model save via Eloquent observers
- Never cache user-specific auth or payment state globally
Validate JSON API payloads during development with the JSON formatter tool before you serialise them into Redis strings—bad encoding wastes hours in production debugging.
When should you choose Redis over Memcached for caching?
Both are fast in-memory stores. Memcached 1.6.x remains excellent for simple GET/SET cache pools. Redis adds data structures, persistence options, pub/sub, and Lua scripting. The table below summarises what I tell teams choosing infrastructure in 2026.
| Criteria | Redis 8.10 | Memcached 1.6.x |
|---|---|---|
| Primary use case | Cache + queues + sessions + structures | Pure object cache |
| Data types | Strings, hashes, lists, sets, ZSET, streams | Opaque blobs only |
| Persistence | RDB snapshots, AOF log | None (by design) |
| Tag-based invalidation | Supported via app patterns | Not native |
| Memory efficiency | Higher per-key overhead | Lean for small objects |
| Multi-threading | IO threads; mostly single-threaded command core | Multi-threaded on 1.6 line |
| Typical PHP stack fit | Laravel cache, queue, session, Horizon | WordPress object cache only |
Verdict: choose Memcached when you need a stateless, horizontally sharded blob cache and nothing else. Choose Redis when one service should handle cache, Laravel queues, sessions, rate limiting, and pub/sub. Full comparison: Redis vs Memcached vs Dragonfly.
WordPress sites benefit from Redis object cache too—see WordPress object cache with Redis setup. Magento 2.4.x shops often pair Redis with Varnish as described in Magento 2 Redis and Varnish for speed.
How do you run Redis safely in production?
Redis is fast because it keeps data in RAM. That speed comes with operational obligations: memory caps, persistence choice, network isolation, and monitoring. On Ubuntu servers I manage via Linux system administration, Redis runs on a private interface—not exposed to the public internet.
Memory, persistence, and security
Set maxmemory to roughly seventy percent of available RAM on a dedicated Redis box. Leave headroom for OS page cache and RDB fork spikes. Enable requirepass or ACL users; bind to 127.0.0.1 unless you run a managed cluster.
Persistence trade-offs matter when Redis holds more than disposable page cache. Queues and session data need RDB snapshots, AOF, or both. Read Redis persistence RDB vs AOF compared and Redis persistence and clustering before you assume cache-only defaults.
Monitor these metrics continuously:
used_memory_rssvsmaxmemoryevicted_keys— rising evictions mean TTL or capacity tuning neededinstantaneous_ops_per_sec— baseline for anomaly detectionblocked_clients— signals slow commands or BLPOP waits
After deploy, reload PHP-FPM so opcache picks up code changes—same routine I use on legal-tech portals like Court Marriage In Nepal and sister sites on shared Deployer pipelines. Redis restarts do not replace application deploy hygiene.
High-traffic and multi-layer caching
Redis is one layer. Full stacks combine CDN edge cache, HTTP reverse proxies, application cache, and ORM query cache. See caching strategies for high-traffic sites and improving web performance with caching strategies. API responses may also use ETag headers as in API caching with ETag and Last-Modified.
Symfony projects integrate through the cache component—Symfony cache with Redis and APCu covers adapter configuration for PHP 8.4+ and Symfony 8.1 deployments.
Key Takeaways
- Use Redis 8.10 for cache plus queues, sessions, and native data structures—not only GET/SET strings.
- Configure Laravel with phpredis, separate logical DBs, and tagged invalidation for catalogue-heavy apps.
- Match structure to pattern: hashes for field maps, sets for uniqueness, sorted sets for rankings, streams for durable events.
- Stop cache stampedes with locks, stale-while-revalidate, and TTL rules tied to business freshness needs.
- Cap memory, enable auth, choose persistence when data survives beyond a page view, and monitor evictions.
- Combine Redis with CDN and HTTP caching layers—one store rarely fixes every latency problem alone.
People Also Ask
Is Redis only a cache?
No. Redis started as a cache but now serves as a primary data store for ephemeral and semi-durable workloads. Teams use it for session storage, job queues, rate limiting, pub/sub, leaderboards, and distributed locks. Cache remains the most common entry point, but the data structures are what keep it in the stack long term.
What TTL should I set for Redis cache keys?
Match TTL to how fast the underlying data changes. Static config can live for hours or days. Product listings might use five to thirty minutes. Personalised or cart data often needs seconds to minutes, or no cache at all. When in doubt, shorter TTL plus tag invalidation beats long TTL plus manual flush scripts.
Does Redis replace MySQL or PostgreSQL?
Not for authoritative business data. Redis excels at speed and atomic in-memory operations but is sized for RAM, not terabytes of relational history. Keep orders, users, and payments in MySQL 9.7 or PostgreSQL 18. Use Redis as an acceleration and coordination layer on top.
Can Redis run on the same server as PHP?
Yes for small and mid-traffic sites—a common setup on client VPS hosts at roughly Rs 2,500–5,000/month (~USD 19–37). Watch RAM contention: if Redis and MySQL compete for memory, latency spikes on both. Split Redis to its own instance once evictions or OOM kills appear in logs.
Ship faster applications with the right Redis layer
Redis: Caching and Data Structures reward teams who treat cache as architecture, not an afterthought. Pick the native type, set honest TTLs, protect hot keys from stampedes, and lock down production access. The result is lower database load, snappier pages, and headroom before your next hardware bill. If you want help auditing cache strategy on a Laravel, WordPress, or custom PHP codebase, review our testing and optimisation service or contact us for a production review.
Frequently Asked Questions
0 Comments
Leave a comment
Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

