Redis stores keys and values as byte strings — any UUID format works as a key or value. The question is which UUID version to use where, and how to take advantage of UUID v7’s embedded timestamp in Redis data structures. This guide covers four patterns: direct key naming, Redis Streams event IDs, sorted sets ordered by UUID v7 timestamp, and session storage. All examples use the uuid npm package for Node.js and the uuid6 package on PyPI for Python.
Key naming with UUID v7
UUID v7 keys in Redis give you time-ordered access without a separate sort field:
session:019236a7-b4f2-7000-8d3e-9c1a2b3d4e5f
order:019236a7-b4f4-7000-8e2f-7b4c5d6e7f80
event:019236a7-b4f6-7000-9a1b-6c5d4e3f2a91
Using SCAN with a pattern prefix lists all keys of a type; the UUID v7 values returned are already in approximate chronological order (within-prefix ordering matches creation time). The Redis SCAN documentation covers pattern matching and cursor-based iteration.
Session storage with UUID v7
import { v7 as uuidv7 } from 'uuid';
import { createClient } from 'redis';
const redis = createClient();
async function createSession(userId: string): Promise<string> {
const sessionId = uuidv7(); // UUID v7 session key
await redis.setEx(
`session:${sessionId}`,
3600, // TTL: 1 hour
JSON.stringify({ userId, createdAt: Date.now() })
);
return sessionId;
}
Note: This is an example of Redis caching — session tokens sent to clients should use crypto.randomBytes(32).toString('hex') (256-bit random, no timestamp) rather than UUID v7. UUID v7 in a cookie reveals session creation time. Use UUID v7 for internal record IDs only. The OWASP Web Security Testing Guide covers session token requirements.
Redis Streams with UUID v7 correlation IDs
Redis Streams are a natural fit for event pipelines. Use UUID v7 as a correlation ID field alongside the Redis auto-generated stream ID:
import redis
import uuid6
r = redis.Redis()
# Add event to stream with UUID v7 correlation ID
r.xadd('orders', {
'correlation_id': str(uuid6.uuid7()), # UUID v7 for cross-service tracing
'order_id': str(uuid6.uuid7()),
'event_type': 'ORDER_PLACED',
'payload': '{"items": 3}'
})
# Read from stream
messages = r.xread({'orders': '0'}, count=100)
The Redis-generated stream ID (1727308800000-0) handles within-Redis ordering. The UUID v7 correlation_id ties the event to records in PostgreSQL and other services. The Redis Streams documentation covers consumer groups, acknowledgement, and pending entries.
Sorted sets ordered by UUID v7 timestamp
Extract the timestamp from a UUID v7 to use as a sorted set score:
import { v7 as uuidv7 } from 'uuid';
function uuidToScore(uuid: string): number {
return parseInt(uuid.replace(/-/g, '').slice(0, 12), 16); // Unix ms
}
const id = uuidv7();
const score = uuidToScore(id);
// Add to sorted set with timestamp as score
await redis.zAdd('user:events', [{ score, value: id }]);
// Query events in a time window
const start = Date.now() - 3600_000; // 1 hour ago
const end = Date.now();
const recent = await redis.zRangeByScore('user:events', start, end);
This pattern replaces a ZRANGEBYSCORE on a separate created_at field — the UUID v7 itself encodes the timestamp. The Redis ZRANGEBYSCORE command supports +inf and -inf bounds for open-ended queries.
Cache key design
For cache entries keyed by UUID v7 (caching database rows by their primary key):
import uuid6
def cache_key(table: str, record_id: str) -> str:
return f"{table}:{record_id}"
# Cache a database row
record_id = "019236a7-b4f2-7000-8d3e-9c1a2b3d4e5f"
r.setex(cache_key("orders", record_id), 300, serialised_order)
# Extract timestamp to set TTL proportional to record age
ts_ms = uuid6.UUID(record_id).time
age_s = (time.time() * 1000 - ts_ms) / 1000
ttl = max(60, int(3600 - age_s)) # Older records get shorter TTL
r.setex(cache_key("orders", record_id), ttl, serialised_order)
Using the UUID v7 timestamp to set adaptive TTLs means recently created records stay cached longer — a pattern that works because UUID v7 always encodes a reliable creation time per RFC 9562 §5.7.
Redis Cluster and UUID v7 hash slots
Redis Cluster assigns each key to a hash slot (0–16383) by hashing the key or a hash tag {...} within the key. UUID v7 keys distribute evenly across hash slots because the random bits in positions 64–127 vary for every key. No special configuration is needed for UUID keys in Redis Cluster. The Redis Cluster specification explains the CRC16 hash slot algorithm.
Further reading
- UUID Security — when not to use UUID v7 in externally visible keys
- UUID v7 in Distributed Systems — multi-service tracing
- UUID Generation Strategies — server vs client generation
External references
- Redis documentation
- uuid npm package
- uuid6 on PyPI
- RFC 9562 — UUID standard
- OWASP Web Security Testing Guide
Frequently asked questions
Can I use a UUID as a Redis key directly?
Yes. Redis keys are binary-safe strings — a UUID string like 018f4b2a-7c3d-7000-8e5f-1a2b3c4d5e6f is a valid Redis key. UUID v7 keys also work well with Redis Cluster because the hash slot for a UUID key is determined by the full key value, distributing load evenly across shards. For namespace-scoped keys, use a prefix: session:018f4b2a-7c3d-7000-.... The Redis keyspace documentation covers key naming conventions.
How do UUID v7 IDs compare to Redis Stream auto-generated IDs?
Redis Streams auto-generate IDs in the format millisecondsTimestamp-sequenceNumber (e.g. 1727308800000-0). UUID v7 encodes a 48-bit millisecond timestamp in its leading bits — the same granularity. The difference is that Redis Stream IDs are compact integers while UUID v7 values are 128-bit and globally unique across systems. Use Redis auto-IDs for within-Redis ordering; use UUID v7 for IDs that must be unique across databases and services. See the Redis Streams documentation.
How do I sort Redis sorted set members by UUID v7 creation time?
Store the Unix millisecond timestamp as the score and the UUID v7 string as the member: ZADD events 1727308800000 "018f4b2a-7c3d-7000-...". To retrieve by time range: ZRANGEBYSCORE events minTs maxTs. Alternatively, use the UUID v7 string itself as the score by extracting the timestamp with parseInt(uuid.replace(/-/g,'').slice(0,12), 16) in your application before the ZADD call. The Redis ZADD documentation covers score ranges and ordering.