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:
import { hitlimit } from '@joint-ops/hitlimit-bun'
const limiter = hitlimit({ limit: 100, window: '1m' })
Bun.serve({
port: 3000,
async fetch(req) {
const { allowed, remaining, reset, limit } = await limiter.check(req)
const headers = {
'X-RateLimit-Limit': String(limit),
'X-RateLimit-Remaining': String(remaining),
'X-RateLimit-Reset': String(reset)
}
if (!allowed) {
return new Response('Rate limit exceeded', {
status: 429,
headers: { ...headers, 'Retry-After': String(reset) }
})
}
return new Response('Hello World!', { headers })
}
}) Route-Based Rate Limiting
Apply different limits to different routes:
import { hitlimit } from '@joint-ops/hitlimit-bun'
// Different limiters for different endpoints
const apiLimiter = hitlimit({ limit: 100, window: '1m' })
const authLimiter = hitlimit({ limit: 5, window: '15m' })
const uploadLimiter = hitlimit({ limit: 10, window: '1h' })
Bun.serve({
port: 3000,
async fetch(req) {
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 result = await limiter.check(req)
if (!result.allowed) {
return new Response('Rate limited', { status: 429 })
}
// Route handling...
return new Response('OK')
}
}) IP Address Extraction
Extract client IP from various headers:
import { hitlimit } from '@joint-ops/hitlimit-bun'
const limiter = hitlimit({
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:
import { hitlimit } from '@joint-ops/hitlimit-bun'
const wsLimiter = hitlimit({ limit: 10, window: '1m' })
Bun.serve({
port: 3000,
async fetch(req, server) {
if (req.headers.get('upgrade') === 'websocket') {
const result = await wsLimiter.check(req)
if (!result.allowed) {
return new Response('Too many connections', { status: 429 })
}
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) {
try {
const result = await limiter.check(req)
if (!result.allowed) {
return new Response('Rate limited', { status: 429 })
}
} catch (error) {
// Log error but allow request (fail-open)
console.error('Rate limiter error:', error)
}
return new Response('OK')
} Next Steps
- Elysia Plugin - Use with Elysia framework
- Stores - Native SQLite configuration
- Performance - Optimization tips