Skip to content

feat: add Store.redis() for standard Redis/ioredis/Valkey clients#210

Merged
tmm merged 3 commits intowevm:mainfrom
tenequm:feat/store-redis
Mar 23, 2026
Merged

feat: add Store.redis() for standard Redis/ioredis/Valkey clients#210
tmm merged 3 commits intowevm:mainfrom
tenequm:feat/store-redis

Conversation

@tenequm
Copy link
Copy Markdown
Contributor

@tenequm tenequm commented Mar 20, 2026

Adds Store.redis() - a new store adapter for standard Redis clients that handles BigInt-safe serialization internally.

Closes #208

Problem

Store.upstash() works because the Upstash REST SDK auto-serializes JSON (including BigInt) on their end. Standard Redis clients (ioredis, node-redis, Valkey) only accept strings, so passing channel state with BigInt fields directly to client.set() either throws or corrupts data.

Anyone running self-hosted Redis/Valkey has to write a custom store adapter with BigInt-safe serialization - which is error-prone and every self-hosted user rediscovers independently.

Solution

Store.redis() accepts any client with standard get/set/del string methods and handles serialization internally using ox's Json.parse/Json.stringify (same as Store.cloudflare() and Store.memory() already do):

import { Store } from 'mppx/server'
import Redis from 'ioredis'

const redis = new Redis('redis://localhost:6379')
const store = Store.redis(redis)

Interface

export function redis(client: redis.Parameters): Store

export declare namespace redis {
  type Parameters = {
    get: (key: string) => Promise<string | null>
    set: (key: string, value: string) => Promise<unknown>
    del: (key: string) => Promise<unknown>
  }
}

Works with ioredis, node-redis (@redis/client), Valkey, and any Redis-compatible client without requiring a specific package dependency.

Tests

  • Added redis to the existing describe.each test matrix (roundtrip, missing key, delete, overwrite)
  • Added redis json-roundtrips nested objects test
  • Added redis roundtrips BigInt values test (the core issue this solves)

All 21 tests pass.

Adds a new Store.redis() adapter that accepts any client with standard
get/set/del string methods and handles BigInt-safe serialization
internally using ox's Json.parse/Json.stringify.

This fills the gap between Store.memory() (not suitable for production
multi-instance deployments) and Store.upstash() (requires Upstash's
REST SDK which auto-serializes JSON). Standard Redis clients only
accept strings, so passing channel state with BigInt fields directly
to client.set() either throws or corrupts data.

Store.redis() works with ioredis, node-redis (@redis/client), Valkey,
and any Redis-compatible client without requiring a specific package
dependency.

Closes wevm#208
@tmm tmm merged commit d9b651d into wevm:main Mar 23, 2026
2 checks passed
@tenequm tenequm deleted the feat/store-redis branch March 23, 2026 15:55
brendanjryan pushed a commit that referenced this pull request Mar 24, 2026
* feat: add Store.redis() for standard Redis/ioredis/Valkey clients

Adds a new Store.redis() adapter that accepts any client with standard
get/set/del string methods and handles BigInt-safe serialization
internally using ox's Json.parse/Json.stringify.

This fills the gap between Store.memory() (not suitable for production
multi-instance deployments) and Store.upstash() (requires Upstash's
REST SDK which auto-serializes JSON). Standard Redis clients only
accept strings, so passing channel state with BigInt fields directly
to client.set() either throws or corrupts data.

Store.redis() works with ioredis, node-redis (@redis/client), Valkey,
and any Redis-compatible client without requiring a specific package
dependency.

Closes #208

* chore: changeset

---------

Co-authored-by: tmm <tmm@tmm.dev>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Add Store.redis() for standard Redis/ioredis/Valkey clients

2 participants