UpstashStore — Upstash Redis (serverless Redis over HTTP)
Read this page in the documentation
UpstashStore — Upstash Redis (serverless Redis over HTTP) Overview Upstash Redis is a serverless, globally-replicated Redis served over an HTTP/REST connection via the @upstash/redis client. It has no SQL query surface, so UpstashStore implements the minimal NoSqlStore marker interface (src/nosql/store.ts) — connection lifecycle plus a getClient() escape hatch — and exposes an edge-KV get/set/del/list/incr surface mapped onto the @upstash/redis client. Identity: Property | Value | --------- | ----------------- | name | 'upstash' | library | '@upstash/redis'| Driver — lazy-loaded Uses @upstash/redis (new Redis({ url, token })). The driver is not a hard dependency: it is loaded lazily via require('@upstash/redis') inside connect() (resolving mod.Redis ?? mod.default ?? mod), so importing this module never requires @upstash/redis to be installed unless a store is actually connected. Injected client UpstashStoreOptions accepts a pre-built client implementing the UpstashRedisClient interface. When provided, connect() uses it directly and skips require('@upstash/redis'). This is how the test suite injects a method-spy mock (no driver, no network). Values are serialized before writing: strings are stored verbatim; every other value is JSON.stringify'd. Connection Build a store from connection options and call connect(): Connection options: Option | Type | Purpose | -------- | -------------------- | ------------------------------------------------------------------------------------ | url | string | REST URL of the Upstash Redis database. | token | string | REST API token. | client | UpstashRedisClient | Pre-built @upstash/redis client; when set, connect() uses it and skips require. | All options are optional (UpstashStoreOptions = {}); url/token are forwarded to new Redis(...) when the driver is loaded. Injected-client form Methods Each operation routes to the corresponding @upstash/redis client method. Driver failures are wrapped in a DatabaseError; using any method before connect() (or after disconnect()) throws a ConnectionError. Lifecycle Method | Signature | Behavior | ------------- | ---------------------------------- | -------------------------------------------------------------------------------------------------- | connect | connect(): Promise<void> | Uses an injected client if provided, otherwise lazy-requires @upstash/redis and builds a Redis. Idempotent. Wraps failures in ConnectionError. | disconnect | disconnect(): Promise<void> | Clears the client and connection state. | isConnected | isConnected(): boolean | true only when connected and a client is present. | getClient | getClient(): UpstashRedisClient | Returns the underlying @upstash/redis client. Throws ConnectionError if not connected. | Key-value operations Method | Signature | Client call | Behavior | ------- | --------------------------------------------------------------------------- | ---------------------------------- | --------------------------------------------------------------------------------------------------- | get | get(key: string): Promise<any> | client.get(key) | Reads a key. Returns whatever the client returns (null if missing). | set | set(key: string, value: unknown, options?: UpstashSetOptions): Promise<any> | client.set(key, value, opts?) | Writes value (serialized). options.ttl maps to Redis ex (seconds), options.expiration to exat (absolute Unix seconds). Passes undefined options when none are set. | del | del(key: string): Promise<number> | client.del(key) | Deletes a key. Returns the number of keys removed. | list | list(prefix?: string): Promise<string[]> | client.keys(pattern) | Lists key names via KEYS, matching <prefix> (or when no prefix). | incr | incr(key: string, by?: number): Promise<number> | client.incr / client.incrby | Atomically increments the value at key by by (default 1). Uses incr when by === 1, otherwise incrby(key, by). | UpstashSetOptions Example Verification status Unit / mock-verified only. The tests in tests/nosql/upstash.test.ts inject a method-spy mock UpstashRedisClient (get/set/del/keys/incr/incrby) via UpstashStoreOptions.client. The real @upstash/redis package is not installed and there is no network in the test run. What this proves: Each method routes to the correct client method with the correct arguments: get('k'), del('k'), keys('user:') / keys(''). set serializes non-strings ({ a: 1 } → '{"a":1}'), stores strings verbatim, and maps ttl → { ex: 60 } (passing undefined when no options). incr uses incr for by === 1 and incrby(key, by) otherwise. Lifecycle: connect/idempotent-connect/disconnect, getClient returning the injected client, and ConnectionError before connect(). Error handling: driver failures wrapped in DatabaseError. What this does not prove: live execution against a real Upstash Redis database. The method/argument mapping is verified against the @upstash/redis documented surface, but end-to-end execution over the wire has not been exercised here. Related reading All data stores — the full catalogue, grouped by purpose Database types — where this sits among the 22 categories