Asillios

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 npm
npm install asillios-limiter
Star on GitHub

Copy 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.

Simple Integration

Wrap your LLM calls with a few lines of code. Auto-detects OpenAI and Anthropic response formats.

0%
[░░░░░░░░░░░░░░░░░░░░]
tokens used this window

Per-User Tracking

Track token consumption per user. Set limits, get alerts when users approach quotas, identify power users.

user-a
85%
user-b
42%
user-c
91%
user-d
23%

Threshold Alerts

Get notified at 80%, 90%, 100% usage. Custom callbacks for billing integration or user notifications.

Waiting for threshold events...

Production Ready

In-memory storage by default. Plug in Redis or any database with the StorageAdapter interface.

Quick Start

Basic Setup
1import { createLimiter } from "asillios-limiter";
2
3const limiter = createLimiter({
4 limit: 100000, // 100k tokens per window
5 window: 60 * 60 * 1000, // 1 hour
6 thresholds: [80, 90, 100],
7 onThreshold: (userId, percent) => {
8 console.log(`user ${userId} hit ${percent}% of their limit`);
9 },
10});
Wrap your LLM calls
1// Works with OpenAI
2const 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});
8
9// Works with Anthropic too
10const 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});
Check usage and stats
1// Check if user can make more requests
2const canProceed = await limiter.check("user-123");
3
4// Get detailed stats
5const stats = await limiter.stats("user-123");
6console.log(stats);
7// { tokensUsed: 150, remaining: 99850, resetAt: Date, percentUsed: 0.15 }
8
9// Manually add tokens (useful for streaming)
10await limiter.addTokens("user-123", 500);
11
12// Reset a user's usage
13await limiter.reset("user-123");
Custom Storage (Redis example)
1import { createLimiter, StorageAdapter, UserData } from "asillios-limiter";
2
3class 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 }
14
15 async set(userId: string, data: UserData): Promise<void> {
16 await redis.set(`limiter:${userId}`, JSON.stringify({
17 ...data,
18 thresholdsTriggered: [...data.thresholdsTriggered],
19 }));
20 }
21
22 async delete(userId: string): Promise<void> {
23 await redis.del(`limiter:${userId}`);
24 }
25}
26
27const limiter = createLimiter({
28 limit: 100000,
29 window: 60 * 60 * 1000,
30 storage: new RedisStorage(),
31});