upstash-ratelimit
Adds request limits to APIs and functions. It uses Redis to control access and prevent overload, ensuring stability.
What it does
This tool helps control how many times a user or system can access a specific part of a website or app within a certain time. This prevents abuse by stopping someone from making too many requests too quickly.
When to use it
- ✓Protecting contact forms from spam.
- ✓Limiting login attempts to prevent attacks.
- ✓Controlling API usage to avoid overload.
Example of what to ask your AI
“I want to limit access to my login page to a maximum of 5 attempts per minute per user.”
Want more? Open the sections below.
How to use
The easiest way: copy the message below and paste it into Claude, ChatGPT, Cursor or any AI. It reads the skill and follows the instructions.
Skill link
Ready-to-paste message
How it works
The tool uses a database called Redis to count requests. Each time someone accesses something protected, a counter is updated in Redis. If the counter reaches the limit, access is temporarily blocked.
Installation
Easiest way: copy the skill link and paste it into Claude, ChatGPT or Cursor asking it to follow the instructions.
In the terminal (Claude Code, Codex, Cursor), in your project folder:
npx skills add sickn33/agentic-awesome-skills --skill upstash-ratelimitOr download just the file:
curl -L https://raw.githubusercontent.com/sickn33/agentic-awesome-skills/main/plugins/agentic-awesome-skills-claude/skills/upstash-ratelimit/SKILL.md -o SKILL.mdTechnical content (original SKILL.md)
Original text by the author, straight from GitHub.
Upstash Ratelimit
Overview
@upstash/ratelimit implements distributed rate limiting on top of Upstash
Redis. Because state lives in Redis, every instance of a serverless function
or edge worker shares the same counters, which an in-memory limiter cannot
do. It ships three algorithms (fixed window, sliding window, token bucket),
per-identifier keys, optional in-memory blocking of already-limited
identifiers, and optional analytics.
When to Use This Skill
- Use when the user needs to limit requests per IP, user, API key, or tenant across multiple serverless instances or regions.
- Use when protecting login, signup, form, webhook, or LLM endpoints from
abuse and returning
429 Too Many Requests. - Use when choosing between fixed window, sliding window, and token bucket.
- Do not use for client-side retry/backoff against a third-party API's limits;
see
api-rate-limit-handler. - Do not use for a single long-running process with no shared state; an in-memory limiter is simpler there.
How It Works
Step 1: Install and configure
npm install @upstash/ratelimit @upstash/redis
Set UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN in the environment.
Step 2: Create the limiter once, outside the handler
import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";
export const ratelimit = new Ratelimit({
redis: Redis.fromEnv(),
limiter: Ratelimit.slidingWindow(10, "10 s"), // 10 requests per 10 seconds
prefix: "rl:api",
analytics: true,
});
Constructing the limiter at module scope lets the built-in ephemeral cache short-circuit blocked identifiers without a Redis call.
Step 3: Call limit() with a stable identifier
const { success, limit, remaining, reset, pending } = await ratelimit.limit(userId);
success is false when the identifier is over its limit. reset is a Unix
timestamp in milliseconds. pending is a promise for background work
(analytics, multi-region sync); await it or pass it to waitUntil on edge
runtimes so the function is not frozen before it completes.
Examples
Example 1: Next.js middleware returning 429
import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";
import { NextResponse, type NextRequest } from "next/server";
const ratelimit = new Ratelimit({
redis: Redis.fromEnv(),
limiter: Ratelimit.slidingWindow(20, "1 m"),
});
export async function middleware(request: NextRequest) {
const ip = request.headers.get("x-forwarded-for") ?? "anonymous";
const { success, limit, remaining, reset } = await ratelimit.limit(ip);
if (!success) {
return new NextResponse("Too Many Requests", {
status: 429,
headers: {
"X-RateLimit-Limit": String(limit),
"X-RateLimit-Remaining": String(remaining),
"X-RateLimit-Reset": String(reset),
"Retry-After": String(Math.ceil((reset - Date.now()) / 1000)),
},
});
}
return NextResponse.next();
}
export const config = { matcher: "/api/:path*" };
Example 2: Token bucket with per-plan limits
const limiters = {
free: new Ratelimit({
redis: Redis.fromEnv(),
prefix: "rl:free",
limiter: Ratelimit.tokenBucket(5, "10 s", 10), // refill 5 per 10 s, burst 10
}),
pro: new Ratelimit({
redis: Redis.fromEnv(),
prefix: "rl:pro",
limiter: Ratelimit.tokenBucket(50, "10 s", 100),
}),
};
const { success } = await limiters[plan].limit(apiKey);
Best Practices
- ✅ Use a stable, low-cardinality identifier (user id, API key, tenant) where possible; fall back to IP only for anonymous traffic.
- ✅ Set a distinct
prefixper endpoint or plan so limits do not collide. - ✅ Return
Retry-AfterandX-RateLimit-*headers with 429 responses. - ✅ Prefer
slidingWindowfor most APIs; usetokenBucketwhen short bursts are acceptable; usefixedWindowwhen the lowest Redis cost matters. - ❌ Don't construct a new
Ratelimitinside the request handler. - ❌ Don't rely on
pendingcompleting on its own in edge runtimes. - ❌ Don't rate limit by
x-forwarded-forwithout validating it is set by your proxy; clients can spoof it otherwise.
Limitations
- Requires an Upstash Redis database; it does not work with other Redis servers or without network access.
- Each
limit()call is at least one HTTP round trip to Redis, so it adds latency to every request it guards.
…
FAQ
What happens if the limit is reached?
The person who exceeded the limit will receive an error message (429 code) and won't be able to access the resource for a while.
Can I set different limits for different users?
Yes, you can set limits based on unique identifiers like user ID, API key, or even IP address.
Do I need a special server to use this?
Yes, this tool requires an Upstash Redis database, which is a separate service.
Details
Original description by the author
Add rate limiting to API routes, middleware, and edge functions with @upstash/ratelimit: sliding window, fixed window, and token bucket backed by Upstash Redis.
Popularity
- GitHub stars
- 48k
- Ranking position
- #4457
- License
- MIT
- Updated
- 10/15/2026
Comments
- …
More skills from this repository
00-andruia-consultant
Helps your agent start or improve AI projects. It analyzes code, suggests tools, and creates action plans in Spanish.
sickn33/agentic-awesome-skills
007
Lets your agent perform security audits and threat modeling. It's useful for protecting projects against attacks and vulnerabilities.
sickn33/agentic-awesome-skills
10-andruia-skill-smith
Helps your agent create or improve AI tools. It defines how tools work, writes documentation, and validates the structure.
sickn33/agentic-awesome-skills
20-andruia-niche-intelligence
Lets your agent create a summary about a specific industry. It's useful for understanding the context, rules, usage patterns, and risks of a project, using reliable sources.
sickn33/agentic-awesome-skills
Similar skills
benchmark
Helps your agent measure code speed and performance. It's useful for ensuring things are fast and finding slowness issues.
affaan-m/ECC
content-hash-cache-pattern
Lets your agent use content hashes to cache file processing results. This avoids repeated processing and auto-invalidates the cache when content changes. Useful for speeding up slow tasks.
affaan-m/ECC
parallel-execution-optimizer
Makes your agent speed up complex tasks by breaking them into smaller parts and running them in parallel. It ensures everything is verified at the end.
affaan-m/ECC