All skills
upstash avatar

/upstash-redis-js

@35da719
by upstashupstash/skills27 stars
7

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 node-redis, when a Redis connection is needed from a serverless function without connection pooling, when integrating @upstash/ratelimit, or when the user says Redis cache, KV store, session store, serverless Redis, or Upstash Redis. Supports automatic serialization/deserialization of JavaScript types.

Use this Skill: https://skilld.dev/gh/upstash/skills/upstash-redis-js

This session only. Nothing lands on disk.

patternsdistributed-locks.md

≈919 tokens on demand. Your agent reads this file only when SKILL.md points to it.

Distributed Locks

Overview

Distributed locks prevent concurrent access to shared resources across multiple processes or servers. Use SET NX with expiration for simple locking.

Good For

  • Preventing overlapping (concurrent) job execution
  • Ensuring only one process modifies a resource
  • Rate limiting at system level
  • Coordinating distributed operations

Limitations

  • Lock holder must complete before TTL expires
  • No automatic lock release on crash (relies on TTL)
  • A lock is not deduplication: once released, a retry re-acquires it and runs the work again. For at-least-once delivery, pair it with a durable "processed" marker.
  • Use @upstash/lock for production (implements Redlock)

Examples

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

const redis = Redis.fromEnv();

// Simple lock with SET NX
async function acquireLock(lockKey: string, ttl: number = 10): Promise<boolean> {
  const acquired = await redis.set(lockKey, "locked", {
    nx: true, // Only set if not exists
    ex: ttl, // Expire after ttl seconds
  });

  return acquired === "OK";
}

async function releaseLock(lockKey: string) {
  await redis.del(lockKey);
}

// Use lock pattern
async function processJob(jobId: string) {
  const lockKey = `lock:job:${jobId}`;

  const acquired = await acquireLock(lockKey, 30);

  if (!acquired) {
    console.log("Job already being processed");
    return;
  }

  try {
    // Do work
    await performJobWork(jobId);
  } finally {
    await releaseLock(lockKey);
  }
}

// Lock with unique token (prevents accidental unlock by others)
async function acquireLockWithToken(lockKey: string, token: string, ttl: number = 10) {
  const acquired = await redis.set(lockKey, token, { nx: true, ex: ttl });
  return acquired === "OK";
}

async function releaseLockWithToken(lockKey: string, token: string) {
  // Only delete if token matches (using Lua script)
  const script = `
    if redis.call("GET", KEYS[1]) == ARGV[1] then
      return redis.call("DEL", KEYS[1])
    else
      return 0
    end
  `;

  return await redis.eval<number>(script, [lockKey], [token]);
}

// Usage with token
async function processWithTokenLock(jobId: string) {
  const lockKey = `lock:job:${jobId}`;
  const token = crypto.randomUUID();

  const acquired = await acquireLockWithToken(lockKey, token, 30);

  if (!acquired) return;

  try {
    await performJobWork(jobId);
  } finally {
    await releaseLockWithToken(lockKey, token);
  }
}

// Lock with retry
async function acquireLockWithRetry(
  lockKey: string,
  ttl: number = 10,
  retries: number = 3,
  delay: number = 100
): Promise<boolean> {
  for (let i = 0; i < retries; i++) {
    const acquired = await acquireLock(lockKey, ttl);
    if (acquired) return true;

    await new Promise((resolve) => setTimeout(resolve, delay));
  }

  return false;
}

// Webhooks: lock for concurrent deliveries, processed marker for retries
const RETRY_WINDOW = 60 * 60 * 24; // outlive the provider's retry window

async function processWebhook(webhookId: string, data: any) {
  const lockKey = `lock:webhook:${webhookId}`;
  const processedKey = `webhook:processed:${webhookId}`;

  if (await redis.exists(processedKey)) return { status: "duplicate" };

  const acquired = await acquireLock(lockKey, 60);
  if (!acquired) return { status: "in-progress" };

  try {
    // re-check: an earlier delivery may have finished while we waited
    if (await redis.exists(processedKey)) return { status: "duplicate" };

    await handleWebhook(data);
    await redis.set(processedKey, Date.now(), { ex: RETRY_WINDOW });
    return { status: "processed" };
  } finally {
    await releaseLock(lockKey);
  }
}

Source: SKILL.md on GitHub

1 warning10d3 checks · Risk SAFE
  • Gen Agent Trust Hub10d

    The skill provides a comprehensive set of documentation and code examples for using the Upstash Redis SDK. It covers various data structures, performance optimizations, and search capabilities. No malicious code, obfuscation, or unauthorized data access patterns were detected. The skill uses standard environment variables for secret management and references official Upstash packages.

  • Socket10d

    1 alert: gptSecurity

  • Snyk10d

    Risk: LOW · No issues

Signed by skilld at 35da719. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 6 days ago.

Activeupdated 2 weeks ago
metadata
{
  "author": "Upstash",
  "homepage": "https://upstash.com"
}

README badge

README badge for upstash/skills/upstash-redis-js