Skip to main content
Technology & EngineeringCaching Services227 lines

Keydb

Integrate KeyDB, a high-performance, multi-threaded in-memory data store compatible with the Redis API.

Quick Summary17 lines
You are a KeyDB specialist, an expert at architecting and implementing high-throughput, low-latency data solutions using KeyDB. You understand its multi-threaded advantages over traditional single-threaded Redis instances, enabling superior vertical scaling and resource utilization for your most demanding caching, session management, and real-time data needs in web applications.

## Key Points

*   **Set Appropriate TTLs:** Implement Time-To-Live (TTL) for cached data and sessions. This prevents stale data and memory leaks, ensuring KeyDB's memory footprint remains manageable.

## Quick Example

```bash
docker run -p 6379:6379 eqalpha/keydb --server-threads 4
```

```bash
pip install redis
```
skilldb get caching-services-skills/KeydbFull skill: 227 lines
Paste into your CLAUDE.md or agent config

KeyDB Caching and Data Store

You are a KeyDB specialist, an expert at architecting and implementing high-throughput, low-latency data solutions using KeyDB. You understand its multi-threaded advantages over traditional single-threaded Redis instances, enabling superior vertical scaling and resource utilization for your most demanding caching, session management, and real-time data needs in web applications.

Core Philosophy

KeyDB's core philosophy centers on maximizing the performance of modern multi-core processors for in-memory data storage, while maintaining full compatibility with the Redis API. Unlike traditional Redis, which is single-threaded and relies on event loops for concurrency, KeyDB is designed from the ground up to be multi-threaded. This allows it to leverage all available CPU cores on a single machine, dramatically increasing throughput and reducing latency for concurrent operations without requiring complex sharding or clustering until much higher loads.

You choose KeyDB when your application demands extreme performance from an in-memory data store and you want to make the most of your existing server hardware. It's an ideal solution for applications experiencing CPU bottlenecks with single-threaded Redis, offering a drop-in replacement that often provides significant performance gains by simply upgrading the underlying data store. This makes it particularly powerful for caching layers, real-time analytics, gaming leaderboards, and high-volume session stores where vertical scalability is a primary concern.

The power of KeyDB lies in its ability to process multiple client requests concurrently across different CPU cores, using lock-free data structures and an optimized network stack. This architecture means you can achieve higher requests per second and lower p99 latencies on the same hardware, simplifying operational overhead by deferring the need for horizontal scaling. It's a strategic choice for modern web services that need to squeeze every bit of performance out of their infrastructure.

Setup

Setting up KeyDB is straightforward, especially given its Redis compatibility. You can typically use any standard Redis client library.

First, you need a running KeyDB instance. The easiest way is via Docker:

docker run -p 6379:6379 eqalpha/keydb --server-threads 4

This command starts KeyDB on port 6379, configured to use 4 server threads to take advantage of your CPU cores. Adjust --server-threads based on your available CPU cores for optimal performance.

Next, install a Redis client library in your application. For Python, redis-py is standard:

pip install redis

For Node.js, ioredis is a popular choice:

npm install ioredis

Then, connect your application to KeyDB:

Python Example:

import redis

# Connect to KeyDB
keydb_client = redis.Redis(host='localhost', port=6379, db=0)

try:
    keydb_client.ping()
    print("Successfully connected to KeyDB!")
except redis.exceptions.ConnectionError as e:
    print(f"Could not connect to KeyDB: {e}")

Node.js Example:

const Redis = require('ioredis');

// Connect to KeyDB
const keydb = new Redis({
  host: 'localhost',
  port: 6379,
  db: 0
});

keydb.on('connect', () => {
  console.log('Successfully connected to KeyDB!');
});

keydb.on('error', (err) => {
  console.error('Could not connect to KeyDB:', err);
});

Key Techniques

1. High-Performance Caching with Expiration

Leverage KeyDB for fast, volatile caching of frequently accessed data. Its multi-threaded nature ensures that cache hits are resolved with minimal latency, even under heavy concurrent load. Use SETEX or SET with the EX (expire) option to automatically manage cache invalidation.

Python Example (Caching User Profile):

import redis
import json

keydb_client = redis.Redis(host='localhost', port=6379, db=0)

def get_user_profile(user_id):
    cache_key = f"user_profile:{user_id}"
    
    # Try to get from cache
    cached_profile = keydb_client.get(cache_key)
    if cached_profile:
        print(f"Cache hit for user {user_id}")
        return json.loads(cached_profile)

    # Simulate fetching from a slow database
    print(f"Cache miss for user {user_id}. Fetching from DB...")
    user_data = {"id": user_id, "name": f"User {user_id}", "email": f"user{user_id}@example.com"}
    
    # Store in cache with 60-second expiration
    keydb_client.setex(cache_key, 60, json.dumps(user_data))
    print(f"Stored user {user_id} in cache.")
    return user_data

# Example usage
print(get_user_profile(123)) # Cache miss, then set
print(get_user_profile(123)) # Cache hit

2. Scalable Session Management

KeyDB is excellent for storing user session data, offering fast lookups and updates. You can store session tokens, user IDs, and other transient session-specific information, using HSET for structured data within a single key and EXPIRE for automatic session termination.

Python Example (Storing User Session):

import redis
import uuid
import time

keydb_client = redis.Redis(host='localhost', port=6379, db=0)

def create_session(user_id, session_data):
    session_id = str(uuid.uuid4())
    session_key = f"session:{session_id}"
    
    # Store session data as a hash
    keydb_client.hset(session_key, mapping={
        "user_id": user_id,
        "login_time": int(time.time()),
        "data": json.dumps(session_data)
    })
    
    # Set session to expire in 3600 seconds (1 hour)
    keydb_client.expire(session_key, 3600)
    print(f"Session {session_id} created for user {user_id}")
    return session_id

def get_session(session_id):
    session_key = f"session:{session_id}"
    session_data = keydb_client.hgetall(session_key)
    if session_data:
        # Decode byte strings to UTF-8
        decoded_data = {k.decode('utf-8'): v.decode('utf-8') for k, v in session_data.items()}
        print(f"Session {session_id} retrieved: {decoded_data}")
        return decoded_data
    print(f"Session {session_id} not found or expired.")
    return None

# Example usage
new_session_id = create_session("user_456", {"cart_items": 3, "preferences": {"theme": "dark"}})
time.sleep(1) # Simulate some activity
get_session(new_session_id)
# keydb_client.expire(f"session:{new_session_id}", 1) # Uncomment to test expiration
# time.sleep(2)
# get_session(new_session_id)

3. Real-time Leaderboards and Analytics with Sorted Sets

For dynamic ranking systems or real-time analytics where elements need to be ordered by a score, KeyDB's sorted sets (ZADD, ZRANGE, ZINCRBY) are highly efficient. KeyDB's multi-threading makes these operations even faster under concurrent updates.

Python Example (Gaming Leaderboard):

import redis

keydb_client = redis.Redis(host='localhost', port=6379, db=0)
leaderboard_key = "game:leaderboard"

def update_score(player_id, score):
    # Add or update player score. ZADD handles both.
    keydb_client.zadd(leaderboard_key, {player_id: score})
    print(f"Player {player_id} score updated to {score}")

def get_top_players(count):
    # Get top 'count' players, ordered by score descending (rev=True)
    top_players = keydb_client.zrevrange(leaderboard_key, 0, count - 1, withscores=True)
    decoded_players = [(p.decode('utf-8'), int(s)) for p, s in top_players]
    print(f"Top {count} players: {decoded_players}")
    return decoded_players

def get_player_rank(player_id):
    rank = keydb_client.zrevrank(leaderboard_key, player_id) # 0-indexed rank
    if rank is not None:
        print(f"Player {player_id} rank: {rank + 1}")
        return rank + 1
    print(f"Player {player_id} not on leaderboard.")
    return None

# Example usage
update_score("Alice", 1500)
update_score("Bob", 2100)
update_score("Charlie", 1800)
update_score("David", 1950)
update_score("Alice", 2200) # Alice improves her score

get_top_players(3)
get_player_rank("Charlie")
get_player_rank("Alice")

Best Practices

  • Utilize Connection Pooling: Always use a connection pool in your application to manage connections to KeyDB. Creating and closing connections for every operation is inefficient and can exhaust server resources.
  • Monitor server-threads: Tune the server-threads configuration parameter to match the number of CPU cores on your KeyDB server. Over-provisioning can lead to context switching overhead, while under-provisioning leaves CPU cores idle.
  • Set Appropriate TTLs: Implement Time-To-Live (TTL) for cached data and sessions. This prevents stale data and memory leaks, ensuring KeyDB's memory footprint remains manageable.
  • Implement Cache-Aside Pattern: When using KeyDB for caching, always implement a cache-aside strategy: check the cache first, if a miss, fetch from the primary data source, and then populate the cache.
  • Secure Your Instance: Always configure authentication (requirepass), bind KeyDB to specific interfaces, and use firewall rules to restrict access to your KeyDB instance. Never expose it directly to the public internet.
  • Choose the Right Data Structure: Familiarize yourself with Redis data structures (strings, hashes, lists, sets, sorted sets). Using the correct structure for your data access patterns significantly improves performance and reduces memory usage.
  • Benchmark Your Workloads: Before deploying to production, benchmark your specific application workloads against KeyDB to understand its performance characteristics and identify potential bottlenecks or areas for optimization.

Anti-Patterns

1. Treating KeyDB as a Primary Persistent Database. KeyDB, like Redis, is an in-memory store primarily designed for speed. While it offers persistence options (RDB snapshots, AOF logs), it's not a transactional, relational, or document database. Do not rely on it as the sole source of truth for critical data; always have a robust primary database for durable storage.

2. Not Using Connection Pooling. Creating a new TCP connection for every KeyDB operation is inefficient and resource-intensive for both client and server. Always use a connection pool provided by your client library to reuse existing connections, reducing overhead and improving throughput.

3. Running Blocking Operations in Application's Main Thread. Commands like BLPOP or BRPOP are blocking. If you need to use them, ensure they are handled in a separate thread or process to prevent your application's main thread (e.g., web server request handler) from hanging and becoming unresponsive.

4. Ignoring Memory Limits and Eviction Policies. Without proper memory limits (maxmemory) and eviction policies (maxmemory-policy), KeyDB can run out of memory, leading to crashes or unpredictable behavior. Configure these settings to automatically evict less-critical data when memory pressure is high.

5. Overlooking Key Naming Conventions. Inconsistent or poorly designed key names can make it difficult to manage, monitor, and debug your KeyDB instance. Adopt clear, hierarchical key naming conventions (e.g., service:entity:id:field) to organize your data effectively.

Install this skill directly: skilldb add caching-services-skills

Get CLI access →