On this page

hitlimit() Function (Bun)

Using Node.js? See the Node.js hitlimit() API for @joint-ops/hitlimit.

The @joint-ops/hitlimit-bun package exports two functions for rate limiting:

  • hitlimit(options, handler) — wraps a request handler, returns a Bun-compatible fetch function
  • createHitLimit(options) — returns a { check, reset } object for manual control

hitlimit(options, handler)

function hitlimit(
  options: HitLimitOptions,
  handler: (req: Request, server: BunServer) => Response | Promise<Response>
): (req: Request, server: BunServer) => Response | Promise<Response>

Wraps your handler with rate limiting. The returned function is passed directly to Bun.serve as the fetch handler.

server.ts
import { hitlimit } from '@joint-ops/hitlimit-bun'

Bun.serve({
  port: 3000,
  fetch: hitlimit(
    { limit: 100, window: '1m' },
    (req) => new Response('Hello!')
  )
})

createHitLimit(options)

function createHitLimit(options: HitLimitOptions): {
  check(req: Request, server: BunServer): Promise<Response | null>
  reset(key: string): void
}

Returns an object for manual rate limit control. check() returns a 429 Response if rate limited, or null if the request should proceed.

server.ts
import { createHitLimit } from '@joint-ops/hitlimit-bun'

const limiter = createHitLimit({ limit: 100, window: '1m' })

Bun.serve({
  port: 3000,
  async fetch(req, server) {
    const response = await limiter.check(req, server)
    if (response) return response

    return new Response('Hello!')
  }
})

Options Object

PropertyTypeDefaultDescription
limitnumber100Maximum requests per window
windowstring | number'1m'Time window duration (e.g., '1m', '1h', or milliseconds)
key(req, server) => string-Key extraction function
storeHitLimitStorememoryStore()Storage backend (memory, sqlite, redis)
skip(req, server) => boolean-Skip rate limiting for certain requests
headersHeadersConfig-Rate limit response headers configuration
responseobject | (info) => object-Custom error response body
tiersRecord<string, TierConfig>-Named tier configurations with per-tier limit and window
tier(req) => string-Function to resolve which tier a request belongs to
banBanConfig-Auto-ban clients after repeated violations (threshold + duration)
onStoreError(error, req) => void-Handler called when the store throws

Adapter Usage

For Elysia and Hono, use the built-in adapters. Adapters handle key extraction, headers, and error responses automatically.

Elysia Plugin

elysia-plugin.ts
import { Elysia } from 'elysia'
import { hitlimit } from '@joint-ops/hitlimit-bun/elysia'

const app = new Elysia()
  .use(hitlimit({ limit: 100, window: '1m' }))
  .get('/', () => 'Hello!')
  .listen(3000)

Hono Middleware

hono-middleware.ts
import { Hono } from 'hono'
import { hitlimit } from '@joint-ops/hitlimit-bun/hono'

const app = new Hono()
app.use(hitlimit({ limit: 100, window: '1m' }))
app.get('/', (c) => c.text('Hello!'))

Bun.serve({ port: 3000, fetch: app.fetch })

For full adapter documentation, see Bun.serve, Elysia Plugin, and Hono Middleware.

Advanced Usage

Tiered Limits

Apply different rate limits based on user plans using the tiers and tier options:

tiered.ts
import { createHitLimit } from '@joint-ops/hitlimit-bun'

const limiter = createHitLimit({
  tiers: {
    free:       { limit: 100,   window: '1h' },
    pro:        { limit: 1000,  window: '1m' },
    enterprise: { limit: 10000, window: '1m' }
  },
  tier: (req) => req.headers.get('x-plan') || 'free'
})

Bun.serve({
  port: 3000,
  async fetch(req, server) {
    const response = await limiter.check(req, server)
    if (response) return response

    return new Response('OK')
  }
})

Ban Configuration

Automatically ban clients that repeatedly exceed rate limits:

ban.ts
import { createHitLimit } from '@joint-ops/hitlimit-bun'

const limiter = createHitLimit({
  limit: 10,
  window: '1m',
  ban: {
    threshold: 5,
    duration: '1h'
  }
})

Bun.serve({
  port: 3000,
  async fetch(req, server) {
    const response = await limiter.check(req, server)
    if (response) return response

    return new Response('Hello!')
  }
})

Redis Store

Use Redis for distributed rate limiting across multiple servers:

redis.ts
import { createHitLimit } from '@joint-ops/hitlimit-bun'
import { redisStore } from '@joint-ops/hitlimit-bun/stores/redis'

const limiter = createHitLimit({
  limit: 500,
  window: '5m',
  store: redisStore({ url: 'redis://localhost:6379' })
})

Bun.serve({
  port: 3000,
  async fetch(req, server) {
    const response = await limiter.check(req, server)
    if (response) return response

    return new Response('OK')
  }
})

Store Error Handling

Control behavior when the store is unavailable:

const limiter = createHitLimit({
  limit: 100,
  window: '1m',
  store: redisStore({ url: 'redis://localhost:6379' }),
  onStoreError(error) {
    console.error('Store error:', error)
  }
})