This guide explains how to set up and configure rate limiting for the Skill Seekers website API endpoints.
Rate limiting protects the API endpoints from abuse and prevents exhausting GitHub API quota. The implementation uses Upstash Redis for distributed rate limiting that works with Vercel's serverless architecture.
- Prevents spam: Blocks automated bots from submitting hundreds of configs
- Protects GitHub API quota: Limits admin operations that call GitHub API
- Prevents DoS attacks: Stops malicious users from overwhelming the server
- Fair usage: Ensures all users get equal access to the API
| Endpoint | Limit | Window | Identifier |
|---|---|---|---|
POST /api/submit-config |
5 requests | 1 hour | IP Address |
POST /api/admin/approve |
20 requests | 1 hour | Username |
POST /api/admin/reject |
20 requests | 1 hour | Username |
GET /api/admin/submissions |
30 requests | 1 hour | Username |
GET /api/auth/github |
10 requests | 15 minutes | IP Address |
- Go to https://upstash.com/
- Sign up for a free account
- Free tier includes:
- 10,000 commands per day
- Up to 256MB storage
- No credit card required
- Click "Create Database" in Upstash dashboard
- Select region closest to your Vercel deployment
- Choose "Global" for multi-region replication (optional)
- Click "Create"
- Open your Redis database in Upstash
- Go to "REST API" tab
- Copy:
UPSTASH_REDIS_REST_URLUPSTASH_REDIS_REST_TOKEN
Add to .env:
UPSTASH_REDIS_REST_URL=https://your-redis-url.upstash.io
UPSTASH_REDIS_REST_TOKEN=your_upstash_token_here- Go to Vercel dashboard: https://vercel.com/yusufkaraaslan/skillseekersweb
- Navigate to Settings → Environment Variables
- Add:
UPSTASH_REDIS_REST_URL= (your URL)UPSTASH_REDIS_REST_TOKEN= (your token)
- Click "Save"
- Redeploy the site
1. Request arrives → Extract identifier (IP or username)
2. Check Upstash Redis for rate limit status
3. If under limit → Allow request, increment counter
4. If over limit → Return 429 Too Many Requests with Retry-After header
If Upstash is not configured:
⚠️ Warning logged to console- ✅ Request allowed to proceed
⚠️ No rate limiting applied
This prevents the site from breaking if Upstash credentials are missing.
When rate limited, the response includes:
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 3421
X-RateLimit-Limit: ...
X-RateLimit-Reset: 1737120000
{
"error": "Too many requests",
"message": "Rate limit exceeded. Please try again later.",
"retryAfter": 3421
}Located at src/utils/ratelimit.ts:
import { Ratelimit } from '@upstash/ratelimit';
import { Redis } from '@upstash/redis';
export const rateLimits = {
submitConfig: new Ratelimit({
redis,
limiter: Ratelimit.slidingWindow(5, '1h'),
prefix: 'ratelimit:submit',
analytics: true,
}),
// ... other limiters
};Example from src/pages/api/submit-config.ts:
import { rateLimits, applyRateLimit, getClientIP } from '../../utils/ratelimit';
export const POST: APIRoute = async ({ request }) => {
// Apply rate limiting
const clientIP = getClientIP(request);
const rateLimitResponse = await applyRateLimit(rateLimits.submitConfig, clientIP);
if (rateLimitResponse) {
return rateLimitResponse; // Returns 429 if rate limited
}
// ... rest of handler
};The getClientIP() function detects the client IP from various headers:
x-real-ip(Vercel)cf-connecting-ip(Cloudflare)x-forwarded-for(Standard)- Fallback to
'unknown'
View rate limiting analytics in Upstash:
- Go to your database dashboard
- Check "Analytics" tab
- See request counts, hit rates, and usage patterns
Check Vercel function logs for rate limiting warnings:
Warning: Rate limiting not configured - Upstash credentials missing
# Set up .env with Upstash credentials
# Start dev server
npm run dev
# Test rate limit (submit 6 configs within an hour)
for i in {1..6}; do
curl -X POST http://localhost:4321/api/submit-config \
-H "Content-Type: application/json" \
-d '{"config": {...}}'
done
# 6th request should return 429- Deploy to Vercel with Upstash configured
- Use browser DevTools or curl to make multiple requests
- Verify 429 response after exceeding limits
To change rate limits, edit src/utils/ratelimit.ts:
submitConfig: new Ratelimit({
redis,
limiter: Ratelimit.slidingWindow(10, '1h'), // Change from 5 to 10
// ...
})Then redeploy the site.
- 10,000 commands/day = ~416 commands/hour
- Example: If each config submission = 2 commands (check + increment):
- Can handle ~5,000 submissions/day on free tier
- Well above expected traffic for this site
- Pay-as-you-go pricing: $0.20 per 100K commands
- Pro tier: $120/month for 500M commands
For this site, free tier is sufficient unless you get massive viral traffic.
Check:
- ✅ Upstash credentials set in environment variables
- ✅ Vercel deployment restarted after adding credentials
- ✅ Check Vercel function logs for errors
Solution:
- Add
UPSTASH_REDIS_REST_URLandUPSTASH_REDIS_REST_TOKENto environment variables - Redeploy the site
Solution:
- Increase rate limits in
src/utils/ratelimit.ts - Consider different limits for authenticated vs anonymous users
✅ DO:
- Keep Upstash tokens secret (never commit to git)
- Use environment variables for credentials
- Monitor rate limit analytics for abuse patterns
- Adjust limits based on actual usage
❌ DON'T:
- Hardcode Upstash credentials in source code
- Share Upstash tokens publicly
- Set limits too low (frustrates legitimate users)
- Set limits too high (defeats the purpose)
- Upstash Docs: https://upstash.com/docs/redis
- Rate Limiting SDK: https://upstash.com/docs/redis/sdks/ratelimit-ts
- Vercel Environment Variables: https://vercel.com/docs/projects/environment-variables
Last Updated: 2026-01-17 Status: ✅ Implemented and tested