clerk-rate-limits
Provides strategies to handle Clerk rate limits using request throttling, retry logic, and header monitoring.
Install
mkdir -p .claude/skills/clerk-rate-limits && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/2392" && unzip -o skill.zip -d .claude/skills/clerk-rate-limits && rm skill.zipInstalls to .claude/skills/clerk-rate-limits
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Understand and manage Clerk rate limits and quotas.Key capabilities
- →Understand Clerk's rate limiting system
- →Implement retry logic for 429 responses
- →Batch multiple API operations to reduce requests
- →Cache user data to minimize API calls
- →Monitor rate limit usage with warnings
How it works
The skill provides strategies to manage Clerk API rate limits by implementing retry logic for 429 errors, batching operations, and caching data to reduce the number of API calls. It also includes monitoring for rate limit usage.
Inputs & outputs
When to use clerk-rate-limits
- →Implement API retry logic
- →Monitor Clerk rate limit headers
- →Debug 429 throttling errors
- →Optimize high-traffic API calls
About this skill
Clerk Rate Limits
Overview
Understand Clerk's rate limiting system and implement strategies to avoid hitting limits. Covers Backend API rate limits, retry logic, batching, caching, and monitoring.
Prerequisites
- Clerk account with API access
- Understanding of your application's traffic patterns
- Monitoring/logging infrastructure
Instructions
Step 1: Understand Rate Limits
Clerk Backend API enforces rate limits per API key:
| Plan | Rate Limit | Burst |
|---|---|---|
| Free | 20 req/10s | 40 |
| Pro | 100 req/10s | 200 |
| Enterprise | Custom | Custom |
Rate limit headers returned on every response:
X-RateLimit-Limit— max requests per windowX-RateLimit-Remaining— remaining requestsX-RateLimit-Reset— seconds until window resets
Step 2: Implement Rate Limit Handling with Retry
// lib/clerk-api.ts
import { createClerkClient } from '@clerk/backend'
const clerk = createClerkClient({ secretKey: process.env.CLERK_SECRET_KEY! })
async function withRetry<T>(fn: () => Promise<T>, maxRetries = 3): Promise<T> {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
return await fn()
} catch (err: any) {
if (err.status === 429 && attempt < maxRetries) {
// Parse retry-after header or use exponential backoff
const retryAfter = err.headers?.['retry-after']
const waitMs = retryAfter ? parseInt(retryAfter) * 1000 : Math.pow(2, attempt) * 1000
console.warn(`Rate limited. Retrying in ${waitMs}ms (attempt ${attempt + 1}/${maxRetries})`)
await new Promise((resolve) => setTimeout(resolve, waitMs))
continue
}
throw err
}
}
throw new Error('Max retries exceeded')
}
// Usage
export async function getUser(userId: string) {
return withRetry(() => clerk.users.getUser(userId))
}
Step 3: Batch Operations
// lib/clerk-batch.ts
import { createClerkClient } from '@clerk/backend'
const clerk = createClerkClient({ secretKey: process.env.CLERK_SECRET_KEY! })
async function batchGetUsers(userIds: string[], batchSize = 10) {
const results = []
for (let i = 0; i < userIds.length; i += batchSize) {
const batch = userIds.slice(i, i + batchSize)
const users = await Promise.all(batch.map((id) => clerk.users.getUser(id)))
results.push(...users)
// Respect rate limits between batches
if (i + batchSize < userIds.length) {
await new Promise((resolve) => setTimeout(resolve, 500))
}
}
return results
}
// For listing: use pagination instead of fetching all
async function getAllUsers() {
const allUsers = []
let offset = 0
const limit = 100
while (true) {
const batch = await clerk.users.getUserList({ limit, offset })
allUsers.push(...batch.data)
if (batch.data.length < limit) break
offset += limit
await new Promise((resolve) => setTimeout(resolve, 200)) // Rate limit pause
}
return allUsers
}
Step 4: Caching Strategy
// lib/clerk-cache.ts
const userCache = new Map<string, { user: any; cachedAt: number }>()
const CACHE_TTL = 60_000 // 1 minute
export async function getCachedUser(userId: string) {
const cached = userCache.get(userId)
if (cached && Date.now() - cached.cachedAt < CACHE_TTL) {
return cached.user
}
const { createClerkClient } = await import('@clerk/backend')
const clerk = createClerkClient({ secretKey: process.env.CLERK_SECRET_KEY! })
const user = await clerk.users.getUser(userId)
userCache.set(userId, { user, cachedAt: Date.now() })
return user
}
// Invalidate cache on webhook events
export function invalidateUserCache(userId: string) {
userCache.delete(userId)
}
For production, use Redis instead of in-memory cache:
import { Redis } from '@upstash/redis'
const redis = Redis.fromEnv()
export async function getCachedUserRedis(userId: string) {
const cached = await redis.get(`clerk:user:${userId}`)
if (cached) return cached
const clerk = createClerkClient({ secretKey: process.env.CLERK_SECRET_KEY! })
const user = await clerk.users.getUser(userId)
await redis.set(`clerk:user:${userId}`, JSON.stringify(user), { ex: 60 })
return user
}
Step 5: Monitor Rate Limit Usage
// lib/clerk-monitor.ts
let rateLimitHits = 0
export function trackRateLimit(response: Response) {
const remaining = parseInt(response.headers.get('X-RateLimit-Remaining') || '999')
const limit = parseInt(response.headers.get('X-RateLimit-Limit') || '0')
if (remaining < limit * 0.1) {
console.warn(`[Clerk] Rate limit warning: ${remaining}/${limit} remaining`)
}
if (remaining === 0) {
rateLimitHits++
console.error(`[Clerk] Rate limit hit! Total hits this session: ${rateLimitHits}`)
}
}
Output
- Retry logic with exponential backoff for 429 responses
- Batch operations respecting rate limits
- Multi-level caching (in-memory + Redis)
- Rate limit monitoring with warnings
Error Handling
| Error | Cause | Solution |
|---|---|---|
429 Too Many Requests | Rate limit exceeded | Implement retry with backoff, add caching |
quota_exceeded | Monthly MRU quota hit | Upgrade plan or reduce retained users |
| Concurrent limit hit | Too many parallel requests | Queue requests, reduce batchSize |
| Stale cache data | Cache not invalidated | Invalidate on user.updated webhook |
Examples
Quick Rate Limit Check
# Check current rate limit status
curl -s -D - -H "Authorization: Bearer $CLERK_SECRET_KEY" \
https://api.clerk.com/v1/users?limit=1 2>&1 | grep -i x-ratelimit
Resources
Next Steps
Proceed to clerk-security-basics for security best practices.
Prerequisites
Limitations
- →Rate limit exceeded results in 429 Too Many Requests
- →Monthly MAU quota hit results in quota_exceeded
- →Too many parallel requests can hit concurrent limits
How it compares
This skill provides specific code examples and strategies for managing Clerk API rate limits, unlike a generic API integration that might not account for throttling.
Compared to similar skills
clerk-rate-limits side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| clerk-rate-limits (this skill) | 1 | 27d | Caution | Intermediate |
| fastapi-templates | 520 | 2mo | No flags | Intermediate |
| android-kotlin-development | 268 | 5mo | Review | Advanced |
| fastapi-pro | 79 | 4mo | No flags | Advanced |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by jeremylongshore
View all by jeremylongshore →You might also like
fastapi-templates
wshobson
Create production-ready FastAPI projects with async patterns, dependency injection, and comprehensive error handling. Use when building new FastAPI applications or setting up backend API projects.
android-kotlin-development
aj-geddes
Develop native Android apps with Kotlin. Covers MVVM with Jetpack, Compose for modern UI, Retrofit for API calls, Room for local storage, and navigation architecture.
fastapi-pro
sickn33
Build high-performance async APIs with FastAPI, SQLAlchemy 2.0, and Pydantic V2. Master microservices, WebSockets, and modern Python async patterns. Use PROACTIVELY for FastAPI development, async optimization, or API architecture.
telegram-bot-builder
davila7
Expert in building Telegram bots that solve real problems - from simple automation to complex AI-powered bots. Covers bot architecture, the Telegram Bot API, user experience, monetization strategies, and scaling bots to thousands of users. Use when: telegram bot, bot api, telegram automation, chat bot telegram, tg bot.
telegram-mini-app
davila7
Expert in building Telegram Mini Apps (TWA) - web apps that run inside Telegram with native-like experience. Covers the TON ecosystem, Telegram Web App API, payments, user authentication, and building viral mini apps that monetize. Use when: telegram mini app, TWA, telegram web app, TON app, mini app.
stripe-integration
wshobson
Implement Stripe payment processing for robust, PCI-compliant payment flows including checkout, subscriptions, and webhooks. Use when integrating Stripe payments, building subscription systems, or implementing secure checkout flows.