Valkey on a VPS: The Open-Source Redis Alternative for Caching, Queues, and Session Storage
Valkey is a fully open-source, Redis-compatible in-memory data store forked from Redis 7.2 after Redis changed to a proprietary SSPL license in 2024. Valkey is maintained by the Linux Foundation with major contributors from AWS, Google, Oracle, and Ericsson. It is API-compatible with Redis — the same commands, same clients, same configuration — with a BSD open-source license that will remain free to use and deploy indefinitely.
Why Valkey Instead of Redis
- License: Redis is now SSPL (non-OSI-approved, commercial restrictions). Valkey is BSD licensed — use freely in any context.
- API compatibility: Valkey is a drop-in replacement — same commands, same clients (ioredis, redis-py, jedis), same config format.
- Active development: Linux Foundation backing, rapid release cadence, I/O threading improvements
- Zero migration cost: Change the hostname in your Redis connection string — nothing else changes
Step 1: Docker Compose Setup
<code">mkdir -p /opt/valkey && cd /opt/valkey nano docker-compose.yml
<code">version: '3.8'
services:
valkey:
image: valkey/valkey:8-alpine
container_name: valkey
restart: always
ports:
- "127.0.0.1:6379:6379"
command: valkey-server /usr/local/etc/valkey/valkey.conf
volumes:
- ./valkey.conf:/usr/local/etc/valkey/valkey.conf:ro
- valkey_data:/data
volumes:
valkey_data:
<code">nano valkey.conf
<code"># Authentication requirepass YourStrongValkeyPassword! # Persistence — choose based on use case: # Option A: RDB snapshots (good for cache + occasional persistence) save 900 1 # Save if at least 1 key changed in 900 seconds save 300 10 # Save if at least 10 keys changed in 300 seconds save 60 10000 # Save if at least 10000 keys changed in 60 seconds # Option B: AOF (append-only file — better durability for queues/sessions) # appendonly yes # appendfsync everysec # Flush to disk every second # Option C: No persistence (pure cache — data lost on restart) # save "" # appendonly no # Memory limit and eviction (for caching use case) maxmemory 512mb maxmemory-policy allkeys-lru # Evict least recently used keys when full # Bind to localhost only (Nginx/app handles external access) bind 127.0.0.1 # Performance tcp-keepalive 300 tcp-backlog 511 # Logging loglevel notice logfile /data/valkey.log
<code">docker compose up -d docker compose logs -f valkey # Test connection docker exec valkey valkey-cli -a YourStrongValkeyPassword! PING # Expected: PONG
Step 2: Bare-Metal Install (Alternative)
<code"># Install from package manager sudo apt install -y valkey-server # Or compile from source: git clone https://github.com/valkey-io/valkey.git /tmp/valkey cd /tmp/valkey && make -j$(nproc) sudo make install # Installs valkey-server and valkey-cli sudo systemctl enable valkey-server sudo systemctl start valkey-server
Step 3: Common Use Cases
Application Caching (Python/Flask)
<code">pip install valkey redis # Valkey uses the redis client
<code">import redis
import json
from functools import wraps
# Connect — identical to Redis connection
r = redis.Redis(
host='localhost',
port=6379,
password='YourStrongValkeyPassword!',
decode_responses=True,
)
def cache(ttl: int = 300):
"""Cache decorator — caches function result in Valkey for TTL seconds."""
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
key = f"cache:{func.__name__}:{args}:{kwargs}"
cached = r.get(key)
if cached:
return json.loads(cached)
result = func(*args, **kwargs)
r.setex(key, ttl, json.dumps(result))
return result
return wrapper
return decorator
@cache(ttl=300)
def get_user_profile(user_id: int) -> dict:
"""Expensive database query — cached for 5 minutes."""
# ... database query here
return {"id": user_id, "name": "Alice"}
Session Storage (Node.js/Express)
<code">npm install ioredis connect-redis express-session
<code">import session from 'express-session';
import { createClient } from 'redis'; // ioredis also works
import RedisStore from 'connect-redis';
// Connect to Valkey — same API as Redis
const client = createClient({
socket: { host: 'localhost', port: 6379 },
password: 'YourStrongValkeyPassword!',
});
await client.connect();
app.use(session({
store: new RedisStore({ client }), // Uses Valkey transparently
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
cookie: {
secure: true, // HTTPS only
httpOnly: true,
maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days
},
}));
Job Queue (BullMQ)
<code">npm install bullmq ioredis
<code">import { Queue, Worker } from 'bullmq';
import IORedis from 'ioredis';
const connection = new IORedis({
host: 'localhost',
port: 6379,
password: 'YourStrongValkeyPassword!',
maxRetriesPerRequest: null, // Required for BullMQ
});
// Producer: add jobs
const emailQueue = new Queue('email', { connection });
await emailQueue.add('send-welcome', {
to: 'user@example.com',
template: 'welcome',
});
// Consumer: process jobs
const worker = new Worker('email', async (job) => {
const { to, template } = job.data;
await sendEmail(to, template);
console.log(`Sent ${template} email to ${to}`);
}, { connection, concurrency: 5 });
Step 4: Monitor Valkey
<code"># Real-time stats docker exec valkey valkey-cli -a YourStrongValkeyPassword! INFO # Key metrics from INFO: # connected_clients: active connections # used_memory_human: RAM in use # hit_rate: cache hit percentage (keyspace_hits / (hits + misses)) # evicted_keys: keys evicted due to maxmemory policy # Monitor commands in real-time (debug use) docker exec valkey valkey-cli -a YourStrongValkeyPassword! MONITOR # Slow query log (queries over 10ms) docker exec valkey valkey-cli -a YourStrongValkeyPassword! SLOWLOG GET 10 # Key count by pattern docker exec valkey valkey-cli -a YourStrongValkeyPassword! INFO keyspace
Step 5: Migrate from Redis to Valkey
<code"># For Docker users — just change the image: # FROM: image: redis:7-alpine # TO: image: valkey/valkey:8-alpine # For bare-metal: sudo systemctl stop redis-server sudo apt remove redis-server sudo apt install valkey-server # Copy existing redis.conf settings to valkey.conf # Valkey reads the same configuration format # Dump Redis data and restore to Valkey: redis-cli -a OLD_PASS --rdb /tmp/dump.rdb BGSAVE # Copy dump.rdb to new Valkey data directory # Valkey reads Redis RDB dump format natively
Getting Started
Valkey is a drop-in Redis replacement — same resource footprint (50–200 MB RAM depending on data), same commands, same client libraries. Deploy on any Ubuntu VPS at VPS.DO via Docker or apt package. For new projects, use Valkey from the start; for existing Redis deployments, migration is as simple as changing the Docker image and potentially the package name.
Conclusion
Valkey provides Redis-compatible in-memory data storage under a perpetual BSD license — eliminating concerns about Redis’s SSPL licensing for commercial and self-hosted deployments. The API is identical, client libraries work without changes, and data formats are compatible. For caching, session storage, pub/sub messaging, and job queues, Valkey is the recommended open-source choice for new VPS deployments and the natural migration path for existing Redis users.