Roadmap
Recached competes on where the data can live — the same engine on the server and in the browser, with sync in between. The benchmarks show this costs nothing in raw speed.
Ordered by priority.
1. Rate-limiting commands ✅ shipped
RLSET key limit window / RLCHECK key [limit window]. A built-in sliding-window rate limiter that replaces hand-rolled INCR+EXPIRE (racy) or Lua script approaches. RLCHECK returns [allowed, remaining, retry_after_ms] — a direct fit for X-RateLimit-* / Retry-After headers — and the inline config form auto-creates self-cleaning per-IP/per-user limiters in a single command. See Commands → Rate Limiting.
2. Scoped sync and per-client auth ✅ shipped
Every WebSocket connection can now be scoped to glob patterns via the SYNC command, and the mutation fan-out delivers only matching keys. With RECACHED_SYNC_SECRET set, scopes become a real authorization boundary: connections present an HMAC-signed token minted by your backend (SYNC TOKEN <token>), and every command — reads included — is checked against the granted patterns; admin/keyspace-wide commands are refused. See Sync Scopes.
3. Live queries — "Redis that renders" ✅ shipped
QSUB pattern returns the current state of every matching key and then streams keychange diffs — initial state plus diffs, not fire-and-forget events — scope-checked under strict sync scoping. The client half makes it a one-liner in React and Vue:
const cart = useKeys('cart:item:*'); // current matching keys + live updatesServer write → diff over WebSocket → local WASM cache → component re-render, with zero application glue. See Commands → Live Queries and useKeys.
4. Native JSON type ✅ shipped
JSET key path value, JGET key [path], JMERGE key patch — nested JSON stored as a native type, without RedisJSON. Path reads and partial updates never re-serialize the whole document, and only the change travels over the wire. JMERGE follows RFC 7386 (deep merge, null removes fields). The browser SDK mirrors all three (jset/jget/jmerge), so a merge from any client updates every connected browser's local document. See Commands → JSON.
5. Offline-first writes with merge semantics ✅ shipped
Browser clients queue writes as operations in a durable outbox while offline (IndexedDB-backed with persistence enabled, so they survive a full page reload), auto-reconnect with backoff, re-establish the session (auth, sync token, live queries — which re-hydrate local state), and replay the outbox. Writes are retired only on server acknowledgment (at-least-once delivery). Operation replay makes merges type-aware: incr/decr queue deltas that merge additively (PN-counter semantics), jmerge patches deep-merge, collection ops replay, and plain set is last-writer-wins by server arrival. See Offline & Reconnection.
6. Mobile SDKs — React Native, Flutter, Kotlin, Swift
- Kotlin + Swift first, via a single
uniffi-annotated Rust crate that generates bindings for both. The platform WebSocket (OkHttp / URLSession) feeds frames intosync-client— no embedded async runtime. Persistence: a file/SQLite adapter over the same outbox/meta effects the browser maps to IndexedDB. Reactivity: KotlinFlow/ SwiftObservationover keychange pushes. - Flutter via
flutter_rust_bridge: synchronous local reads into Rust memory,watchKey()→Streamfor rebuilds. - React Native last (Hermes has no WASM):
uniffi-bindgen-react-nativereuses the same binding layer, and the existing React hooks API carries over — sameuseKeyin React DOM and React Native.
7. WASM server-side scripting
Run .wasm stored procedures in place of Lua scripts. The scripting VM would be sandboxed (no network, no file I/O, bounded execution time), accept any WASM module that exports a specific entry function, and execute it against the cache store. Supports any language that compiles to WASM: Rust, Go (TinyGo), AssemblyScript, Python.
8. WASI target
A wasm32-wasip1 build of wasm-edge for Cloudflare Workers and Deno Deploy, running Recached as a cache layer at the edge with the same API as the browser client.
core-engine is already wasm32-compatible; the work is adapting the WebSocket and persistence layers to WASI. Last on the list because the platform fights the model — Workers cannot hold persistent WebSockets outside Durable Objects — and edge platforms ship native KV stores.
Ongoing: drop-in credibility
Not features, but continuous work that keeps "any Redis client works today" honest:
- Binary-safe WebSocket values — values over WS are currently UTF-8 (lossy for raw bytes); binary frames would make the two transports equivalent.
- RESP3 — push protocol support on the TCP port.
- Command coverage — closing gaps in the supported command set as real workloads surface them (see Commands).
Feedback on priorities is welcome — open an issue or write to dennis@thinkgrid.dev.