Skip to main content

Cachemate

Self-healing, multi-node Redis cache client with table-version auto-invalidation and in-memory LRU failover.

Cachemate eliminates stale database caches and Redis outages without complex cache-aside boilerplate. It combines composite table-version key derivation with multi-node connection pooling and automatic in-memory fallback.

pnpm add cachemate

Key Features

  • Table-Version Invalidation: Invalidate entire SQL joins and entity collections in $O(1)$ time by incrementing a single version counter.
  • Multi-Node Failover & Connection Pooling: Pool primary and replica Redis/Valkey instances with automatic failover, health checks, and OOM circuit breaking.
  • In-Memory LRU Failover: If all Redis instances go down or run out of memory, Cachemate seamlessly routes traffic to a bounded in-memory LRU cache with zero downtime.
  • Zero Cache Stampedes: Non-blocking background fills and deterministic key hashing ensure concurrent misses never overwhelm your upstream database.
  • Strict TypeScript & Zero-Config JavaScript: Full type safety with generic return types, strict ClientOptions, and safe runtime fallbacks for pure JS environments.
  • PostgreSQL Real-Time Invalidation: Built-in support for PostgreSQL LISTEN / NOTIFY triggers to invalidate caches instantaneously on row mutations.

Architecture Diagram

┌────────────────────────────┐
│ Application / API Layer │
└──────────────┬─────────────┘

client.cache() / rows() / flat()


┌────────────────────────────┐
│ Cachemate Core │
│ - Deterministic Key Gen │
│ - Table Version Registry │
│ - Pool Run Coordinator │
└──────────────┬─────────────┘

┌──────────────────┴──────────────────┐
▼ ▼
┌──────────────────────┐ ┌──────────────────────┐
│ Redis Node Pool │ │ MemoryStore (LRU) │
│ ┌──────────────────┐ │ Failover / │ - Bounded MB Cap │
│ │ Redis Primary │ │ OOM Circuit │ - Byte Size Calc │
│ ├──────────────────┤ │ ────────────►│ - In-Process Cache │
│ │ Redis Replica │ │ (Zero DB │ - Auto-fallback │
│ └──────────────────┘ │ Downtime) └──────────────────────┘
└──────────┬───────────┘

│ (Cache Miss)

┌──────────────────────┐
│ Database / Loader Fn │
│ (PostgreSQL, MySQL, │◄─────── Invalidation Triggers (LISTEN/NOTIFY)
│ Prisma, Drizzle) │
└──────────────────────┘

When to use Cachemate vs standard Redis

Feature / ScenarioStandard Redis Client (ioredis / redis)Cachemate
Relational / Join CachingManual key deletion, manual tag sets, pattern scanning (KEYS * / SCAN)Composite Table Version Keys: $O(1)$ invalidation of multi-table joins
Cache InvalidationProne to stale reads or missing keys on related table updatesAutomatic: Increment table version counter; old keys expire naturally via TTL
Redis Outages / Network SplitsThrows errors, drops requests, or requires custom fallback logicAutomatic In-Memory LRU: Uninterrupted service with bounded memory footprint
Redis OOM (command disabled)Application crashes or fails write operationsOOM Backoff: Advances to next node or memory store until memory pressure clears
Row-Level Queries + Filter ListsEither cache whole JSON array or write complex multi-tier cachingclient.rows(): Automatic two-tier caching (query ID list + entity rows)
Database SyncWrite bespoke webhook / pubsub integrationBuilt-in startPgInvalidationListener: Plug-and-play Postgres triggers

Next Steps