Give users free tiers without getting surprised by a massive API bill.
Asillios is an open source TypeScript library for per-user rate limiting, usage stats, and threshold alerts.
95+ downloads on npmCopy this prompt to add rate limiting with Claude Code, Cursor, or any other AI assistant.
Add rate limiting to my app using asillios-limiter. Install it (ex. npm install asillios-limiter) Use limiter.wrap() to track token usage from OpenAI or Anthropic. Docs at asillios.com.

The name comes from the Greek ásylon, a sacred refuge where nothing could be seized. Asillios (a- without + sill- seizure + -ios one who is) is your software's sanctuary from unexpected costs.
Simple Integration
Wrap your LLM calls with a few lines of code. Auto-detects OpenAI and Anthropic response formats.
Per-User Tracking
Track token consumption per user. Set limits, get alerts when users approach quotas, identify power users.
Threshold Alerts
Get notified at 80%, 90%, 100% usage. Custom callbacks for billing integration or user notifications.
Production Ready
In-memory storage by default. Plug in Redis or any database with the StorageAdapter interface.
1import { createLimiter } from "asillios-limiter";23const limiter = createLimiter({4 limit: 100000, // 100k tokens per window5 window: 60 * 60 * 1000, // 1 hour6 thresholds: [80, 90, 100],7 onThreshold: (userId, percent) => {8 console.log(`user ${userId} hit ${percent}% of their limit`);9 },10});
1// Works with OpenAI2const response = await limiter.wrap("user-123", async () => {3 return openai.chat.completions.create({4 model: "gpt-4",5 messages: [{ role: "user", content: "hello" }],6 });7});89// Works with Anthropic too10const response = await limiter.wrap("user-123", async () => {11 return anthropic.messages.create({12 model: "claude-3-sonnet-20240229",13 max_tokens: 1024,14 messages: [{ role: "user", content: "hello" }],15 });16});
1// Check if user can make more requests2const canProceed = await limiter.check("user-123");34// Get detailed stats5const stats = await limiter.stats("user-123");6console.log(stats);7// { tokensUsed: 150, remaining: 99850, resetAt: Date, percentUsed: 0.15 }89// Manually add tokens (useful for streaming)10await limiter.addTokens("user-123", 500);1112// Reset a user's usage13await limiter.reset("user-123");
1import { createLimiter, StorageAdapter, UserData } from "asillios-limiter";23class RedisStorage implements StorageAdapter {4 async get(userId: string): Promise<UserData | null> {5 const data = await redis.get(`limiter:${userId}`);6 if (!data) return null;7 const parsed = JSON.parse(data);8 return {9 ...parsed,10 resetAt: new Date(parsed.resetAt),11 thresholdsTriggered: new Set(parsed.thresholdsTriggered),12 };13 }1415 async set(userId: string, data: UserData): Promise<void> {16 await redis.set(`limiter:${userId}`, JSON.stringify({17 ...data,18 thresholdsTriggered: [...data.thresholdsTriggered],19 }));20 }2122 async delete(userId: string): Promise<void> {23 await redis.del(`limiter:${userId}`);24 }25}2627const limiter = createLimiter({28 limit: 100000,29 window: 60 * 60 * 1000,30 storage: new RedisStorage(),31});