Set up Redis cache for web applications on a Linux VPS

You have a web application on a VPS, a WordPress site, a Django app, a Node.js API, and it starts slowing down as traffic grows. The database is the bottleneck: every page load hits MySQL or PostgreSQL, even for the same data. You need a caching layer that sits in memory and serves responses in microseconds. That's where Redis comes in. This guide walks you through setting up Redis as a cache on a Linux VPS, from installation to production hardening, using commands that work as of mid-2026.
Prerequisites
- A Linux VPS running Ubuntu 24.04 LTS, Debian 12, or AlmaLinux 9. The commands in this guide target Ubuntu/Debian, adapt package names for RHEL-family (dnf instead of apt).
- A non-root sudo user (standard security practice).
- Root or sudo access to install packages and edit system files.
- A web application already running on the same VPS or a separate server (the cache can be local or network-facing).
- Port 6379 open in your firewall only for your web server's IP if Redis is on a different machine. For same-machine caching, bind to 127.0.0.1.
Why you need a dedicated cache, not just any memory store
Many developers throw data into the database and hope queries are fast enough. For low-traffic sites, that works. But when you hit hundreds or thousands of concurrent users, every query adds latency. A typical MySQL query on a VPS might take 5, 50 ms. A Redis lookup for the same cached data takes 0.1, 1 ms, literally two orders of magnitude faster. Redis stores everything in RAM, uses key-value data structures, and avoids disk I/O for reads. It also supports automatic key expiration (TTL), eviction policies when memory fills up, and atomic operations for counters, sessions, and rate-limiting. For a web application, Redis as a cache means your PHP/Python/Node code first checks Redis; if the key exists (a cache hit), you return it immediately. If not (a cache miss), you fetch from the database, then store the result in Redis with an expiration time.
Step 1, Installing Redis on your VPS
The official Redis repository stays ahead of the Ubuntu universe package. Install the latest stable release (Redis 8.8 as of this writing) by adding the repository.
sudo apt update
sudo apt install -y curl gnupg
curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list
sudo apt update
sudo apt install -y redis
Verify the installed version:
redis-server --version
You should see output similar to Redis server v=8.8.0 (the exact minor version may differ). Then enable and start the service:
sudo systemctl enable redis-server
sudo systemctl start redis-server
sudo systemctl status redis-server
The status should show active (running). This simple apt install gives you a working Redis, but it runs with default settings, no password, bind to all interfaces, unlimited memory. The next steps lock that down.
Step 2, Configuring Redis as a cache (not a persistent database)
The default Redis configuration is built for use as a database with disk persistence. For a pure cache, you want to disable persistence entirely, no RDB snapshots, no AOF logs. This makes Redis faster and avoids the "save on every write" overhead that doesn't matter when you can regenerate the cache from the database.
Edit the main config file:
sudo nano /etc/redis/redis.conf
Make these changes:
- Disable RDB persistence, comment out or set:
save ""
- Disable AOF:
appendonly no
- Set a memory limit, this is critical for a cache. Without it, Redis can consume all available RAM and crash your VPS. Set to about 60, 70% of your VPS RAM. For a 2 GB VPS:
maxmemory 256mb
- Choose an eviction policy,
allkeys-lruis the safest for a general cache: when memory fills up, Redis evicts the least-recently-used keys. For session storage,allkeys-lfu(least-frequently-used) may be better. Set:
maxmemory-policy allkeys-lru
- Bind to localhost, only if Redis and your web app run on the same VPS. Find the
binddirective:
bind 127.0.0.1
- Set a strong password, even if binding to localhost, a password prevents other processes or users from connecting. Uncomment or add:
requirepass your_strong_redis_password
Replace your_strong_redis_password with a long, random string (use openssl rand -base64 32).
After saving the file, restart Redis:
sudo systemctl restart redis-server
Step 3, Securing Redis with nftables (or ufw)
If you run Redis on a separate machine from the web app, you need to restrict access to only your web server's IP. On the Redis VPS, use nftables (the modern replacement for iptables):
sudo nft add rule inet filter input tcp dport 6379 ip saddr YOUR_WEB_SERVER_IP accept
sudo nft add rule inet filter input tcp dport 6379 drop
Make it permanent by saving the ruleset:
sudo nft list ruleset > /etc/nftables.conf
sudo systemctl enable nftables
If you use ufw (common on Ubuntu):
sudo ufw allow from YOUR_WEB_SERVER_IP to any port 6379 proto tcp
Test from your web server:
redis-cli -h YOUR_REDIS_VPS_IP -p 6379 -a your_strong_redis_password PING
Expected output: PONG. If you get Connection refused or NOAUTH, check the firewall and the bind config.
Step 4, Basic verification: is your cache working?
Test from the same VPS (or from your web server after connecting):
redis-cli -a your_strong_redis_password PING
Should return PONG. Then set a test key:
redis-cli -a your_strong_redis_password SET mykey "Hello from Redis cache"
redis-cli -a your_strong_redis_password GET mykey
Output: "Hello from Redis cache". Now check the cache hit rate using Redis's built-in stats:
redis-cli -a your_strong_redis_password INFO stats | grep keyspace
Look for keyspace_hits and keyspace_misses. After your application has been running for a while, a healthy cache has a hit rate of 80, 95% (hits/total). Low hit rate means your TTLs are too short or your cache keys are not being used effectively.
Step 5, Connecting a web application to Redis
This step varies by framework. Here are two common examples:
PHP (WordPress, Laravel, custom apps)
Install the PhpRedis extension:
sudo apt install -y php8.3-redis
sudo systemctl restart php8.3-fpm
In your PHP code:
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->auth('your_strong_redis_password');
$cached = $redis->get('my_page_key');
if ($cached) {
echo $cached;
exit;
}
// ... generate page content ...
$redis->setex('my_page_key', 3600, $page_content); // expire after 1 hour
Node.js (Express, Nest, custom apps)
Install the redis package:
npm install redis
In your code:
import { createClient } from 'redis';
const client = createClient({ url: 'redis://:[email protected]:6379' });
await client.connect();
const cached = await client.get('my_page_key');
if (cached) return res.send(cached);
// ... generate response ...
await client.setEx('my_page_key', 3600, responseData);
Step 6, Monitoring and tuning for production
Redis itself has fine-grained monitoring. Two essential commands:
redis-cli -a your_strong_redis_password INFO memory
Shows used_memory_human and maxmemory_human so you see how close you are to the limit. If you're consistently at 90%+ of maxmemory, the eviction policy is constantly running, increase the limit or add more RAM to the VPS.
redis-cli -a your_strong_redis_password INFO stats | grep -E "keyspace_(hits|misses)|evicted_keys|expired_keys"
Watch evicted_keys: if it's high, your TTLs are too long or your maxmemory is too low. Watch expired_keys: if it's very high relative to hits, your TTLs might be too short, causing premature cache invalidation.
For logs, check journalctl -u redis-server if something goes wrong. A common error is OOM command not allowed when used memory > 'maxmemory', meaning Redis hit the limit and has no room to evict, check your eviction policy.
Frequently Asked Questions
What is the difference between using Redis as a cache vs. as a database?
As a cache, Redis stores temporary copies of data from an authoritative source (your main database). Keys have TTLs, and data loss is acceptable, you just regenerate from the DB. As a database, Redis persists all writes to disk and you treat it as the source of truth. For a cache, disable persistence and set a memory cap with an eviction policy.
Should I run Redis on the same VPS as my web application?
For low to medium traffic, running them together is fine and reduces network latency. Keep Redis bound to 127.0.0.1. For high traffic (millions of requests/day), separate Redis to its own VPS so they don't compete for CPU and memory.
What eviction policy should I use for a web cache?
allkeys-lru (remove least-recently-used keys) covers most cases. For session handling where some sessions are more frequent than others, allkeys-lfu (remove least-frequently-used) performs better. Use volatile-lru only if you explicitly want to protect keys without a TTL from eviction.
Can I use Redis without a password if it's on localhost only?
Technically yes, but it's a poor practice. Any process or user on the same VPS, including a compromised web app, can connect and flush your cache or access session data. Always set requirepass.
How much RAM should I allocate for Redis on a VPS?
Set maxmemory to 60, 70% of total VPS RAM, leaving the rest for the OS, the web server, and the database. For a 1 GB VPS, use maxmemory 512mb. For 4 GB, use maxmemory 2gb. Monitor and adjust based on cache hit rate and eviction counts.
What happens when Redis uses all its maxmemory?
With a proper eviction policy (allkeys-lru), Redis automatically removes the least-recently-used keys to make room for new ones. The cache becomes "warm", old data disappears, new data fills the space. This is normal and not an error. If you see OOM errors, your eviction policy may be set to noeviction (default on some distributions), which blocks new writes.
Related articles
- Nginx tuning for high traffic, workers, gzip, buffers, cache
- Configure swap and optimize memory on a low-RAM VPS
- Docker networking explained, bridge, host, overlay
- Set up nftables firewall on a VPS to replace iptables


