Claude Skills Guide

Claude Code Upstash Redis Rate Limiting Workflow

Building robust rate limiting into your applications is essential for API protection, cost control, and abuse prevention. When combined with Claude Code’s automation capabilities, Upstash Redis provides a powerful foundation for implementing sophisticated rate limiting workflows. This guide walks you through creating an integrated system that uses Claude Code skills with Upstash’s edge-friendly Redis solution.

Why Upstash for Rate Limiting

Upstash offers several advantages that make it ideal for rate limiting implementations. Its global edge network ensures low latency regardless of where your users are located. The pay-per-request pricing model means you only pay for what you use, perfect for variable workloads. Redis compatibility means you can use familiar commands and patterns while benefiting from Upstash’s managed infrastructure.

Unlike traditional Redis deployments, Upstash provides built-in rate limiting primitives through its QStash message queue and specialized rate limiting commands. This eliminates the need to implement complex sliding window algorithms from scratch.

Setting Up Your Claude Code Environment

Before implementing the rate limiting workflow, ensure Claude Code is installed and configured. You’ll need Node.js 18 or later, and an Upstash account with a created database.

# Install Claude Code if you haven't already
npm install -g @anthropic-ai/claude-code

# Verify installation
claude --version

Create a new skill for managing rate limiting operations:

mkdir -p ~/.claude/skills/rate-limiter

Building the Upstash Integration Skill

Create a comprehensive skill file that handles all rate limiting operations:

# Rate Limiter Skill

You are an expert in implementing rate limiting using Upstash Redis. You help design, build, and optimize rate limiting systems.

## Available Tools

When working with Upstash Redis rate limiting, use these approaches:

### 1. Fixed Window Rate Limiting

The simplest approach limits requests within fixed time windows:


```typescript
import { Redis } from '@upstash/redis';

const redis = new Redis({
  url: process.env.UPSTASH_REDIS_REST_URL,
  token: process.env.UPSTASH_REDIS_REST_TOKEN,
});

async function fixedWindowLimit(key: string, limit: number, windowSeconds: number) {
  const current = await redis.incr(key);
  
  if (current === 1) {
    await redis.expire(key, windowSeconds);
  }
  
  return {
    allowed: current <= limit,
    remaining: Math.max(0, limit - current),
    reset: Math.floor(Date.now() / 1000) + windowSeconds
  };
}

2. Sliding Window Rate Limiting

More accurate rate limiting using sorted sets:

async function slidingWindowLimit(
  key: string, 
  limit: number, 
  windowMs: number
) {
  const now = Date.now();
  const windowStart = now - windowMs;
  
  // Remove expired entries
  await redis.zremrangebyscore(key, 0, windowStart);
  
  // Count current requests
  const count = await redis.zcard(key);
  
  if (count >= limit) {
    return { allowed: false, remaining: 0, retryAfter: windowMs };
  }
  
  // Add new request
  await redis.zadd(key, { score: now, member: `${now}-${Math.random()}` });
  await redis.expire(key, Math.ceil(windowMs / 1000));
  
  return { 
    allowed: true, 
    remaining: limit - count - 1,
    reset: Math.floor((now + windowMs) / 1000)
  };
}

3. Token Bucket Algorithm

Flexible rate limiting supporting burst traffic:

interface TokenBucket {
  tokens: number;
  lastRefill: number;
}

async function tokenBucketCheck(
  key: string,
  capacity: number,
  refillRate: number // tokens per second
) {
  const bucketKey = `bucket:${key}`;
  const data = await redis.hmget(bucketKey, 'tokens', 'lastRefill');
  
  const now = Date.now();
  let tokens = parseFloat(data[0] || capacity.toString());
  let lastRefill = parseInt(data[1] || now.toString());
  
  // Refill tokens based on elapsed time
  const elapsed = (now - lastRefill) / 1000;
  tokens = Math.min(capacity, tokens + (elapsed * refillRate));
  
  if (tokens >= 1) {
    tokens -= 1;
    await redis.hmset(bucketKey, { 
      tokens: tokens.toFixed(2), 
      lastRefill: now 
    });
    await redis.expire(bucketKey, Math.ceil(capacity / refillRate) * 2);
    
    return { allowed: true, remaining: Math.floor(tokens) };
  }
  
  return { 
    allowed: false, 
    remaining: 0,
    retryAfter: Math.ceil((1 - tokens) / refillRate * 1000)
  };
}

Claude Code Workflow Integration

Now integrate the rate limiter into Claude Code workflows for automated API protection:

# claude.settings.yml - Global rate limiting configuration
rate_limits:
  api:
    endpoint: "/api/v1"
    limit: 100
    window: "1m"
    redis_key_prefix: "rl:api"
    
  auth:
    endpoint: "/api/auth/*"
    limit: 5
    window: "1m"
    redis_key_prefix: "rl:auth"
    
  expensive:
    endpoint: "/api/reports/*"
    limit: 10
    window: "1h"
    redis_key_prefix: "rl:expensive"

Automated Rate Limit Management

Create a skill that helps manage rate limits across your infrastructure:

// Rate limit management skill
class RateLimitManager {
  private redis: Redis;
  
  async analyzeRateLimits(clientId: string) {
    const keys = await this.redis.keys(`rl:${clientId}:*`);
    const analysis = await Promise.all(
      keys.map(async (key) => {
        const data = await this.redis.hgetall(key);
        return { key, ...data };
      })
    );
    
    return {
      totalRequests: analysis.reduce((sum, a) => sum + (parseInt(a.count) || 0), 0),
      endpoints: analysis.map(a => a.endpoint),
      oldestRequest: Math.min(...analysis.map(a => parseInt(a.firstRequest) || Date.now()))
    };
  }
  
  async detectAbuse(clientId: string, threshold: number) {
    const analysis = await this.analyzeRateLimits(clientId);
    const abuseScore = this.calculateAbuseScore(analysis);
    
    if (abuseScore > threshold) {
      await this.redis.set(`abuse:flag:${clientId}`, Date.now(), { ex: 86400 });
      return { flagged: true, score: abuseScore };
    }
    
    return { flagged: false, score: abuseScore };
  }
}

Testing Your Rate Limiter

Verify the implementation works correctly with comprehensive tests:

describe('Rate Limiter', () => {
  it('allows requests within limit', async () => {
    const result = await fixedWindowLimit('test-key', 5, 60);
    expect(result.allowed).toBe(true);
    expect(result.remaining).toBe(4);
  });
  
  it('blocks requests exceeding limit', async () => {
    // Fill up the bucket
    for (let i = 0; i < 5; i++) {
      await fixedWindowLimit('test-key', 5, 60);
    }
    
    const result = await fixedWindowLimit('test-key', 5, 60);
    expect(result.allowed).toBe(false);
  });
  
  it('resets after window expires', async () => {
    jest.useFakeTimers();
    jest.setSystemTime(Date.now() + 61000);
    
    const result = await fixedWindowLimit('test-key', 5, 60);
    expect(result.allowed).toBe(true);
    
    jest.useRealTimers();
  });
});

Monitoring and Alerts

Set up monitoring to track rate limiting effectiveness:

// Prometheus metrics for rate limiting
const rateLimitMetrics = {
  requestsTotal: new Counter({
    name: 'rate_limit_requests_total',
    help: 'Total requests by endpoint and status',
    labelNames: ['endpoint', 'allowed']
  }),
  
  requestsInProgress: new Gauge({
    name: 'rate_limit_requests_in_progress',
    help: 'Current requests being processed'
  }),
  
  rateLimitHits: new Counter({
    name: 'rate_limit_hits_total',
    help: 'Number of times rate limit was exceeded'
  })
};

Best Practices

When implementing rate limiting with Claude Code and Upstash, consider these recommendations:

Start with conservative limits and adjust based on actual usage patterns. Different endpoints typically require different limits—authentication endpoints should be more restrictive than read operations.

Always include proper headers in API responses so clients know their rate limit status. The standard headers are X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset.

Implement graduated responses rather than hard blocks when possible. Return 429 (Too Many Requests) with a Retry-After header instead of immediately blocking.

Use separate rate limits for different client tiers. Free tier users might get 100 requests per minute while paid users get 1000.

Monitor for rate limit evasion attempts and implement IP-based fallback limits if abuse is detected.

Conclusion

Combining Claude Code’s automation capabilities with Upstash Redis creates a powerful rate limiting system. The examples in this guide provide starting points for fixed window, sliding window, and token bucket implementations. Adapt these patterns to your specific requirements, and use Claude Code to automate the ongoing management and monitoring of your rate limiting infrastructure.

Built by theluckystrike — More at zovo.one