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:

bash
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:

bash
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:

bash
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:

bash
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:

bash
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:

bash
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:

bash
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:

bash
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:

compose.yaml
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:

.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 -::1 in redis.conf and don't turn off protected-mode yes.
  • Set a password, with requirepass or, 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 FLUSHALL and CONFIG for the application user via ACLs.
  • Cap memory with maxmemory. For a cache, the allkeys-lru policy fits; for a queue, use noeviction so 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 database queue 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.