relay-session-redis
v1.0.0
Published
Redis store adapter for relay-session.
Maintainers
Readme
relay-session-redis
Redis store adapter for relay-session.
Implements the full SessionStoreAdapter interface including:
merge()— atomic partial writes via a Lua script (no last-write-wins on concurrent requests)lock()/unlock()/isLocked()— distributed locking viaSET NX PX
Installation
npm install relay-session-redis ioredisUsage
import {Redis} from 'ioredis'
import {sessionMiddleware} from 'relay-session'
import {createRedisSessionStore} from 'relay-session-redis'
const redis = new Redis()
app.use(sessionMiddleware({
store: createRedisSessionStore(redis),
cookie: {name: 'sid', secret: process.env.SESSION_SECRET!, ttl: 3_600_000},
}))Options
createRedisSessionStore(redis, options ?)| Option | Type | Default | Description |
|-----------------|-----------|-----------|--------------------------------------------------------------------------------------------------------------------------------------------------|
| prefix | string | 'sess:' | Key prefix for session data. Example: sess:<sessionId> |
| lockPrefix | string | 'lock:' | Lock key prefix, appended after prefix. Example: sess:lock:<sessionId> |
| preloadScript | boolean | false | Preloads the Lua merge script into Redis on store creation via SCRIPT LOAD. Otherwise the script is loaded lazily on the first merge() call. |
Key Layout
sess:<sessionId> session data (JSON)
sess:lock:<sessionId> distributed lockmerge() — Atomic Partial Writes
When merge() is available, relay-session sends only the changed dot-paths to the store instead of the full session
object. This avoids last-write-wins data loss when concurrent requests modify different fields.
The adapter applies these updates atomically via a Lua script — the read-modify-write happens in a single Redis operation:
// Paths received from relay-session:
{ 'data.user.name': 'Pascal' }
{ 'data.cart': [1, 2, 3] }
{ 'meta': { id: '...', expiresAt: ... } } // on rotation
{ 'data': null, 'meta': { redirectTo: '...' } } // redirect entriesIf the session key has expired before merge() is called, the Lua script is a no-op (no error).
lock() / unlock() / isLocked() — Distributed Locking
lock() uses SET key 1 NX PX ttlMs — a single atomic Redis command. Only one request can acquire the lock; concurrent
callers receive false and retry with backoff (controlled by relay-session's lock.retries and lock.backoff
options).
The lock.ttl option in relay-session controls the lock expiry. If a request crashes while holding the lock, Redis
automatically expires it after ttl ms.
Requirements
- Redis 5.0 or later (
EVALwithcjsonis available in all versions; no Redis modules required) - ioredis
^5 - Node.js
>=18.15.0
