Implement API rate limiting in Google Antigravity with Redis and sliding window algorithms.
# API Rate Limiting for Google Antigravity
Protect your APIs from abuse with effective rate limiting using Redis.
## Redis Rate Limiter
```typescript
// lib/rate-limiter.ts
import Redis from "ioredis";
const redis = new Redis(process.env.REDIS_URL!);
interface RateLimitResult {
success: boolean;
remaining: number;
reset: number;
}
export async function checkRateLimit(key: string, limit: number, windowSeconds: number): Promise<RateLimitResult> {
const now = Date.now();
const windowStart = now - windowSeconds * 1000;
const redisKey = `ratelimit:${key}`;
const pipeline = redis.pipeline();
pipeline.zremrangebyscore(redisKey, 0, windowStart);
pipeline.zadd(redisKey, now, `${now}-${Math.random()}`);
pipeline.zcard(redisKey);
pipeline.expire(redisKey, windowSeconds);
const results = await pipeline.exec();
const count = results?.[2]?.[1] as number;
return {
success: count <= limit,
remaining: Math.max(0, limit - count),
reset: Math.ceil((windowStart + windowSeconds * 1000) / 1000),
};
}
```
## Token Bucket
```typescript
// lib/token-bucket.ts
import Redis from "ioredis";
const redis = new Redis(process.env.REDIS_URL!);
export async function consumeToken(key: string, config: { maxTokens: number; refillRate: number; refillInterval: number }): Promise<{ allowed: boolean; tokens: number }> {
const script = `
local tokens = tonumber(redis.call("get", KEYS[1]) or ARGV[1])
local lastRefill = tonumber(redis.call("get", KEYS[2]) or ARGV[4])
local now = tonumber(ARGV[4])
local elapsed = now - lastRefill
local refills = math.floor(elapsed / tonumber(ARGV[3]))
tokens = math.min(tonumber(ARGV[1]), tokens + refills * tonumber(ARGV[2]))
if tokens >= 1 then
tokens = tokens - 1
redis.call("set", KEYS[1], tokens)
redis.call("set", KEYS[2], now)
return {1, tokens}
end
return {0, tokens}
`;
const result = await redis.eval(script, 2, `bucket:${key}:tokens`, `bucket:${key}:lastRefill`, config.maxTokens, config.refillRate, config.refillInterval, Date.now()) as [number, number];
return { allowed: result[0] === 1, tokens: result[1] };
}
```
## Middleware
```typescript
// middleware.ts
import { NextRequest, NextResponse } from "next/server";
import { checkRateLimit } from "@/lib/rate-limiter";
export async function middleware(request: NextRequest) {
if (request.nextUrl.pathname.startsWith("/api")) {
const ip = request.ip || "unknown";
const { success, remaining, reset } = await checkRateLimit(`${ip}:${request.nextUrl.pathname}`, 100, 60);
if (!success) {
return new NextResponse(JSON.stringify({ error: "Too many requests" }), {
status: 429,
headers: { "X-RateLimit-Remaining": "0", "Retry-After": "60" },
});
}
const response = NextResponse.next();
response.headers.set("X-RateLimit-Remaining", remaining.toString());
return response;
}
return NextResponse.next();
}
```
## In-Memory Limiter
```typescript
// lib/memory-rate-limiter.ts
const counts = new Map<string, { count: number; resetAt: number }>();
export function checkMemoryRateLimit(key: string, limit: number, windowMs: number): { allowed: boolean; remaining: number } {
const now = Date.now();
const record = counts.get(key);
if (!record || now > record.resetAt) {
counts.set(key, { count: 1, resetAt: now + windowMs });
return { allowed: true, remaining: limit - 1 };
}
if (record.count >= limit) return { allowed: false, remaining: 0 };
record.count++;
return { allowed: true, remaining: limit - record.count };
}
setInterval(() => {
const now = Date.now();
for (const [key, record] of counts) if (now > record.resetAt) counts.delete(key);
}, 60000);
```
## Best Practices
1. **Distributed Storage**: Use Redis for rate limiting across instances
2. **Headers**: Always return rate limit headers
3. **Tiered Limits**: Different limits for auth vs anonymous
4. **Burst Handling**: Allow bursts with token bucket
5. **Monitoring**: Log rate limit hitsThis rate-limiting prompt is ideal for developers working on:
By using this prompt, you can save hours of manual coding and ensure best practices are followed from the start. It's particularly valuable for teams looking to maintain consistency across their rate-limiting implementations.
Yes! All prompts on Antigravity AI Directory are free to use for both personal and commercial projects. No attribution required, though it's always appreciated.
This prompt works excellently with Claude, ChatGPT, Cursor, GitHub Copilot, and other modern AI coding assistants. For best results, use models with large context windows.
You can modify the prompt by adding specific requirements, constraints, or preferences. For rate-limiting projects, consider mentioning your framework version, coding style, and any specific libraries you're using.