Back to Skills

vercel-kv

verified

Integrate Redis-compatible Vercel KV for caching, session management, and rate limiting in Next.js. Powered by Upstash with strong consistency and TTL support. Use when implementing cache strategies, rate limiters, or troubleshooting environment variables, serialization errors, rate limit issues, scanIterator hangs, or Next.js cache stale reads.

View on GitHub

Marketplace

claude-skills

jezweb/claude-skills

Plugin

frontend

Repository

jezweb/claude-skills
211stars

skills/vercel-kv/SKILL.md

Last Verified

January 21, 2026

Install Skill

Select agents to install to:

Scope:
npx add-skill https://github.com/jezweb/claude-skills/blob/main/skills/vercel-kv/SKILL.md -a claude-code --skill vercel-kv

Installation paths:

Claude
.claude/skills/vercel-kv/
Powered by add-skill CLI

Instructions

# Vercel KV

**Last Updated**: 2026-01-21
**Version**: @vercel/kv@3.0.0 (Redis-compatible, powered by Upstash)

---

## Quick Start

```bash
# Create KV: Vercel Dashboard → Storage → KV
vercel env pull .env.local  # Creates KV_REST_API_URL and KV_REST_API_TOKEN
npm install @vercel/kv
```

**Basic Usage**:
```typescript
import { kv } from '@vercel/kv';

// Set with TTL (expires in 1 hour)
await kv.setex('session:abc', 3600, { userId: 123 });

// Get
const session = await kv.get('session:abc');

// Increment counter (atomic)
const views = await kv.incr('views:post:123');
```

**CRITICAL**: Always use namespaced keys (`user:123` not `123`) and set TTL for temporary data.

---

## Common Patterns

**Caching** (cache-aside):
```typescript
const cached = await kv.get(`post:${slug}`);
if (cached) return cached;

const post = await db.query.posts.findFirst({ where: eq(posts.slug, slug) });
await kv.setex(`post:${slug}`, 3600, post); // Cache 1 hour
return post;
```

**Rate Limiting**:
```typescript
async function checkRateLimit(ip: string): Promise<boolean> {
  const key = `ratelimit:${ip}`;
  const current = await kv.incr(key);
  if (current === 1) await kv.expire(key, 60); // 60s window
  return current <= 10; // 10 requests per window
}
```

**Session Management**:
```typescript
const sessionId = crypto.randomUUID();
await kv.setex(`session:${sessionId}`, 7 * 24 * 3600, { userId });
```

**Pipeline** (batch operations):
```typescript
const pipeline = kv.pipeline();
pipeline.set('user:1', data);
pipeline.incr('counter');
const results = await pipeline.exec(); // Single round-trip
```

**Key Naming**: Use namespaces like `user:123`, `post:abc:views`, `ratelimit:ip:endpoint`

---

## Critical Rules

**Always**:
- ✅ Set TTL for temporary data (`setex` not `set`)
- ✅ Use namespaced keys (`user:123` not `123`)
- ✅ Handle null returns (non-existent keys)
- ✅ Use pipeline for batch operations

**Never**:
- ❌ Forget to set TTL (memory leak)
- ❌ Store large values >1MB (use Vercel

Validation Details

Front Matter
Required Fields
Valid Name Format
Valid Description
Has Sections
Allowed Tools
Instruction Length:
15879 chars