Why Cache with Redis?
Every database query has a cost — CPU, I/O, and latency. When the same data is requested thousands of times per second, you're paying that cost repeatedly for identical results. Redis is an in-memory data store that sits in front of your database, returning cached results in under a millisecond and shielding your database from unnecessary load.
This tutorial walks through practical Redis caching patterns you can apply today.
Core Redis Commands You Need to Know
Connect to a Redis instance:
redis-cli -h your-redis-host -p 6379 -a your-passwordThe fundamental caching commands:
# Store a value with a 60-second TTL
SET user:42 '{"id":42,"name":"Alice"}' EX 60
# Retrieve it
GET user:42
# Check remaining TTL
TTL user:42
# Delete a key
DEL user:42
# Check if a key exists
EXISTS user:42The Cache-Aside Pattern
Cache-aside (also called lazy loading) is the most common pattern: your application checks Redis first; on a miss it queries the database and populates the cache.
# Pseudocode as shell commands for illustration
CACHE_KEY="user:42"
VALUE=$(redis-cli GET "$CACHE_KEY")
if [ -z "$VALUE" ]; then
# Cache miss — fetch from database
VALUE=$(psql -c "SELECT row_to_json(u) FROM users u WHERE id = 42" -t)
redis-cli SET "$CACHE_KEY" "$VALUE" EX 300
fi
echo "$VALUE"In Node.js this looks like:
# Install ioredis
npm install ioredisCaching Database Query Results
A common real-world example — caching the top 10 blog posts:
-- This is the expensive query you want to cache
SELECT id, title, slug, view_count
FROM posts
WHERE published = true
ORDER BY view_count DESC
LIMIT 10;Set the cache key with a reasonable TTL so stale data doesn't linger:
# After running the query, store the JSON result
redis-cli SET "posts:top10" "$RESULT_JSON" EX 120A two-minute TTL means readers see data at most two minutes old — acceptable for a leaderboard, far better than hammering the database on every page load.
Cache Invalidation Strategies
Caching introduces a consistency challenge: when the underlying data changes, the cache must be updated or invalidated.
Time-based expiry (TTL) — simplest approach, accept slight staleness:
redis-cli SET "product:99" "$JSON" EX 300 # expires in 5 minutesWrite-through — update the cache whenever you update the database:
# After UPDATE posts SET view_count = ... WHERE id = 1;
redis-cli SET "post:1" "$UPDATED_JSON" EX 600Explicit delete on write — simplest for rarely-read-but-often-written data:
redis-cli DEL "posts:top10"Session Storage with Redis
Redis is also ideal for storing user sessions. Each session is a hash with per-field access:
redis-cli HSET "session:abc123" user_id 42 role admin last_seen 1716000000
redis-cli EXPIRE "session:abc123" 86400 # 24 hours
# Read a single field
redis-cli HGET "session:abc123" roleRate Limiting with Redis
Implement a simple rate limiter using atomic increments:
KEY="rate:user:42:$(date +%s | cut -c1-8)" # bucket per ~10s window
COUNT=$(redis-cli INCR "$KEY")
redis-cli EXPIRE "$KEY" 10
if [ "$COUNT" -gt 100 ]; then
echo "Rate limit exceeded"
fiMonitoring Cache Performance
# Live stats — hits, misses, memory usage
redis-cli INFO stats | grep -E "keyspace_hits|keyspace_misses|used_memory_human"
# Calculate hit rate
# hit_rate = keyspace_hits / (keyspace_hits + keyspace_misses) * 100A healthy cache hit rate is typically above 90%. If yours is lower, review your TTLs and key design.
Managed Redis on PandaStack
[PandaStack](https://dashboard.pandastack.io) includes managed Redis alongside PostgreSQL, MySQL, and MongoDB — no separate provisioning required. Create a Redis instance from the Databases panel, copy the connection string, and start caching in minutes.
Documentation: [docs.pandastack.io](https://docs.pandastack.io).
Summary
| Pattern | Best For |
|---|---|
| Cache-aside | Read-heavy, infrequently updated data |
| Write-through | Data that must stay consistent |
| TTL expiry | Leaderboards, aggregates, public data |
| Session storage | User authentication state |
| Rate limiting | API abuse prevention |
Pick the pattern that matches your consistency requirements, keep TTLs short enough to avoid excessive staleness, and monitor your hit rate to prove the cache is doing its job.