On this page

Elysia Plugin

hitlimit provides a first-class plugin for Elysia, the ergonomic web framework for Bun. The plugin integrates seamlessly with Elysia's plugin system and provides type-safe rate limiting.

Installation

Install hitlimit-bun alongside Elysia:

bun add @joint-ops/hitlimit-bun elysia

Basic Usage

Add rate limiting to your Elysia application:

app.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 World!')
  .get('/api/data', () => ({ data: 'protected' }))
  .listen(3000)

console.log('Server running on port 3000')

Route-Specific Limits

Apply different limits to specific route groups using the name option. Each instance needs a unique name so Elysia registers them separately:

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

const app = new Elysia()
  // Global rate limit
  .use(hitlimit({ limit: 100, window: '1m', name: 'global' }))

  // Public routes
  .get('/', () => 'Welcome')

  // Stricter limit for auth routes
  .group('/auth', (app) =>
    app
      .use(hitlimit({ limit: 5, window: '15m', name: 'auth' }))
      .post('/login', ({ body }) => 'Login')
      .post('/register', ({ body }) => 'Register')
  )

  // Higher limit for API routes
  .group('/api', (app) =>
    app
      .use(hitlimit({ limit: 1000, window: '1m', name: 'api' }))
      .get('/users', () => [])
      .get('/posts', () => [])
  )
  .listen(3000)

Custom Key Extraction

Rate limit by user ID, API key, or other identifiers:

custom-key.ts
const app = new Elysia()
  .use(hitlimit({
    limit: 100,
    window: '1m',
    key({ request }) {
      // Rate limit by API key header
      return request.headers.get('x-api-key') || 'anonymous'
    }
  }))
  .get('/api', () => 'Protected')

Custom Error Response

Customize the rate limit exceeded response:

custom-response.ts
const app = new Elysia()
  .use(hitlimit({
    limit: 100,
    window: '1m',
    response: {
      error: 'Too many requests',
      message: 'Please slow down'
    }
  }))
  .get('/', () => 'Hello')

Using Stores

Use SQLite or Redis stores for persistence:

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

const app = new Elysia()
  .use(hitlimit({
    limit: 100,
    window: '1m',
    store: sqliteStore({
      path: './rate-limits.db'
    })
  }))
  .get('/', () => 'Hello World')
  .listen(3000)

Plugin Options

Option Type Description
limit number Maximum requests per window (default: 100)
window string Time window (e.g., '1m', '1h') (default: '1m')
name string Unique plugin name for multiple instances (auto-generated if omitted)
key function Custom key extraction function
store Store Storage backend (memory, sqlite, redis)
response object | function Custom 429 response body
skip function Function to skip rate limiting for certain requests
tiers object Tiered rate limit configurations
tier function Function to resolve which tier a request belongs to

Next Steps