
Security News
Socket Releases Free Certified Patches for Critical vm2 Sandbox Escape
A critical vm2 sandbox escape can allow untrusted JavaScript to break isolation and execute commands on the host Node.js process.
@joint-ops/hitlimit-bun
Advanced tools
Ultra-fast Bun-native rate limiting - Memory-first with 6M+ ops/sec for Bun.serve, Elysia & Hono
Rate limiting built for Bun. Not ported β built.
7.73M ops/sec on memory. 5.57M at 10K IPs. Native bun:sqlite. Atomic Redis Lua. Postgres. Zero dependencies.
bun add @joint-ops/hitlimit-bun
Bun.serve({
fetch: hitlimit({}, (req) => new Response('Hello!'))
})
One line. Done. Works with Bun.serve, Elysia, and Hono out of the box.
Docs Β· GitHub Β· Benchmarks
import { hitlimit } from '@joint-ops/hitlimit-bun'
Bun.serve({
fetch: hitlimit({ limit: 100, window: '1m' }, (req) => {
return new Response('Hello!')
})
})
import { Elysia } from 'elysia'
import { hitlimit } from '@joint-ops/hitlimit-bun/elysia'
new Elysia()
.use(hitlimit({ limit: 100, window: '1m' }))
.get('/', () => 'Hello!')
.listen(3000)
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 })
Tiered limits β Free, Pro, Enterprise:
hitlimit({
tiers: { free: { limit: 100, window: '1h' }, pro: { limit: 5000, window: '1h' } },
tier: (req) => req.headers.get('x-tier') || 'free'
}, handler)
Auto-ban β Repeat offenders get blocked:
hitlimit({ limit: 10, window: '1m', ban: { threshold: 5, duration: '1h' } }, handler)
Custom keys β Rate limit by anything:
hitlimit({ key: (req) => req.headers.get('x-api-key') || 'anon' }, handler)
Route-specific limits (Elysia):
new Elysia()
.use(hitlimit({ limit: 100, window: '1m', name: 'global' }))
.group('/auth', app => app.use(hitlimit({ limit: 5, window: '15m', name: 'auth' })))
.listen(3000)
Every store is built in. Swap one line β your rate limiting code stays the same.
Single Server Multi-Server
ββββββββββββββββββββββββ ββββββββββββββββββββββββββββ
β Memory β SQLite β β Redis β Postgres β
β (default) (bun:sqlite) β Valkey β MongoDB β
β β β Dragonfly MySQL β
ββββββββββββββββββββββββ ββββββββββββββββββββββββββββ
No dependencies at all Your existing infra, zero lock-in
| Store | Ops/sec | Latency | When to use |
|---|---|---|---|
| Memory | 5,574,103 | 179ns | Single server, maximum speed |
| bun:sqlite | 372,247 | 2.7ΞΌs | Single server, need persistence |
| MongoDB | 2,132 | 469ΞΌs | Multi-server / NoSQL infrastructure |
Redis, Valkey, DragonflyDB, Postgres, and MySQL are network-bound (~200β3,500 ops/sec). Benchmarks at hitlimit.jointops.dev/docs/benchmarks.
import { hitlimit } from '@joint-ops/hitlimit-bun'
import { ______Store } from '@joint-ops/hitlimit-bun/stores/______'
Bun.serve({ fetch: hitlimit({ store: ______Store({ /* config */ }) }, handler) })
Bun.serve({ fetch: hitlimit({}, handler) }) // that's it
import { sqliteStore } from '@joint-ops/hitlimit-bun'
Bun.serve({ fetch: hitlimit({ store: sqliteStore({ path: './ratelimit.db' }) }, handler) })
No peer dependency β bun:sqlite is built into Bun.
import { redisStore } from '@joint-ops/hitlimit-bun/stores/redis'
Bun.serve({ fetch: hitlimit({ store: redisStore({ url: 'redis://localhost:6379' }) }, handler) })
Peer dep: ioredis
import { valkeyStore } from '@joint-ops/hitlimit-bun/stores/valkey'
Bun.serve({ fetch: hitlimit({ store: valkeyStore({ url: 'redis://localhost:6379' }) }, handler) })
Peer dep: ioredis
import { dragonflyStore } from '@joint-ops/hitlimit-bun/stores/dragonfly'
Bun.serve({ fetch: hitlimit({ store: dragonflyStore({ url: 'redis://localhost:6379' }) }, handler) })
Peer dep: ioredis
import { postgresStore } from '@joint-ops/hitlimit-bun/stores/postgres'
Bun.serve({ fetch: hitlimit({ store: postgresStore({ url: 'postgres://localhost:5432/mydb' }) }, handler) })
Peer dep: pg
import { mongoStore } from '@joint-ops/hitlimit-bun/stores/mongodb'
import { MongoClient } from 'mongodb'
const client = new MongoClient('mongodb://localhost:27017')
const db = client.db('myapp')
Bun.serve({ fetch: hitlimit({ store: mongoStore({ db }) }, handler) })
Peer dep: mongodb
import { mysqlStore } from '@joint-ops/hitlimit-bun/stores/mysql'
import mysql from 'mysql2/promise'
const pool = mysql.createPool('mysql://root@localhost:3306/mydb')
Bun.serve({ fetch: hitlimit({ store: mysqlStore({ pool }) }, handler) })
Peer dep: mysql2
| Runtime | Ops/sec | |
|---|---|---|
| Bun | 5,574,103 | ββββββββββββββββββββ |
| Node.js | 4,082,874 | βββββββββββββββ |
Bun leads at 10K IPs (5.57M vs 4.08M) and single-IP (7.73M vs 5.96M). Same library, same algorithm, memory store. For Redis, Postgres, and cross-store breakdowns, see the full benchmark results. Controlled-environment microbenchmarks with transparent methodology. Run them yourself.
Node.js: JS β N-API β C++ binding β SQLite
Bun: JS β Native call β SQLite (no overhead)
No N-API. No C++ bindings. No FFI. Bun calls SQLite directly.
MIT
FAQs
Ultra-fast Bun-native rate limiting - Memory-first with 6M+ ops/sec for Bun.serve, Elysia & Hono
We found that @joint-ops/hitlimit-bun demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago.Β It has 3 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
A critical vm2 sandbox escape can allow untrusted JavaScript to break isolation and execute commands on the host Node.js process.

Research
Five malicious NuGet packages impersonate Chinese .NET libraries to deploy a stealer targeting browser credentials, crypto wallets, SSH keys, and local files.

Security News
pnpm 11 turns on a 1-day Minimum Release Age and blocks exotic subdeps by default, adding safeguards against fast-moving supply chain attacks.