Hono Adapter
The Hono adapter provides seamless integration with Hono applications using the official createMiddleware pattern.
Installation
npm install @joint-ops/hitlimit hono
# or: pnpm add @joint-ops/hitlimit hono bun add @joint-ops/hitlimit-bun hono Basic Usage
Use hitlimit as Hono middleware:
app.ts
import { Hono } from 'hono'
import { serve } from '@hono/node-server'
import { hitlimit } from '@joint-ops/hitlimit/hono'
const app = new Hono()
// Apply to all routes
app.use(hitlimit({
limit: 100,
window: '1m'
}))
app.get('/', (c) => c.text('Hello World'))
serve({ fetch: app.fetch, port: 3000 }) app.ts
import { Hono } from 'hono'
import { hitlimit } from '@joint-ops/hitlimit-bun/hono'
const app = new Hono()
// Apply to all routes
app.use(hitlimit({
limit: 100,
window: '1m'
}))
app.get('/', (c) => c.text('Hello Bun + Hono!'))
Bun.serve({ port: 3000, fetch: app.fetch }) Route-Specific Rate Limiting
Apply different limits to specific routes:
const app = new Hono()
// Public routes
app.get('/', (c) => c.text('Welcome'))
// Strict limit for auth routes
const auth = new Hono()
auth.use(hitlimit({ limit: 5, window: '15m' }))
auth.post('/login', (c) => c.json({ success: true }))
auth.post('/register', (c) => c.json({ success: true }))
// Higher limit for API routes
const api = new Hono()
api.use(hitlimit({ limit: 1000, window: '1m' }))
api.get('/users', (c) => c.json([]))
api.get('/posts', (c) => c.json([]))
app.route('/auth', auth)
app.route('/api', api) Custom Key Extraction
Rate limit by user ID, API key, or custom identifiers:
app.use(hitlimit({
limit: 100,
window: '1m',
key: (c) => {
// Rate limit by custom header
return c.req.header('x-api-key') || 'anonymous'
}
})) Tiered Limits
Apply different limits based on user plan or tier:
app.use(hitlimit({
tiers: {
free: { limit: 10, window: '1m' },
pro: { limit: 100, window: '1m' },
enterprise: { limit: Infinity }
},
tier: (c) => {
return c.req.header('x-plan') || 'free'
}
})) Skipping Requests
Bypass rate limiting for certain requests:
hitlimit({
limit: 100,
window: '1m',
skip: (c) => {
// Skip health checks and internal requests
return c.req.path === '/health' ||
c.req.header('x-internal') === 'true'
}
}) Custom Error Response
Customize the response when rate limit is exceeded:
hitlimit({
limit: 100,
window: '1m',
response: (info) => ({
error: 'RATE_LIMIT_EXCEEDED',
message: `Too many requests. Try again in ${info.resetIn} seconds.`,
retryAfter: info.resetIn
})
}) Using with Stores
Use Redis or SQLite for distributed rate limiting:
import { hitlimit } from '@joint-ops/hitlimit/hono'
import { redisStore } from '@joint-ops/hitlimit/stores/redis'
app.use(hitlimit({
limit: 100,
window: '1m',
store: redisStore({
url: 'redis://localhost:6379'
})
})) import { hitlimit } from '@joint-ops/hitlimit-bun/hono'
import { sqliteStore } from '@joint-ops/hitlimit-bun/stores/sqlite'
app.use(hitlimit({
limit: 100,
window: '1m',
store: sqliteStore({
path: './rate-limits.db'
})
})) Migrating from hono-rate-limiter
If you're coming from hono-rate-limiter, hitlimit offers a similar API with more features:
Before (hono-rate-limiter)
import { rateLimiter } from 'hono-rate-limiter'
app.use(rateLimiter({
windowMs: 60000, // milliseconds
limit: 100,
keyGenerator: (c) => c.req.header('x-api-key')
})) After (hitlimit)
app.use(hitlimit({
window: '1m', // human-readable!
limit: 100,
key: (c) => c.req.header('x-api-key') || 'anonymous'
})) Key improvements:
- Human-readable time windows —
'1m'instead of milliseconds - Built-in tiered limits — No manual tier management needed
- Zero runtime dependencies — no external packages needed
- More stores — Memory, SQLite, Redis built-in (no separate packages)
- Better TypeScript — Full type inference for all options