Redis is a key-value database that keeps its data in RAM rather than on disk, which is why reads and writes typically take well under a millisecond. It shines wherever speed matters more than long-term storage: caching the results of expensive queries, storing user sessions, queuing background jobs, counters and rate limiting.
Redis usually doesn't replace MySQL or PostgreSQL; it sits alongside them. Your main database is the source of truth, and Redis is a fast layer for data that is either temporary or can be rebuilt. Below we cover what Redis is actually good for, how to run it with Docker, how to secure it, and when you don't need it at all.
Short answer: Redis is an in-memory key-value database, so reads and writes usually complete in under a millisecond. It is mostly used next to your main database for caching, sessions, background job queues, counters and rate limiting, and it is not a replacement for MySQL or PostgreSQL.
How Redis works
Everything in Redis has a key, such as user:42:profile, and a value. What sets it apart from a plain dictionary is that the value can be a full data structure (list, set, hash and so on), and Redis provides atomic commands for each. "Atomic" means that if a hundred concurrent requests increment a counter, it ends up exactly a hundred higher.
Two more properties matter:
- TTL: any key can have an expiry and delete itself. Ideal for caches and sessions.
- Single-threaded command execution: commands run one at a time, which makes concurrency simple. The flip side is that one expensive command, like
KEYS *across millions of keys, stalls everyone else.
Main use cases for Redis
Caching
The most common use. You store the result of an expensive query or computation in Redis for a while, and subsequent requests read it from there. What to cache and for how long is the subject of Laravel caching: where and how long.
Sessions
Once your application runs on more than one server, file-based sessions stop working because each server has its own files. Redis gives every server a shared, fast place to store sessions.
Queues
Redis lists make a solid foundation for background job queues. Laravel, Sidekiq in Ruby, and Celery and RQ in Python all support Redis as a queue backend. Queues in Laravel are covered in detail in this article.
Rate limiting
"At most 60 requests per minute per IP." With INCR and EXPIRE this takes a few lines and works consistently across all your servers.
Pub/Sub
One part of your system publishes a message and every subscriber to that channel receives it immediately. It's a good fit for real-time notifications, with one caveat: a subscriber that isn't connected at that moment misses the message. For messages that must not be lost, Redis Streams is the better choice.
Redis data types with redis-cli examples
You can run these commands directly from the shell. If you're inside the interactive redis-cli prompt, leave out the redis-cli prefix and the comments after #.
String: the simplest type, for caches and counters:
redis-cli SET page:home "<html>...</html>" EX 300 # expires in 300 seconds
redis-cli GET page:home
redis-cli TTL page:home # seconds remaining
redis-cli INCR stats:visits # atomic counter
Hash: like a record with several fields:
redis-cli HSET user:42 name "Sara" plan "pro"
redis-cli HGET user:42 plan
redis-cli HGETALL user:42
List: queues or most-recent items:
redis-cli LPUSH jobs "send-invoice:1001"
redis-cli RPOP jobs
redis-cli LRANGE recent:posts 0 9 # first ten items
Set: a collection with no duplicates:
redis-cli SADD online:users 42 57 91
redis-cli SISMEMBER online:users 42
redis-cli SCARD online:users
Sorted set: a set with scores, for leaderboards:
redis-cli ZADD leaderboard 1500 "ali" 2100 "sara" 1800 "reza"
redis-cli ZRANGE leaderboard 0 2 REV WITHSCORES # top three
And the rate-limiting pattern:
redis-cli INCR rate:203.0.113.5
redis-cli EXPIRE rate:203.0.113.5 60 NX # only if no expiry is set
If the value returned by INCR exceeds 60, reject the request. The NX option on EXPIRE is available from Redis 7 onward.
Persistence: RDB vs. AOF
If the data lives in RAM, what happens on restart? Redis has two ways of writing to disk:
| Method | How it works | Advantage | Drawback |
|---|---|---|---|
| RDB | Periodic full snapshot of the data in dump.rdb |
Compact file, fast startup | Changes since the last snapshot are lost |
| AOF | Every write command is appended to a file | With appendfsync everysec, at most about one second of data is lost |
Larger file, slower recovery |
For queues and sessions, turn AOF on. For a pure cache you can even switch persistence off entirely; an empty cache just means the first few requests are slower.
Why Redis isn't your primary database
- Your data is limited by RAM, and RAM costs more than disk.
- No querying: you can't ask for "last month's orders from customers in a given city". You can only access data by key.
- No relations, constraints or SQL-style transactions.
- Even with AOF, its durability guarantees don't match a relational database.
A simple rule: if a key disappears from Redis, you should be able to rebuild it from your main database. For choosing that main database, see this article.
Running Redis with Docker
If you don't have Docker yet, first install Docker on Ubuntu 24.04. Then:
docker run -d --name redis \
--restart unless-stopped \
-p 127.0.0.1:6379:6379 \
-v redis-data:/data \
redis:8-alpine \
redis-server --appendonly yes --requirepass "$REDIS_PASSWORD"
Note that the port is bound to 127.0.0.1. If you write just -p 6379:6379, Docker publishes the port on every network interface and bypasses your ufw rules as well.
To test it:
docker exec -it redis redis-cli
AUTH <your-password>
PING
In a Docker Compose project, it's better for Redis not to publish any port at all; the application connects to it by service name over Compose's internal network:
services:
redis:
image: redis:8-alpine
command: ["redis-server", "--appendonly", "yes", "--requirepass", "${REDIS_PASSWORD}"]
volumes:
- redis-data:/data
restart: unless-stopped
volumes:
redis-data:
Compose is explained in Docker Compose explained. Without Docker, you can install it on Ubuntu with sudo apt install redis-server.
To connect Laravel, this is all you need in .env:
REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=your-password
REDIS_PORT=6379
CACHE_STORE=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis
Security: the bare minimum
Redis is designed to run on a trusted network. An open Redis instance on the internet gets found and abused very quickly.
- Never expose port 6379 to the internet. Keep
bind 127.0.0.1 -::1inredis.confand don't turn offprotected-mode yes. - Set a password, with
requirepassor, better, with ACLs and a separate user per application. - Configure the firewall as in the first-hour server checklist, and remember that Docker-published ports bypass ufw.
- Block dangerous commands such as
FLUSHALLandCONFIGfor the application user via ACLs. - Cap memory with
maxmemory. For a cache, theallkeys-lrupolicy fits; for a queue, usenoevictionso Redis doesn't silently drop your jobs.
When you don't need Redis
Redis is one more service to install, monitor, update and back up. These situations usually work fine without it:
- A small site on a single server: Laravel's file or database cache and the
databasequeue driver are perfectly adequate to start with. - When the slowness comes from a bad query: add an index and fix the query first. Caching a bad query hides the problem; it doesn't solve it.
- Shared hosting that doesn't let you run Redis; in that case it may be time to move to a VPS rather than work around the issue.
Signs that it's time: the database is slowing down under repeated reads, the application runs on more than one server and needs shared sessions, or the database queue can no longer keep up with the job volume.
A side note: in 2024 Redis changed its license and the open-source Valkey project forked from it; starting with Redis 8, an open-source AGPL licensing option was added back. For most projects, both work with the same commands and clients.
Frequently asked questions
What is the difference between Redis and MySQL?
MySQL stores data on disk, supports SQL queries, relations between tables and transactions, and is your primary source of data. Redis keeps data in RAM, gives access only by key, and is suited to temporary or rebuildable data such as caches and sessions.
Does Redis lose data on restart?
Not if persistence is enabled. RDB periodically saves a full snapshot to disk and AOF logs every write command to a file; with AOF and appendfsync everysec, you lose at most about one second of data.
What is Redis used for in Laravel?
Laravel can use Redis for caching, sessions and queues. Set CACHE_STORE, SESSION_DRIVER and QUEUE_CONNECTION to redis in your .env file and add the Redis connection details.
How do I install Redis on Ubuntu?
Run sudo apt install redis-server, or use Docker with the official redis image. Either way, bind Redis to 127.0.0.1 or an internal network, set a password and cap its memory with maxmemory.
What is the difference between Redis and Valkey?
Valkey is an open-source project that forked from Redis in 2024 after Redis changed its license. For most projects both work with the same commands and clients, and since Redis 8 an open-source AGPL licensing option has been added back to Redis.
Wrap-up
Redis is an in-memory key-value store: extremely fast, with practical data structures and TTLs. It's a first-rate tool for caching, sessions, queues, counters and rate limiting, but it isn't the source of truth for your data. It's up in a minute with Docker; just bind it to 127.0.0.1 or an internal network, set a password and cap its memory. And if your site is small, don't add it until you see a real need. The official documentation is at redis.io/docs.