Six frameworks. Four storage backends. One import. Zero dependencies.
Source: Dev.to

Same API everywhere
// Express
import { hitlimit } from '@joint-ops/hitlimit';
app.use(hitlimit({ limit: 100, window: '1m' }));
// Fastify
import { hitlimit } from '@joint-ops/hitlimit/fastify';
await app.register(hitlimit, { limit: 100, window: '1m' });
// Hono
import { hitlimit } from '@joint-ops/hitlimit/hono';
app.use(hitlimit({ limit: 100, window: '1m' }));
// NestJS
import { HitLimitModule, HitLimitGuard } from '@joint-ops/hitlimit/nest';
@Module({
imports: [HitLimitModule.register({ limit: 100, window: '1m' })],
providers: [{ provide: APP_GUARD, useClass: HitLimitGuard }],
})
export class AppModule {}
// Bun.serve
import { hitlimit } from '@joint-ops/hitlimit-bun';
Bun.serve({ fetch: hitlimit({ limit: 100, window: '1m' }, handler) });
// Elysia
import { hitlimit } from '@joint-ops/hitlimit-bun/elysia';
new Elysia().use(hitlimit({ limit: 100, window: '1m' })).listen(3000);
Switch frameworks tomorrow. Your rate‑limiting code stays the same.
4 Storage Backends Built In
// Memory (default) – fastest, no setup
app.use(hitlimit({ limit: 100, window: '1m' }));
// SQLite – survives restarts
app.use(hitlimit({ store: sqliteStore({ path: './limits.db' }), limit: 100, window: '1m' }));
// Redis – distributed across instances
app.use(hitlimit({ store: redisStore({ url: process.env.REDIS_URL }), limit: 100, window: '1m' }));
// Postgres – use your existing database
app.use(hitlimit({ store: postgresStore({ pool }), limit: 100, window: '1m' }));
Start with memory on day one. Move to Postgres or Redis when you scale. Nothing else changes.
New in v1.2.0: PostgreSQL Store
import { postgresStore } from '@joint-ops/hitlimit/stores/postgres';
import { Pool } from 'pg';
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
app.use(
hitlimit({
limit: 100,
window: '1m',
store: postgresStore({ pool }),
})
);
One atomic query per request. Zero race conditions. Tables are created automatically on first run. Named prepared statements give 30‑40 % lower latency. No new infrastructure to manage.
Fast
Node.js (10K unique IPs)
Memory 3.16M ops/s 316ns
SQLite 352K ops/s 2.8µs
Redis 6.7K ops/s 149µs
Postgres 3.0K ops/s 336µs
Bun (10K unique IPs)
Memory 8.32M ops/s 120ns
bun:sqlite 325K ops/s 3.1µs
Redis 6.7K ops/s 148µs
Postgres 3.7K ops/s 273µs
Peak: 12.38 M ops/s on Bun. 4.83 M ops/s on Node.js.
All benchmarks are open source: .
More Than a Counter
- Tiered limits for free, pro and enterprise plans.
- Auto‑ban repeat offenders after N violations.
- Group limits for per‑team or per‑org quotas.
- Skip rules for health checks, admins, internal routes.
- Human‑readable windows like
'15m','1h','1d'instead of milliseconds.
All built in. All zero dependencies.
Get Started
npm install @joint-ops/hitlimit # Node.js
bun add @joint-ops/hitlimit-bun # Bun
Docs | npm | Release notes
If it saves you time, give it a star.