Skip to content

Antonio476587/psyque-rate-limiter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@psyque/rate-limiter

Composable rate limiting for Deno/Oak with pluggable storage backends.

Quick Start

import { createRateLimiter, MemoryStorageAdapter } from "@psyque/rate-limiter";

const storage = new MemoryStorageAdapter();

const limiter = createRateLimiter(storage, {
  prefix: "api",
  maxAttempts: 100,
  windowSeconds: 60,
});

router.get("/api/data", limiter, handler);

Storage Adapters

Memory (built-in)

Zero-dependency, works out of the box. Suitable for testing and single-process deployments.

import { MemoryStorageAdapter } from "@psyque/rate-limiter";
const storage = new MemoryStorageAdapter();

Redis

For production multi-process / multi-node deployments. Inject any Redis-compatible client.

import { connect } from "@db/redis";
import { RedisStorageAdapter } from "@psyque/rate-limiter";

const redis = await connect({ hostname: "localhost", port: 6379 });
const storage = new RedisStorageAdapter(redis);

Custom

Implement the StorageAdapter interface for any backend:

import type { StorageAdapter } from "@psyque/rate-limiter";

class MyStorageAdapter implements StorageAdapter {
  async get(key: string): Promise<string | null> {/* ... */}
  async set(key: string, value: string, ttlSeconds: number): Promise<void> {
    /* ... */
  }
  async increment(key: string): Promise<number> {/* ... */}
  async decrement(key: string): Promise<number> {/* ... */}
  async delete(key: string): Promise<void> {/* ... */}
  async ttl(key: string): Promise<number> {/* ... */}
}

Configuration

Class-based API

Use RateLimiterFactoryImpl for a factory pattern with multiple limiter types:

import {
  KeyGenerationStrategy,
  MemoryStorageAdapter,
  RateLimiterFactoryImpl,
} from "@psyque/rate-limiter";

const storage = new MemoryStorageAdapter();
const factory = new RateLimiterFactoryImpl(storage);

const limiter = factory.createRateLimiter({
  serviceName: "my-service",
  enabled: true,
  addHeaders: true,
  keyGenerationStrategy: KeyGenerationStrategy.USER_BASED,
  thresholds: {
    general: { maxAttempts: 200, windowSeconds: 60 },
    write: { maxAttempts: 50, windowSeconds: 60 },
    apiKey: { maxAttempts: 500, windowSeconds: 60 },
  },
});

// Apply to routes
router.get("/", limiter.getGeneralLimiter(), handler);
router.post("/", limiter.getWriteLimiter(), handler);
router.use(limiter.getSmartLimiter()); // auto-selects by method

Service Rate Limiter

For service-oriented architectures with per-endpoint overrides:

import {
  createServiceRateLimiter,
  MemoryStorageAdapter,
} from "@psyque/rate-limiter";

const storage = new MemoryStorageAdapter();

const limiters = createServiceRateLimiter(storage, {
  serviceName: "comment",
  general: { maxAttempts: 300, windowSeconds: 60 },
  write: { maxAttempts: 60, windowSeconds: 60 },
  apiKey: { maxAttempts: 600, windowSeconds: 60 },
  endpoints: {
    search: { maxAttempts: 30, windowSeconds: 60 },
  },
});

router.get("/", limiters.general, handler);
router.post("/", limiters.write, handler);
router.get("/search", limiters.forEndpoint("search"), handler);

Key Generation Strategies

Strategy Description
IP_BASED Rate limit by client IP address (default)
USER_BASED Rate limit by user ID, fallback to IP
API_KEY_BASED Rate limit by API key → user ID → IP
COMBINED Uses both user ID and IP together

Response Headers

All middleware automatically sets standard rate-limit headers:

Header Description
X-RateLimit-Limit Maximum requests allowed
X-RateLimit-Remaining Requests remaining in window
X-RateLimit-Reset Unix timestamp when window resets
Retry-After Seconds until retry (only on 429)

License

MIT

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors