On this page

Bun.serve Integration

hitlimit provides direct integration with Bun's native HTTP server for maximum performance. This guide covers patterns for using rate limiting with Bun.serve.

Basic Integration

Add rate limiting to any Bun.serve application:

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 World!')
  }
})

Route-Based Rate Limiting

Apply different limits to different routes:

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

// Different limiters for different endpoints
const apiLimiter = createHitLimit({ limit: 100, window: '1m' })
const authLimiter = createHitLimit({ limit: 5, window: '15m' })
const uploadLimiter = createHitLimit({ limit: 10, window: '1h' })

Bun.serve({
  port: 3000,
  async fetch(req, server) {
    const url = new URL(req.url)

    // Select limiter based on route
    let limiter = apiLimiter
    if (url.pathname.startsWith('/auth')) {
      limiter = authLimiter
    } else if (url.pathname.startsWith('/upload')) {
      limiter = uploadLimiter
    }

    const response = await limiter.check(req, server)
    if (response) return response

    // Route handling...
    return new Response('OK')
  }
})

IP Address Extraction

Extract client IP from various headers:

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

const limiter = createHitLimit({
  limit: 100,
  window: '1m',
  key(req, server) {
    // Check for proxy headers first
    const forwarded = req.headers.get('X-Forwarded-For')
    if (forwarded) {
      return forwarded.split(',')[0].trim()
    }

    // Cloudflare
    const cfIP = req.headers.get('CF-Connecting-IP')
    if (cfIP) return cfIP

    // Fallback to Bun's socket address
    return server.requestIP(req)?.address || 'unknown'
  }
})

WebSocket Support

Rate limit WebSocket connections:

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

const wsLimiter = createHitLimit({ limit: 10, window: '1m' })

Bun.serve({
  port: 3000,
  async fetch(req, server) {
    if (req.headers.get('upgrade') === 'websocket') {
      const response = await wsLimiter.check(req, server)
      if (response) return response

      server.upgrade(req)
      return
    }

    return new Response('Use WebSocket')
  },
  websocket: {
    message(ws, msg) {
      ws.send(`Echo: ${msg}`)
    }
  }
})

Error Handling

Handle rate limiter errors gracefully:

async fetch(req, server) {
  try {
    const response = await limiter.check(req, server)
    if (response) return response
  } catch (error) {
    // Log error but allow request (fail-open)
    console.error('Rate limiter error:', error)
  }

  return new Response('OK')
}

Next Steps