πŸš€ Big News:Socket Has Acquired Secure Annex.Learn More β†’
Socket
Book a DemoSign in
Socket

@joint-ops/hitlimit

Package Overview
Dependencies
Maintainers
3
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@joint-ops/hitlimit

Fast rate limiting middleware for Express, Fastify, NestJS & Node.js - API throttling, brute force protection, request limiting

latest
Source
npmnpm
Version
1.4.0
Version published
Maintainers
3
Created
Source

@joint-ops/hitlimit

Rate limiting that doesn't slow you down.

4.08M ops/sec at 10K unique IPs. Zero dependencies. One line to protect any Node.js API.

npm install @joint-ops/hitlimit
app.use(hitlimit())  // That's it. 100 req/min per IP.

Works with Express, Fastify, Hono, NestJS, and native HTTP β€” no config, no adapters to install, no boilerplate.

Docs Β· GitHub Β· Benchmarks

30 Seconds to Production

Express

import express from 'express'
import { hitlimit } from '@joint-ops/hitlimit'

const app = express()
app.use(hitlimit({ limit: 100, window: '15m' }))

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 {}

Native HTTP

import { createHitLimit } from '@joint-ops/hitlimit/node'

const limiter = createHitLimit({ limit: 100, window: '1m' })
const server = http.createServer(async (req, res) => {
  const result = await limiter.check(req)
  if (!result.allowed) return res.writeHead(429).end()
  res.end('OK')
})

What You Get

Tiered limits β€” Free, Pro, Enterprise in 4 lines:

hitlimit({
  tiers: { free: { limit: 100, window: '1h' }, pro: { limit: 5000, window: '1h' } },
  tier: (req) => req.user?.plan || 'free'
})

Auto-ban β€” Ban repeat offenders automatically:

hitlimit({ limit: 100, window: '1m', ban: { threshold: 5, duration: '15m' } })

Custom keys β€” Rate limit by IP, user, API key, or anything:

hitlimit({ key: (req) => req.headers['x-api-key'] || req.ip })

Shared limits β€” Team-wide quotas with group:

hitlimit({ limit: 10000, window: '1h', group: (req) => req.user.teamId })

Skip rules β€” Whitelist health checks, admins, internal routes:

hitlimit({ skip: (req) => req.path === '/health' || req.user?.role === 'admin' })

Pick Your Store

Every store is built in. Swap one line β€” your rate limiting code stays the same.

               Single Server                          Multi-Server
          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
          β”‚  Memory  β”‚  SQLite   β”‚          β”‚  Redis   β”‚  Postgres    β”‚
          β”‚  (default)           β”‚          β”‚  Valkey  β”‚  MongoDB     β”‚
          β”‚                      β”‚          β”‚  Dragonfly  MySQL       β”‚
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             No persistence         Your existing infrastructure, zero lock-in
StoreOps/secLatencyWhen to use
Memory4,082,874245nsSingle server, no persistence needed
SQLite404,1352.5ΞΌsSingle server, need persistence
MongoDB2,161462.8ΞΌsMulti-server / NoSQL infrastructure

Redis, Valkey, DragonflyDB, Postgres, and MySQL are network-bound (~200–3,500 ops/sec). Benchmarks at hitlimit.jointops.dev/docs/benchmarks.

The pattern is always the same

import { hitlimit } from '@joint-ops/hitlimit'
import { ______Store } from '@joint-ops/hitlimit/stores/______'

app.use(hitlimit({ store: ______Store({ /* connection config */ }) }))
Memory β€” default, zero config
app.use(hitlimit()) // that's it
SQLite β€” survives restarts, single server
import { sqliteStore } from '@joint-ops/hitlimit/stores/sqlite'
app.use(hitlimit({ store: sqliteStore({ path: './ratelimit.db' }) }))

Peer dep: better-sqlite3

Redis β€” distributed, atomic Lua scripts
import { redisStore } from '@joint-ops/hitlimit/stores/redis'
app.use(hitlimit({ store: redisStore({ url: 'redis://localhost:6379' }) }))

Peer dep: ioredis

Valkey β€” open-source Redis fork, drop-in replacement
import { valkeyStore } from '@joint-ops/hitlimit/stores/valkey'
app.use(hitlimit({ store: valkeyStore({ url: 'redis://localhost:6379' }) }))

Peer dep: ioredis

DragonflyDB β€” Redis-compatible, higher throughput
import { dragonflyStore } from '@joint-ops/hitlimit/stores/dragonfly'
app.use(hitlimit({ store: dragonflyStore({ url: 'redis://localhost:6379' }) }))

Peer dep: ioredis

PostgreSQL β€” use your existing database
import { postgresStore } from '@joint-ops/hitlimit/stores/postgres'
app.use(hitlimit({ store: postgresStore({ url: 'postgres://localhost:5432/mydb' }) }))

Peer dep: pg

MongoDB β€” NoSQL, TTL indexes, MEAN/MERN stacks
import { mongoStore } from '@joint-ops/hitlimit/stores/mongodb'
import { MongoClient } from 'mongodb'

const client = new MongoClient('mongodb://localhost:27017')
const db = client.db('myapp')
app.use(hitlimit({ store: mongoStore({ db }) }))

Peer dep: mongodb

MySQL β€” SQL distributed, LAMP stacks
import { mysqlStore } from '@joint-ops/hitlimit/stores/mysql'
import mysql from 'mysql2/promise'

const pool = mysql.createPool('mysql://root@localhost:3306/mydb')
app.use(hitlimit({ store: mysqlStore({ pool }) }))

Peer dep: mysql2

Performance

vs Competitors (Memory Store, 10K unique IPs)

LibraryOps/sec
hitlimit4,082,874β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ
rate-limiter-flexible1,261,659β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ
express-rate-limit824,030β–ˆβ–ˆβ–ˆβ–ˆ

This is the memory store comparison β€” the default for all three libraries. For Redis, Postgres, and cross-store breakdowns, see the full benchmark results. Controlled-environment microbenchmarks with transparent methodology. We report scenarios where competitors beat us. Run them yourself.

Migrating?

// express-rate-limit β†’ hitlimit
- import rateLimit from 'express-rate-limit'
- app.use(rateLimit({ windowMs: 60000, max: 100 }))
+ import { hitlimit } from '@joint-ops/hitlimit'
+ app.use(hitlimit({ window: '1m', limit: 100 }))

Full migration guide in the docs.

  • @joint-ops/hitlimit-bun β€” Bun-native variant with native bun:sqlite

License

MIT

Keywords

rate-limit

FAQs

Package last updated on 09 Mar 2026

Did you know?

Socket

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.

Install

Related posts