
Redis Patterns
- 1 installs
- 404 repo stars
- Updated August 5, 2026
- aiskillstore/marketplace
redis-patterns is a skill that provides Upstash Redis patterns for caching, rate limiting, sessions, and pub/sub in TypeScript.
About
This skill provides Upstash Redis patterns for caching and rate limiting in TypeScript. It covers basic caching with TTL, cache invalidation, sliding-window rate limiting, session storage, pub/sub, leaderboards, and the cache-aside pattern. A developer uses it when adding Redis-backed caching or rate limits to a Node or Next.js backend.
- Upstash Redis caching and rate-limiting patterns
- Session storage, pub/sub, and leaderboard recipes
- Cache-aside and TTL invalidation examples in TypeScript
Redis Patterns by the numbers
- 1 all-time installs (skills.sh)
- Ranked #765 of 911 Databases skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
redis-patterns capabilities & compatibility
Requires Upstash Redis REST URL and token (UPSTASH_REDIS_REST_URL, UPSTASH_REDIS_REST_TOKEN).
- Capabilities
- database · api development
- Works with
- redis
- Use cases
- database · api development
- Pricing
- Bring your own API key
What redis-patterns says it does
Upstash Redis patterns for caching and rate limiting.
limiter: Ratelimit.slidingWindow(10, '10 s'), // 10 requests per 10 seconds
npx skills add https://github.com/aiskillstore/marketplace --skill redis-patternsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1 |
|---|---|
| repo stars | ★ 404 |
| Last updated | August 5, 2026 |
| Repository | aiskillstore/marketplace ↗ |
What it does
Add Upstash Redis caching, rate limiting, sessions, or pub/sub to a Node or Next.js backend.
Who is it for?
Developers adding Redis-backed caching or rate limiting with Upstash in TypeScript.
Skip if: Self-hosted Redis clients other than Upstash, or non-JavaScript stacks.
When should I use this skill?
Adding Redis caching, rate limiting, session storage, or pub/sub to a backend.
What you get
Produces Upstash Redis code for caching, rate limiting, sessions, pub/sub, and leaderboards.
- Redis cache helpers
- rate limiter
- session store
By the numbers
- 8 Redis pattern sections (caching, invalidation, rate limiting, sessions, pub/sub, leaderboard, cache-aside)
- sliding-window limit of 10 requests per 10 seconds
Files
Upstash Redis Patterns
Setup
// lib/redis.ts
import { Redis } from '@upstash/redis';
export const redis = new Redis({
url: process.env.UPSTASH_REDIS_REST_URL!,
token: process.env.UPSTASH_REDIS_REST_TOKEN!,
});Basic Caching
// Cache with TTL
async function getCachedUser(id: string): Promise<User | null> {
const cacheKey = `user:${id}`;
// Try cache first
const cached = await redis.get<User>(cacheKey);
if (cached) return cached;
// Fetch from DB
const user = await db.query.users.findFirst({
where: eq(users.id, id),
});
if (user) {
// Cache for 5 minutes
await redis.setex(cacheKey, 300, user);
}
return user;
}Cache Invalidation
// Invalidate on update
async function updateUser(id: string, data: UpdateUserInput): Promise<User> {
const user = await db.update(users)
.set(data)
.where(eq(users.id, id))
.returning();
// Invalidate cache
await redis.del(`user:${id}`);
// Also invalidate list caches
await redis.del('users:list');
return user[0];
}Rate Limiting
import { Ratelimit } from '@upstash/ratelimit';
const ratelimit = new Ratelimit({
redis,
limiter: Ratelimit.slidingWindow(10, '10 s'), // 10 requests per 10 seconds
analytics: true,
});
// In API route or middleware
export async function POST(request: Request) {
const ip = request.headers.get('x-forwarded-for') ?? 'anonymous';
const { success, limit, reset, remaining } = await ratelimit.limit(ip);
if (!success) {
return new Response('Too Many Requests', {
status: 429,
headers: {
'X-RateLimit-Limit': limit.toString(),
'X-RateLimit-Remaining': remaining.toString(),
'X-RateLimit-Reset': reset.toString(),
},
});
}
// Process request...
}Session Storage
interface Session {
userId: string;
expiresAt: number;
}
async function createSession(userId: string): Promise<string> {
const sessionId = crypto.randomUUID();
const session: Session = {
userId,
expiresAt: Date.now() + 7 * 24 * 60 * 60 * 1000, // 7 days
};
await redis.setex(`session:${sessionId}`, 7 * 24 * 60 * 60, session);
return sessionId;
}
async function getSession(sessionId: string): Promise<Session | null> {
return await redis.get<Session>(`session:${sessionId}`);
}
async function deleteSession(sessionId: string): Promise<void> {
await redis.del(`session:${sessionId}`);
}Pub/Sub for Real-time
// Publisher
async function publishEvent(channel: string, data: unknown): Promise<void> {
await redis.publish(channel, JSON.stringify(data));
}
// Usage
await publishEvent('user:updates', { userId: '123', action: 'updated' });Leaderboard
// Add score
await redis.zadd('leaderboard', { score: 100, member: 'user:123' });
// Get top 10
const topUsers = await redis.zrevrange('leaderboard', 0, 9, { withScores: true });
// Get user rank
const rank = await redis.zrevrank('leaderboard', 'user:123');Cache Patterns
// Cache-aside pattern
async function getData<T>(
key: string,
fetcher: () => Promise<T>,
ttl: number = 300
): Promise<T> {
const cached = await redis.get<T>(key);
if (cached) return cached;
const data = await fetcher();
await redis.setex(key, ttl, data);
return data;
}
// Usage
const user = await getData(
`user:${id}`,
() => db.query.users.findFirst({ where: eq(users.id, id) }),
300
);{
"schema_version": "2.0",
"meta": {
"generated_at": "2026-01-16T19:10:55.655Z",
"slug": "barnhardt-enterprises-inc-redis-patterns",
"source_url": "https://github.com/Barnhardt-Enterprises-Inc/quetrex-claude/tree/main/skills/redis-patterns",
"source_ref": "main",
"model": "claude",
"analysis_version": "3.0.0",
"source_type": "community",
"content_hash": "8c598488fd745ccb59cc84abe35ac95dd8e0254345a7303a1986e8c4a7176239",
"tree_hash": "e68c24ba26d7d243514af346cd06c89c3292eab5dcc1985ca9adaec271467d79"
},
"skill": {
"name": "redis-patterns",
"description": "Upstash Redis patterns for caching and rate limiting.",
"summary": "Upstash Redis patterns for caching and rate limiting.",
"icon": "⚡",
"version": "1.0.0",
"author": "Barnhardt-Enterprises-Inc",
"license": "MIT",
"category": "coding",
"tags": [
"redis",
"caching",
"rate-limiting",
"upstash",
"performance"
],
"supported_tools": [
"claude",
"codex",
"claude-code"
],
"risk_factors": [
"network",
"external_commands",
"env_access"
]
},
"security_audit": {
"risk_level": "safe",
"is_blocked": false,
"safe_to_publish": true,
"summary": "This skill contains only markdown documentation with code examples. No executable code, no file system access, no network calls, and no external command execution. The static scanner flagged standard patterns as threats: JavaScript template literals (misidentified as shell backticks), process.env configuration (misidentified as credential access), and crypto.randomUUID (misidentified as weak crypto). All findings are false positives. This is purely instructional material for Redis patterns.",
"risk_factor_evidence": [
{
"factor": "network",
"evidence": [
{
"file": "skill-report.json",
"line_start": 6,
"line_end": 6
}
]
},
{
"factor": "external_commands",
"evidence": [
{
"file": "SKILL.md",
"line_start": 10,
"line_end": 18
},
{
"file": "SKILL.md",
"line_start": 18,
"line_end": 22
},
{
"file": "SKILL.md",
"line_start": 22,
"line_end": 25
},
{
"file": "SKILL.md",
"line_start": 25,
"line_end": 43
},
{
"file": "SKILL.md",
"line_start": 43,
"line_end": 47
},
{
"file": "SKILL.md",
"line_start": 47,
"line_end": 56
},
{
"file": "SKILL.md",
"line_start": 56,
"line_end": 63
},
{
"file": "SKILL.md",
"line_start": 63,
"line_end": 67
},
{
"file": "SKILL.md",
"line_start": 67,
"line_end": 94
},
{
"file": "SKILL.md",
"line_start": 94,
"line_end": 98
},
{
"file": "SKILL.md",
"line_start": 98,
"line_end": 111
},
{
"file": "SKILL.md",
"line_start": 111,
"line_end": 116
},
{
"file": "SKILL.md",
"line_start": 116,
"line_end": 120
},
{
"file": "SKILL.md",
"line_start": 120,
"line_end": 122
},
{
"file": "SKILL.md",
"line_start": 122,
"line_end": 126
},
{
"file": "SKILL.md",
"line_start": 126,
"line_end": 134
},
{
"file": "SKILL.md",
"line_start": 134,
"line_end": 138
},
{
"file": "SKILL.md",
"line_start": 138,
"line_end": 147
},
{
"file": "SKILL.md",
"line_start": 147,
"line_end": 151
},
{
"file": "SKILL.md",
"line_start": 151,
"line_end": 168
},
{
"file": "SKILL.md",
"line_start": 168,
"line_end": 172
}
]
},
{
"factor": "env_access",
"evidence": [
{
"file": "SKILL.md",
"line_start": 15,
"line_end": 15
},
{
"file": "SKILL.md",
"line_start": 16,
"line_end": 16
},
{
"file": "SKILL.md",
"line_start": 15,
"line_end": 15
},
{
"file": "SKILL.md",
"line_start": 16,
"line_end": 16
}
]
}
],
"critical_findings": [],
"high_findings": [],
"medium_findings": [],
"low_findings": [],
"dangerous_patterns": [],
"files_scanned": 2,
"total_lines": 354,
"audit_model": "claude",
"audited_at": "2026-01-16T19:10:55.655Z"
},
"content": {
"user_title": "Implement Redis caching and rate limiting",
"value_statement": "Applications need efficient caching and abuse prevention but lack clear patterns for implementation. This skill provides production-ready Upstash Redis patterns for caching, rate limiting, session storage, and pub/sub messaging.",
"seo_keywords": [
"redis patterns",
"upstash redis",
"caching patterns",
"rate limiting",
"claude code",
"claude ai",
"claude codex",
"session storage",
"cache invalidation",
"redis pub/sub"
],
"actual_capabilities": [
"Cache data with TTL expiration",
"Implement sliding window rate limiting",
"Store and manage user sessions",
"Publish and subscribe to real-time events",
"Build ranked leaderboards with sorted sets",
"Apply cache-aside pattern for data fetching"
],
"limitations": [
"Requires Upstash Redis account and credentials",
"No built-in connection pooling patterns",
"Does not cover Redis clustering or sharding",
"Rate limiting uses IP address only (no user authentication)"
],
"use_cases": [
{
"target_user": "Backend Developers",
"title": "Cache Database Queries",
"description": "Reduce database load by caching frequent queries with automatic expiration and invalidation."
},
{
"target_user": "API Developers",
"title": "Prevent API Abuse",
"description": "Implement rate limiting to protect endpoints from excessive requests and DDoS attacks."
},
{
"target_user": "Full-Stack Developers",
"title": "Manage User Sessions",
"description": "Store session data securely with automatic expiration for user authentication systems."
}
],
"prompt_templates": [
{
"title": "Basic Caching",
"scenario": "Cache database results",
"prompt": "Show me how to cache a database query result in Upstash Redis with a 5-minute TTL. Include cache-aside pattern."
},
{
"title": "Rate Limiting",
"scenario": "Protect API endpoints",
"prompt": "Implement rate limiting for an API route using @upstash/ratelimit. Allow 10 requests per 10 seconds per IP."
},
{
"title": "Session Storage",
"scenario": "User authentication",
"prompt": "Create session storage functions using Upstash Redis. Include create, get, and delete operations with 7-day expiration."
},
{
"title": "Real-time Events",
"scenario": "Live updates",
"prompt": "Show how to use Redis pub/sub for real-time event publishing. Include publisher and subscriber examples."
}
],
"output_examples": [
{
"input": "How do I cache user data with Redis?",
"output": [
"Check cache first using redis.get(key)",
"If cached, return cached data",
"If not cached, fetch from database",
"Store result in Redis with setex(key, ttl, value)",
"Return the data",
"Key pattern: user:{id} for easy invalidation"
]
},
{
"input": "I need to limit API requests per user",
"output": [
"Create a Ratelimit instance with sliding window",
"Pass unique identifier (IP or userId) to limit function",
"Check success boolean in response",
"Return 429 status with headers when limit exceeded",
"Include X-RateLimit headers for client awareness"
]
},
{
"input": "How do I invalidate cached data?",
"output": [
"Use redis.del(key) for single key removal",
"Delete all related cache keys when data updates",
"Consider cache versioning for complex invalidation",
"Use TTL as fallback for automatic expiration"
]
}
],
"best_practices": [
"Use descriptive key prefixes (user:, session:, cache:) to organize data",
"Always invalidate related caches when underlying data changes",
"Set appropriate TTL values based on data freshness requirements",
"Use redis.del() for cache invalidation rather than waiting for TTL"
],
"anti_patterns": [
"Storing sensitive data without encryption in Redis",
"Using extremely long TTLs that prevent data updates from propagating",
"Not handling cache misses gracefully with fallback to database",
"Storing entire large objects instead of referencing them"
],
"faq": [
{
"question": "Is Upstash Redis compatible with standard Redis clients?",
"answer": "Upstash provides REST API and works with @upstash/redis SDK. Some standard Redis clients may not be fully compatible."
},
{
"question": "What is the maximum TTL for Upstash Redis?",
"answer": "Upstash Redis supports TTL up to 30 days for most operations. For longer durations, implement periodic refresh logic."
},
{
"question": "Can this skill integrate with existing Redis installations?",
"answer": "These patterns use @upstash/redis which is designed for Upstash serverless Redis. Standard Redis requires different configuration."
},
{
"question": "Is my data secure in Upstash Redis?",
"answer": "Upstash provides encryption at rest and in transit. Use environment variables for credentials and avoid hardcoding secrets."
},
{
"question": "Why is my rate limit not working correctly?",
"answer": "Ensure you pass a unique identifier (IP or user ID) to the limit function. Check that the rate limiter is instantiated once globally."
},
{
"question": "How does this compare to using Redis directly?",
"answer": "Upstash offers serverless pricing and easier setup but has rate limits on API calls. Standard Redis gives more control but requires server management."
}
]
},
"file_structure": [
{
"name": "SKILL.md",
"type": "file",
"path": "SKILL.md",
"lines": 173
}
]
}
Related skills
FAQ
Which Redis does this use?
Upstash Redis via the @upstash/redis REST client.
How is rate limiting done?
With @upstash/ratelimit using a sliding-window limiter, for example 10 requests per 10 seconds.