On this page

MongoDB Store

The MongoDB store enables distributed rate limiting using your existing MongoDB database. Ideal for teams running MEAN/MERN stacks or MongoDB Atlas who want to add rate limiting without introducing Redis or Postgres.

Installation

The MongoDB store requires mongodb as a peer dependency:

npm install mongodb
# or: pnpm add mongodb
# or: yarn add mongodb
bun add mongodb

Usage

import { hitlimit } from '@joint-ops/hitlimit'
import { mongoStore } from '@joint-ops/hitlimit/stores/mongodb'
import { MongoClient } from 'mongodb'

const client = new MongoClient('mongodb://localhost:27017')
await client.connect()
const db = client.db('myapp')

app.use(hitlimit({
  limit: 100,
  window: '1m',
  store: mongoStore({ db })
}))
import { hitlimit } from '@joint-ops/hitlimit-bun'
import { mongoStore } from '@joint-ops/hitlimit-bun/stores/mongodb'
import { MongoClient } from 'mongodb'

const client = new MongoClient('mongodb://localhost:27017')
await client.connect()
const db = client.db('myapp')

const limiter = hitlimit({
  limit: 100,
  window: '1m',
  store: mongoStore({ db })
})

Options

OptionTypeDefaultDescription
dbDb-A MongoDB Db instance from MongoClient.db() (required)
collectionPrefixstring'hitlimit'Prefix for rate limit collection names
skipIndexCreationbooleanfalseSkip automatic TTL and unique index creation on startup

TTL Indexes

The MongoDB store automatically creates TTL indexes on all collections. MongoDB's background thread deletes expired documents automatically — no cleanup timers needed.

Each collection has an expireAt field with a TTL index (expireAfterSeconds: 0). When the expireAt timestamp passes, MongoDB removes the document within ~60 seconds.

// TTL indexes created automatically:
{ expireAt: 1 }, { expireAfterSeconds: 0 }
// Unique key indexes for upsert operations:
{ key: 1 }, { unique: true }

Schema

The store creates three collections (prefix defaults to hitlimit):

// hitlimit_hits
{ key: "string", count: number, resetAt: number, expireAt: Date }

// hitlimit_bans
{ key: "string", expiresAt: number, expireAt: Date }

// hitlimit_violations
{ key: "string", count: number, resetAt: number, expireAt: Date }

MongoDB Atlas

Connect to MongoDB Atlas using a connection string:

const client = new MongoClient(
  'mongodb+srv://user:password@cluster0.xxxxx.mongodb.net/?retryWrites=true&w=majority'
)
await client.connect()
const db = client.db('myapp')

mongoStore({ db })

Bun Compatibility

The mongodb 6.x driver is pure JavaScript and works with Bun, but there are known issues to be aware of:

  • TLS connections may fail — MongoDB Atlas and other TLS-enabled connections can fail under Bun due to TLS handling differences (Bun issues #17913, #24374). Use localhost or non-TLS connections for Bun.
  • Memory leaks — Some users report ~8-12MB/hr memory growth with the MongoDB driver on Bun (issue #24118).

Recommendation: For production MongoDB with TLS, use Node.js. For localhost/non-TLS development or testing, Bun works reliably. Node.js has no such limitations.

Characteristics

  • Persistence: Full MongoDB durability (journaling, replica sets)
  • Scalability: Shared across all server instances
  • Atomic: findOneAndUpdate with aggregation pipeline ensures race-condition-free increments
  • Cleanup: Automatic via MongoDB TTL indexes (no timers needed)
  • Dependencies: Requires mongodb driver (>=6.0.0)

When to Use

  • Teams already running MongoDB in production
  • MEAN/MERN stack applications
  • MongoDB Atlas or DocumentDB users
  • When you want distributed rate limiting without adding Redis or Postgres
  • NoSQL-first architectures