bunlimit
bunlimit
DocumentationGitHub Introduction Installation Usage Algorithms Adapters API Reference

API Reference

Complete API documentation

Ratelimit

The main class for rate limiting.

Constructor

new Ratelimit(config: RatelimitConfig)

RatelimitConfig

PropertyTypeRequiredDescription
redisRedisClientNo*Bun Redis client instance
adapterRedisAdapterNo*Custom Redis adapter
limiterAlgorithmYesRate limiting algorithm
prefixstringNoKey prefix (default: "ratelimit")
analyticsbooleanNoEnable analytics (default: false)
onLimitExceededFunctionNoCallback when limit exceeded

*Either redis or adapter must be provided.

Example

const ratelimit = new Ratelimit({
  redis: new RedisClient(),
  limiter: fixedWindow(10, 60),
  prefix: 'api',
  analytics: true,
  onLimitExceeded: async (identifier, response) => {
    console.log(`Limit exceeded for ${identifier}`)
  },
})

Methods

limit()

Rate limit a single identifier.

limit(identifier: string): Promise<RatelimitResponse>

Parameters:

  • identifier - Unique identifier (user ID, IP address, API key, etc.)

Returns:

interface RatelimitResponse {
  success: boolean // Whether request is allowed
  limit: number // Maximum requests allowed
  remaining: number // Requests remaining
  reset: number // Timestamp when limit resets (ms)
  pending: Promise<unknown> // Internal promise
}

Example:

const { success, remaining, reset } = await ratelimit.limit('user-123')

if (!success) {
  throw new Error(`Rate limit exceeded. Try again at ${new Date(reset)}`)
}

multiLimit()

Rate limit multiple identifiers at once.

multiLimit(identifiers: string[]): Promise<MultiRatelimitResponse[]>

Parameters:

  • identifiers - Array of unique identifiers

Returns:

interface MultiRatelimitResponse {
  identifier: string // The identifier
  success: boolean // Whether request is allowed
  limit: number // Maximum requests allowed
  remaining: number // Requests remaining
  reset: number // Timestamp when limit resets (ms)
}

Example:

const results = await ratelimit.multiLimit(['user-1', 'user-2', 'user-3'])

for (const result of results) {
  console.log(`${result.identifier}: ${result.success ? 'allowed' : 'denied'}`)
}

reset()

Reset rate limit for an identifier.

reset(identifier: string): Promise<void>

Parameters:

  • identifier - Identifier to reset

Example:

await ratelimit.reset('user-123')

getRemaining()

Get remaining requests for an identifier.

getRemaining(identifier: string): Promise<number>

Parameters:

  • identifier - Identifier to check

Returns:

  • Number of remaining requests

Example:

const remaining = await ratelimit.getRemaining('user-123')
console.log(`${remaining} requests remaining`)

getAnalytics()

Get analytics for an identifier (requires analytics: true).

getAnalytics(identifier: string): Promise<{ allowed: number; denied: number } | null>

Parameters:

  • identifier - Identifier to get analytics for

Returns:

  • Object with allowed and denied counts, or null if analytics disabled

Example:

const stats = await ratelimit.getAnalytics('user-123')
if (stats) {
  console.log(`Allowed: ${stats.allowed}, Denied: ${stats.denied}`)
}

Algorithm Presets

fixedWindow()

Create a fixed window algorithm.

fixedWindow(limit: number, window: number): Algorithm

Parameters:

  • limit - Maximum number of requests
  • window - Time window in seconds

Example:

const limiter = fixedWindow(10, 60) // 10 requests per 60 seconds

slidingWindow()

Create a sliding window algorithm.

slidingWindow(limit: number, window: number): Algorithm

Parameters:

  • limit - Maximum number of requests
  • window - Time window in seconds

Example:

const limiter = slidingWindow(10, 60) // 10 requests per 60 seconds

tokenBucket()

Create a token bucket algorithm.

tokenBucket(limit: number, window: number, refillRate?: number): Algorithm

Parameters:

  • limit - Maximum number of tokens
  • window - Time window in seconds
  • refillRate - Tokens per second (default: limit / window)

Example:

const limiter = tokenBucket(10, 60, 0.5) // 10 tokens, refills at 0.5/sec

Adapters

BunRedisAdapter

Adapter for Bun's native Redis client.

new BunRedisAdapter(client: RedisClient)

Example:

import { RedisClient } from 'bun'
import { BunRedisAdapter } from 'bunlimit'

const redis = new RedisClient('redis://localhost:6379')
const adapter = new BunRedisAdapter(redis)

IoRedisAdapter

Adapter for ioredis.

new IoRedisAdapter(client: Redis)

Example:

import Redis from 'ioredis'
import { IoRedisAdapter } from 'bunlimit'

const redis = new Redis()
const adapter = new IoRedisAdapter(redis)

NodeRedisAdapter

Adapter for node-redis (v4+).

new NodeRedisAdapter(client: RedisClientType)

Example:

import { createClient } from 'redis'
import { NodeRedisAdapter } from 'bunlimit'

const redis = createClient()
await redis.connect()
const adapter = new NodeRedisAdapter(redis)

DenoKvAdapter

Adapter for Deno KV.

new DenoKvAdapter(kv: Deno.Kv)

Example:

import { openKv } from '@deno/kv'
import { DenoKvAdapter } from 'bunlimit'

const kv = await openKv('http://localhost:4512')
const adapter = new DenoKvAdapter(kv)

Types

RedisAdapter

Interface for creating custom adapters.

interface RedisAdapter {
  incr(key: string): Promise<number>
  get(key: string): Promise<string | null>
  set(key: string, value: string): Promise<void>
  expire(key: string, seconds: number): Promise<void>
  del(...keys: string[]): Promise<void>
  keys(pattern: string): Promise<string[]>
  hincrby(key: string, field: string, increment: number): Promise<number>
  hmget(key: string, fields: string[]): Promise<(string | null)[]>
  hmset(key: string, data: string[]): Promise<void>
}

Algorithm

Rate limiting algorithm configuration.

interface Algorithm {
  type: 'fixed-window' | 'sliding-window' | 'token-bucket'
  limit: number
  window: number
  refillRate?: number // Only for token-bucket
}

Callbacks

onLimitExceeded

Callback function triggered when rate limit is exceeded.

type OnLimitExceeded = (identifier: string, response: RatelimitResponse) => void | Promise<void>

Example:

const callback: OnLimitExceeded = async (identifier, response) => {
  console.log(`Rate limit exceeded for ${identifier}`)
  console.log(`Reset at: ${new Date(response.reset)}`)
  await sendNotification(identifier)
}

Error Handling

Common Errors

Missing Redis Configuration

// ❌ Error: Either adapter or redis must be provided
new Ratelimit({
  limiter: fixedWindow(10, 60),
})
// ✅ Correct
new Ratelimit({
  redis: new RedisClient(),
  limiter: fixedWindow(10, 60),
})

Connection Errors

try {
  const result = await ratelimit.limit('user-123')
} catch (error) {
  if (error.code === 'ERR_REDIS_CONNECTION_CLOSED') {
    console.error('Redis connection closed')
  } else {
    console.error('Unexpected error:', error)
  }
}

TypeScript

bunlimit is written in TypeScript and provides full type definitions.

Import Types

import type { RatelimitConfig, RatelimitResponse, MultiRatelimitResponse, Algorithm, RedisAdapter } from 'bunlimit'

Type-Safe Configuration

const config: RatelimitConfig = {
  redis: new RedisClient(),
  limiter: fixedWindow(10, 60),
  prefix: 'api',
  analytics: true,
  onLimitExceeded: async (identifier, response) => {
    // TypeScript knows the types here
    console.log(identifier.toUpperCase())
    console.log(response.reset.toFixed(0))
  },
}

const ratelimit = new Ratelimit(config)

Custom Adapter with Types

import type { RedisAdapter } from 'bunlimit'

class MyAdapter implements RedisAdapter {
  async incr(key: string): Promise<number> {
    // Implementation
    return 1
  }

  // ... implement other methods
}

Adapters

Use different Redis clients with bunlimit

On this page

RatelimitConstructorRatelimitConfigExampleMethodslimit()multiLimit()reset()getRemaining()getAnalytics()Algorithm PresetsfixedWindow()slidingWindow()tokenBucket()AdaptersBunRedisAdapterIoRedisAdapterNodeRedisAdapterDenoKvAdapterTypesRedisAdapterAlgorithmCallbacksonLimitExceededError HandlingCommon ErrorsMissing Redis ConfigurationConnection ErrorsTypeScriptImport TypesType-Safe ConfigurationCustom Adapter with Types