← Back

MangoDB: When Files Are Good Enough

SQLite for Mongo. Same API, zero setup.

I was coding on my phone (slightly ridiculous, I know, but I like it) and wanted to prototype something with MongoDB. Setting up Mongo on a phone? Not happening. Setting up Mongo anywhere means context-switching when you just want to build something.

Mongo is brilliant, but sometimes I just want to point at a file and start coding. Like SQLite does for SQL.

So I built MangoDB 🥭. Mongo’s API, backed by your filesystem instead of a server. Code anywhere, deploy to real Mongo when you’re ready.

How It Works

Mongo’s API, filesystem backend.

import { MangoDBClient } from 'mangodb';

const client = new MangoDBClient('./data');
await client.connect();

const db = client.db('myapp');
const users = db.collection('users');

await users.insertOne({ name: 'Alice', email: 'alice@example.com' });
const user = await users.findOne({ name: 'Alice' });

No server. No Docker. No connection strings.

When you’re ready for production, one line changes:

const client = process.env.MONGODB_URI
  ? new MongoClient(process.env.MONGODB_URI)
  : new MangoDBClient('./data');

Your code stays identical.

Check out the code on GitHub

When to Use It (and When Not To)

Good for:

  • Prototyping without infrastructure
  • Testing (no database setup in CI, tests run in parallel, cleanup is deleting a directory)
  • Weird environments (phone development, restricted networks, air-gapped machines)
  • Onboarding (new developers clone and run tests immediately)

Not for:

  • Production (use real Mongo)
  • Performance testing (file I/O has different characteristics)
  • Learning Mongo internals (this mimics the API, not the implementation)

Check the GitHub repo for current status.

Building It

I built Mango test-driven. Every test runs against both real Mongo and Mango:

describe('insertOne', () => {
  it('should insert a document', async () => {
    const result = await collection.insertOne({ name: 'Alice' });
    expect(result.insertedId).to.exist;

    const found = await collection.findOne({ name: 'Alice' });
    expect(found.name).to.equal('Alice');
  });
});

Run with MONGODB_URI set and you test against real Mongo. Run without and you test against Mango. If behavior differs, I document it in COMPATIBILITY.md.

This caught a lot of assumptions. Mongo has subtle behaviors everywhere: ObjectIds encode timestamp and process info in specific formats, query operators like $in and $nin with empty arrays behave asymmetrically, error message formats matter because some libraries parse them. Every time I thought “surely that’s close enough,” some library would break.

The tests are the compatibility contract. Want to know if Mango works for your use case? Check if there are tests for it.

Try It

npm install mangodb

Point it at a directory, write your code, swap to real MongoDB when you need it.

It’s early, so expect rough edges. But it might save you some setup time.

PRs welcome. The test suite runs against real Mongo, so compatibility issues are usually obvious.


MangoDB is open source on GitHub. Use it for prototyping and testing. Use real MongoDB for production.