Generated banner for Upstash Redis JS
Generated logo for Upstash Redis JS

Upstash Redis JS

UpstashOfficialCreated by Upstash

  • Skill
  • Tool integration
  • Software development
  • MIT
  • No issues found

From the author

Work with the @upstash/redis TypeScript/JavaScript SDK, a serverless HTTP-based Redis client for Next.js, Vercel, Cloudflare Workers, edge runtimes, and Node.js. Use when adding a cache (cache-aside, write-through, TTL and expiration strategies), session storage and user sessions, a key-value store, leaderboards and rankings with sorted sets, counters, distributed locks, queues with lists, streams and consumer groups, sparse index-addressed arrays and ring buffers (ARSET, ARINSERT, ARRING, ARGREP, AROP), embeddings and nearest-neighbour vector search stored inside Redis (VECTOR commands via redis.vector, separate from @upstash/vector), JSON documents, pipelines and MULTI/EXEC transactions, Lua scripting, read replicas, or full-text search, typo-tolerant search, facets, aggregations, and search over Redis stream entries with Upstash Redis Search (different from regular FT.SEARCH; also available for TCP clients via @upstash/search-redis and @upstash/search-ioredis). Also use when migrating from ioredis or
— the description by Upstash

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill provides a complete reference for the @upstash/redis SDK, an HTTP-based Redis client designed for serverless environments like Vercel, Cloudflare Workers, and edge runtimes. It covers core data structures, advanced features like pipelines and Lua scripting, common architectural patterns such as caching and session management, and migration paths from traditional Redis clients. The SDK features automatic serialization of JavaScript types, simplifying data handling for developers.

What it does

  • Provides methods for interacting with Redis data structures including strings, hashes, lists, sets, sorted sets, and JSON.
  • Supports advanced Redis features like pipelines, MULTI/EXEC transactions, and Lua scripting.
  • Includes patterns for implementing caching, rate limiting, distributed locks, and session management.
  • Enables vector search and full-text search capabilities within Redis.
  • Handles automatic serialization and deserialization of native JavaScript types.
  • Offers migration guidance for developers moving from ioredis or node-redis.

When to use it

  • When building serverless applications that require a Redis-compatible key-value store.
  • When implementing caching, session storage, or leaderboards in edge runtimes.
  • When you need to perform atomic operations or complex server-side logic via Lua scripts.
  • When migrating existing Node.js applications to a serverless architecture.
  • When integrating AI agent memory or RAG tools using Redis.

Advantages

  • Serverless-friendly HTTP-based architecture eliminates connection pooling issues.
  • Automatic serialization removes the need for manual JSON parsing.
  • Comprehensive support for modern Redis features including JSON and vector search.
  • Well-defined patterns for common use cases like rate limiting and distributed locks.
  • Seamless integration with popular frameworks like Next.js and Vercel.

Usage examples

“How do I store a user object in Redis using the Upstash SDK?”
The agent will demonstrate using redis.set('user:1', { name: 'Alice' }), highlighting that the SDK automatically handles JSON serialization.
“Show me how to implement a simple counter in Redis.”
The agent will provide code using redis.incr('counter') and explain that the SDK returns the incremented number directly without manual parsing.
“How can I perform multiple operations atomically?”
The agent will explain the use of redis.multi() or pipelines to batch commands and ensure atomic execution.

Install

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/upstash/upstash-redis-js/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip upstash-redis-js.zip -d .agents/skills

Documentation by Upstash

Upstash Redis SDK - Complete Skills Guide

This directory contains comprehensive guides for using the @upstash/redis SDK. These skill files are designed to help developers and AI assistants understand and use the SDK effectively.

Bundled docs and source

Before writing or debugging SDK code, check node_modules/@upstash/redis/docs/ for bundled docs and node_modules/@upstash/redis/src/ for readable TypeScript source. Read and search the relevant files when present; otherwise use the references in this skill.

Installation

npm install @upstash/redis

Quick Start

Basic Initialization
import { Redis } from "@upstash/redis";

// Initialize with explicit credentials
const redis = new Redis({
  url: "UPSTASH_REDIS_REST_URL",
  token: "UPSTASH_REDIS_REST_TOKEN",
});

// Or initialize from environment variables
const redis = Redis.fromEnv();
Environment Variables

Set these in your .env file:

UPSTASH_REDIS_REST_URL=https://your-redis.upstash.io
UPSTASH_REDIS_REST_TOKEN=your-token-here

No credentials yet? If you're an agent that needs scratch Redis and the user hasn't provided a database, you can mint a temporary one with a single POST to https://upstash.com/start-redis (3-day TTL, no signup).

Skill Files Overview

Data Structures (data-structures/)

Redis data types with auto-serialization examples:

  • strings.md - GET, SET, INCR, DECR, APPEND with automatic type handling

  • hashes.md - HSET, HGET, HMGET with object serialization

  • lists.md - LPUSH, RPUSH, LRANGE with array handling

  • sets.md - SADD, SMEMBERS, set operations

  • sorted-sets.md - ZADD, ZRANGE, ZRANK, leaderboard patterns

  • json.md - JSON.SET, JSON.GET, JSONPath queries for nested objects

  • streams.md - XADD, XREAD, XGROUP, consumer groups

  • arrays.md - ARSET, ARINSERT, ARSCAN, ARGREP, AROP, ring buffers with ARRING on sparse index-addressed arrays

  • vector-indexes.md - VECTOR.CREATE, VECTOR.ADD, VECTOR.QUERY nearest-neighbour search inside Redis via redis.vector

Advanced Features (advanced-features/)

Complex operations and optimizations:

  • auto-pipeline.md - Automatic request batching, performance optimization

  • pipeline-and-transactions.md - Manual pipelines, MULTI/EXEC for atomic operations

  • scripting.md - Lua scripts, EVAL, EVALSHA for server-side logic

Patterns (patterns/)

Common use cases and architectural patterns:

  • caching.md - Cache-aside, write-through, TTL strategies

  • rate-limiting.md - Integration with @upstash/ratelimit package

  • session-management.md - Session storage and user state management

  • distributed-locks.md - Lock implementations, deadlock prevention

  • leaderboard.md - Sorted set leaderboards, real-time rankings

Performance (performance/)

Optimization techniques and best practices:

  • batching-operations.md - MGET, MSET, batch operations

  • pipeline-optimization.md - When to use pipelines, performance tips

  • ttl-expiration.md - Key expiration strategies, memory management

  • data-serialization.md - Deep dive into auto serialization, custom serializers, edge cases

  • error-handling.md - Error types, retry strategies, timeout handling, debugging tips

  • redis-replicas.md - Global database setup, read replicas, read-your-writes consistency

Full-text search, filtering, and aggregation extension for Redis:

  • overview.md - Schema definition, field types, pitfalls, package overview

  • commands/querying.md - Query and count with filters, pagination, sorting, highlighting

  • commands/aggregating.md - Metric aggregations ($avg, $sum, $stats), bucket aggregations ($terms, $range, $histogram, $facet)

  • commands/index-management.md - Create, describe, drop indexes (including stream indexes over XADD entries), waitIndexing

  • commands/aliases.md - Index aliases for zero-downtime reindexing

  • adapters.md - Using search with node-redis and ioredis via @upstash/search-redis and @upstash/search-ioredis

Migrations (migrations/)

Migration guides from other libraries:

  • from-ioredis.md - Migration from ioredis, key differences, serialization changes

  • from-redis-node.md - Migration from node-redis, API differences

Common Mistakes (Especially for LLMs)

❌ Mistake 1: Treating Everything as Strings
// ❌ WRONG - Don't do this with @upstash/redis
await redis.set("count", "42"); // Stored as string "42"
const count = await redis.get("count");
const incremented = parseInt(count) + 1; // Manual parsing needed

// ✅ CORRECT - Let the SDK handle it
await redis.set("count", 42); // Stored as number
const count = await redis.get("count");
const incremented = count + 1; // Just use it
❌ Mistake 2: Manual JSON Serialization
// ❌ WRONG - Unnecessary with @upstash/redis
await redis.set("user", JSON.stringify({ name: "Alice" }));
const user = JSON.parse(await redis.get("user"));

// ✅ CORRECT - Automatic handling
await redis.set("user", { name: "Alice" });
const user = await redis.get("user");

Quick Command Reference

// Strings
await redis.set("key", "value");
await redis.get("key");
await redis.incr("counter");
await redis.decr("counter");

// Hashes
await redis.hset("user:1", { name: "Alice", age: 30 });
await redis.hget("user:1", "name");
await redis.hgetall("user:1");

// Lists
await redis.lpush("tasks", "task1", "task2");
await redis.rpush("tasks", "task3");
await redis.lrange("tasks", 0, -1);

// Sets
await redis.sadd("tags", "javascript", "redis");
await redis.smembers("tags");

// Sorted Sets
await redis.zadd("leaderboard", { score: 100, member: "player1" });
await redis.zrange("leaderboard", 0, -1);

// JSON
await redis.json.set("user:1", "$", { name: "Alice", address: { city: "NYC" } });
await redis.json.get("user:1");

// Expiration
await redis.setex("session", 3600, { userId: "123" });
await redis.expire("key", 60);
await redis.ttl("key");

Best Practices

  1. Use environment variables for credentials, never hardcode

  2. Leverage auto-serialization - pass native JavaScript types

  3. Use TypeScript types for better type safety

  4. Set appropriate TTLs to manage memory

  5. Use pipelines for multiple operations

  6. Namespace your keys (e.g., user:123, session:abc)

AI agents: use AgentKit

For agent state on Redis — memory, chat history, RAG search tools, tool caching, rate limiting, chat persistence, resumable streams, locks — use Upstash AgentKit instead of hand-rolling it on @upstash/redis. Pick the adapter for the framework and follow its docs page:

FrameworkPackageDocs
Vercel AI SDK@upstash/agentkit-ai-sdkhttps://upstash.com/docs/redis/sdks/agentkit/ai-sdk
TanStack AI@upstash/agentkit-tanstack-aihttps://upstash.com/docs/redis/sdks/agentkit/tanstack-ai
Vercel Eve@upstash/agentkit-eve, @upstash/agentkit-eve-extensionhttps://upstash.com/docs/redis/sdks/agentkit/eve

Resources

Getting Help

For detailed information on specific topics, refer to the individual skill files in the skills/ directory. Each file contains comprehensive examples, use cases, and best practices for its topic.

Files

data-structures/streams.md

Streams

Overview

Streams are append-only logs of entries with unique IDs. They support consumer groups for distributed processing and delivery guarantees.

Good For

  • Event sourcing

  • Activity logs

  • Message queues with multiple consumers

  • Real-time data feeds

  • Chat systems

Limitations

  • Entries cannot be modified after insertion

  • Memory grows unbounded unless trimmed

  • Maximum stream length: practical limits based on memory

Examples

import { Redis } from "@upstash/redis";

const redis = Redis.fromEnv();

// Add entry to stream (auto-generated ID)
const id1 = await redis.xadd("events", "*", {
  type: "user.login",
  userId: "123",
  timestamp: Date.now(),
});
// Returns ID like "1642424242424-0"

// Add with specific ID (timestamp-sequence format)
const id2 = await redis.xadd("events", "1642424242424-1", {
  type: "user.logout",
  userId: "123",
});

// Add with trim (limit stream size)
await redis.xadd(
  "events",
  "*",
  { event: "test" },
  {
    trim: {
      type: "MAXLEN",
      comparison: "=",
      threshold: 1000,
    },
  }
);

// Add with approximate trim (more efficient)
await redis.xadd(
  "events",
  "*",
  { event: "test" },
  {
    trim: {
      type: "MAXLEN",
      comparison: "~",
      threshold: 1000,
    },
  }
);

// Get stream length
const length = await redis.xlen("events");

// Read entries from stream
const entries = await redis.xread("events", "0", { count: 10 });
// Returns: [{ name: "events", messages: [{ id: "...", message: {...} }] }]

// Read latest entries
const latest = await redis.xread("events", "$"); // $ means new entries only

// Read from multiple streams
const multi = await redis.xread(["stream1", "stream2"], ["0", "0"]);

// Note: Blocking (BLOCK option) is not yet supported in Upstash Redis

// Get range of entries by ID
const range = await redis.xrange("events", "-", "+"); // All entries
const specific = await redis.xrange("events", "1642424242424-0", "1642424242424-1");
const last10 = await redis.xrevrange("events", "+", "-", 10); // Last 10 in reverse

// Create consumer group
await redis.xgroup("events", {
  type: "CREATE",
  group: "processors",
  id: "0",
  options: { MKSTREAM: true },
});
// Creates group "processors" starting from beginning

// Read as consumer group member
const groupEntries = await redis.xreadgroup(
  "processors", // group name
  "consumer1", // consumer name
  "events", // stream key
  ">", // > means undelivered messages
  { count: 5 }
);

// Acknowledge processed messages
if (groupEntries && groupEntries[0]) {
  const messages = (groupEntries[0] as any)[1] as Array<{ 0: string; 1: any }>;
  if (messages && messages.length > 0) {
    const messageIds = messages.map((m) => m[0]);
    await redis.xack("events", "processors", messageIds);
  }
}

// Get pending messages (delivered but not acknowledged)
const pending = await redis.xpending("events", "processors", "-", "+", 10);
// Returns pending entry details

// Get detailed pending info for specific consumer
const pendingDetails = await redis.xpending(
  "events", // stream key
  "processors", // group
  "-", // start
  "_+", // end
  10, // count
  { consumer: "consumer1" } // optional: specific consumer
);

// Claim pending messages (take over from another consumer)
const claimed = await redis.xclaim(
  "events", // stream key
  "processors", // group
  "consumer2", // new owner (consumer)
  3600000, // min idle time (ms)
  "1642424242424-0" // message ID(s) to claim
);

// Delete messages
await redis.xdel("events", [id1, id2]);

// Trim stream to maximum length
await redis.xtrim("events", { strategy: "MAXLEN", threshold: 1000, exactness: "=" });
await redis.xtrim("events", { strategy: "MAXLEN", threshold: 1000, exactness: "~" }); // Approximate (more efficient)

// Get consumer group info
const groups = await redis.xinfo("events", { type: "GROUPS" });
// Returns list of consumer groups

// Get consumers in group
const consumers = await redis.xinfo("events", { type: "CONSUMERS", group: "processors" });
// Returns list of consumers and their stats

// Delete consumer from group
await redis.xgroup("events", {
  type: "DELCONSUMER",
  group: "processors",
  consumer: "consumer1",
});

// Delete consumer group
await redis.xgroup("events", { type: "DESTROY", group: "processors" });

// Practical example: Event log with processing
await redis.xadd("orders", "*", {
  orderId: "order-123",
  status: "pending",
  amount: 99.99,
});

// Create processor group
await redis.xgroup("orders", {
  type: "CREATE",
  group: "order-processors",
  id: "0",
  options: { MKSTREAM: true },
});

// Worker reads and processes
const orders = await redis.xreadgroup("order-processors", "worker-1", "orders", ">", {
  count: 1,
});

if (orders && orders[0]) {
  const messages = (orders[0] as any)[1] as Array<{ 0: string; 1: any }>;
  if (messages && messages.length > 0) {
    const order = messages[0];
    // Process order...
    console.log("Processing:", order[1]);

    // Acknowledge when done
    await redis.xack("orders", "order-processors", order[0]);
  }
}

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Needs Node.js

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Created by
Upstash
Publisher
Upstash (Official)
Source
upstash/skills · skills/upstash-redis-js · commit 9f9e3e5
Licence
MIT License (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by Upstash or Upstash.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download upstash-redis-js.zip