GitHub - dashersw/memgoose: A lightweight, type-safe, in-memory database with MongoDB-like API and pluggable persistence. Built for testing, caching, and rapid development with familiar Mongoose-style schemas.

5 min read Original article โ†—

memgoose

A lightweight, type-safe, in-memory database with MongoDB-like API and pluggable persistence. Built for testing, caching, and rapid development with familiar Mongoose-style schemas.

npm version npm downloads TypeScript License: MIT Tests

At a Glance

// Define schema with validation, indexes, and hooks
const userSchema = new Schema({
  email: { type: String, unique: true },
  age: { type: Number, min: 0 }
}, { timestamps: true })

userSchema.index('email') // O(1) lookups

// Choose your storage
connect({ storage: 'memory' })           // Testing: 0 setup, fastest
connect({ storage: 'sqlite', ... })      // Production: ACID, persistent
connect({ storage: 'wiredtiger', ... })  // Enterprise: MongoDB-grade performance
Metric Value
Query Speed 431-1147x faster with indexes
Storage Options Memory, SQLite, WiredTiger, File
Test Coverage 800+ passing tests
Dependencies Zero (core library)
TypeScript Full support with IntelliSense
API Compatibility Mongoose-like (easy migration)

Quick Start

import { Schema, model } from 'memgoose'

// Define schema with indexes, virtuals, and hooks
const userSchema = new Schema({ firstName: String, lastName: String, email: String, age: Number })

userSchema.index('email')
userSchema.virtual('fullName').get(doc => `${doc.firstName} ${doc.lastName}`)
userSchema.pre('save', ({ doc }) => {
  doc.email = doc.email.toLowerCase() // Normalize email
})

// Create model
const User = model('User', userSchema)

// Insert and query
await User.create({ firstName: 'Alice', lastName: 'Smith', email: 'ALICE@EXAMPLE.COM', age: 25 })
const user = await User.findOne({ email: 'alice@example.com' }) // O(1) with index!
console.log(user.fullName) // "Alice Smith" (virtual property)

// Update, delete, count
await User.updateOne({ firstName: 'Alice' }, { $inc: { age: 1 } })
await User.deleteMany({ age: { $lt: 18 } })
const count = await User.countDocuments({ age: { $gte: 18 } })

Why memgoose?

  • ๐Ÿš€ Blazing Fast: O(1) lookups with indexing (83-1147x faster than linear scans)
  • ๐ŸŽฏ Type-Safe: Full TypeScript support with IntelliSense
  • ๐Ÿ—๏ธ Mongoose-Compatible: Drop-in replacement for mongoose in many cases
  • ๐Ÿ’พ Pluggable Storage: Memory, SQLite, WiredTiger, or file-based (NDJSON + WAL) persistence
  • ๐Ÿ“ฆ Zero Dependencies: No runtime dependencies (optional peer dependencies for storage backends)
  • ๐Ÿงช Well Tested: 800+ passing tests with comprehensive coverage

Use Cases

  • ๐Ÿงช Testing: Mock MongoDB in unit/integration tests without spinning up a database
  • ๐Ÿš€ Prototyping: Quickly build features before implementing real database
  • ๐Ÿ’พ Caching: In-memory cache with familiar mongoose-like API
  • ๐Ÿ“Š Development: Fast local development without database setup
  • ๐ŸŽฏ Learning: Learn MongoDB query patterns without installing MongoDB
  • ๐Ÿ—„๏ธ Persistence: Use SQLite or WiredTiger for lightweight persistent applications

Features

  • ๐Ÿ” Rich Queries: MongoDB-like operators ($eq, $ne, $in, $nin, $gt, $gte, $lt, $lte, $regex, $exists, $size, $elemMatch, $all)
  • ๐Ÿงฎ Logical Operators: $or, $and, $nor, $not for complex query logic
  • โœ๏ธ Update Operators: $set, $unset, $inc, $dec, $push, $pull, $addToSet, $pop, $rename
  • ๐Ÿ“ˆ Smart Indexing: Single-field, compound, unique, and TTL indexes with partial matching
  • ๐Ÿ“Š Aggregation Pipeline: Full pipeline with $match, $group, $project, $lookup, $unwind, and more
  • ๐Ÿ”— Advanced Populate: Nested populate with select, match filtering, and field projection
  • โฑ๏ธ TTL Indexes: Automatic document expiration for sessions, caches, and temporary data
  • ๐ŸŽฃ Hooks: Pre/post hooks for save, update, delete, and find operations
  • ๐Ÿ”ฎ Virtuals: Computed properties with getter functions
  • โšก Atomic Operations: findOneAndUpdate(), findOneAndDelete()
  • ๐Ÿš„ Lean Queries: 17.5x faster by skipping virtual computation

Installation

For persistent storage (optional):

# SQLite storage
npm install better-sqlite3

# WiredTiger storage (requires build tools)
npm install memgoose-wiredtiger

Examples

# Basic usage
npm run example

# Performance benchmark
npm run example:perf

# Memory usage demo
npm run example:memory

# Complete features showcase
npm run example:showcase

See the examples/ folder for complete, runnable code samples demonstrating all features.

Documentation

๐Ÿ“š Complete Documentation

Storage Options

import { connect } from 'memgoose'

// Memory (default, fastest)
connect({ storage: 'memory' })

// SQLite (persistent, ACID)
connect({ storage: 'sqlite', sqlite: { dataPath: './data' } })

// WiredTiger (enterprise-grade)
connect({ storage: 'wiredtiger', wiredtiger: { dataPath: './data' } })

// File (NDJSON + WAL)
connect({ storage: 'file', file: { dataPath: './data' } })

Performance

memgoose delivers exceptional performance through intelligent indexing and optimized query execution.

Benchmark Results

Dataset: 100,000 documents
Hardware: Apple M4 Max (16 cores, 128GB RAM)
Node.js: v24.8.0

Operation Without Index With Index Speedup
Equality query (findOne) 2.01ms <0.01ms 431x โšก
Compound query (city + age) 2.01ms <0.01ms 1147x ๐Ÿš€
Count documents 24.42ms 11.60ms 2x
Update one document 2.09ms 0.02ms 83x
Lean queries (no virtuals) 12.00ms 0.70ms 17.5x

Key Takeaways

  • Index your queries: Add .index('fieldName') to your schema for O(1) lookups
  • Use lean queries: Skip virtual computation for read-heavy operations (17.5x faster)
  • Choose the right storage: Memory for testing, SQLite/WiredTiger for production

See Performance Guide for optimization strategies and detailed benchmarks.

Migration from Mongoose

memgoose is designed to be Mongoose-compatible:

// Mongoose
import mongoose from 'mongoose'
const User = mongoose.model('User', userSchema)

// memgoose (mostly the same!)
import { model } from 'memgoose'
const User = model('User', userSchema)

Contributing

Contributions welcome! Please feel free to submit a Pull Request.

License

MIT


Need help? Check out the examples or open an issue.