Skip to main content
Key0 requires two stores to operate and supports an optional third for auditing: Both Redis and Postgres backends ship with @key0ai/key0. They provide identical atomic guarantees — Redis via Lua scripts, Postgres via serializable transactions.

Choosing a backend

Use Redis when you want:
  • Sub-millisecond latency on reads and writes
  • Simple infrastructure (single Redis instance or cluster)
  • Automatic key expiration via TTLs
Redis stores challenge records as hashes, uses SET NX for transaction dedup, and runs Lua scripts for atomic compare-and-swap state transitions.

Setup

Configuration options

RedisChallengeStore accepts a RedisStoreConfig object:RedisSeenTxStore and RedisAuditStore accept only redis and keyPrefix.

Key naming

All keys are prefixed with keyPrefix (default key0):

TTL behavior

Atomic transitions

State transitions use a Lua script that runs entirely within Redis. The script:
  1. Reads the current state (compare)
  2. Writes the new state and field updates (swap)
  3. Maintains the key0:paid sorted set (add on PAID, remove on exit from PAID)
  4. Appends an audit entry to the challenge’s audit list
All four steps execute atomically — no other command can interleave.

Health check

Call healthCheck() at startup to fail fast on misconfiguration:

IAuditStore

The audit store is optional but recommended for production. Every state transition is logged with:
  • challengeId and requestId for correlation
  • fromState and toState for the transition
  • actor (e.g., "engine", "cron", "admin")
  • reason (optional, e.g., "challenge_created", "payment_verified")
  • updates (the field changes applied in the transition)
  • createdAt timestamp
Both RedisAuditStore and PostgresAuditStore implement IAuditStore. In addition, RedisChallengeStore and PostgresChallengeStore automatically write audit entries during create() and transition() calls — even without a standalone audit store configured.

Standalone (Docker) storage

When running Key0 as a standalone Docker container, set the STORAGE_BACKEND environment variable to select your backend:
Redis is always required in standalone mode, even when using Postgres as the primary storage backend. The BullMQ-based refund cron job uses Redis as its queue broker.

Connection health

Always verify your storage connection at startup. A misconfigured or unreachable store causes silent failures — challenges are created but never persisted, and payments cannot be verified.
For Redis, call store.healthCheck() before accepting traffic. For Postgres, the auto-migration step serves as an implicit health check — if it fails, the store constructor’s internal ready promise rejects, and subsequent operations throw.