A small, dependency-light JSON object store for Node.js. No server, no schema migrations to run, no daemon — point it at a file (or a folder) and write transactions.
npm install sencillodbimport { SencilloDB } from "sencillodb";
const db = new SencilloDB({ file: "./app.json" });
const user = await db.transaction(async (tx) => {
await tx.ensureIndex({ collection: "users", field: "email", unique: true });
return tx.create({
collection: "users",
data: { name: "Alice", email: "alice@example.com", age: 30 },
});
});
const adults = await db.transaction((tx) =>
tx.findMany({ collection: "users", filter: { age: { $gte: 18 } }, limit: 20 })
);TypeScript types ship with the package; the API is ESM only and needs Node 18+.
SencilloDB sits between "a JSON file I read and write myself" and a real database. You get transactions, indexes, queries and relations over plain JSON files that stay readable in an editor — good for CLIs, prototypes, desktop apps, small services, tests and anything where running Postgres is more machinery than the job deserves.
It is best when you want local durability, simple deployment and a document-shaped API inside one Node process. It is not trying to replace Postgres, SQLite or MongoDB for high-write multi-user systems, analytics, replication, access control or complex joins. See Use Cases and Limits for the decision guide.
| Transactions | Serialized, all-or-nothing. A throw inside the callback discards every change. |
| Storage modes | One file, one file per collection (lazily loaded), or one file per index bucket (sharded). |
| Queries | $eq $ne $gt $gte $lt $lte $in $nin $regex $exists $and $or $nor $not, plus dot paths, sorting, limit/skip and count. |
| Indexes | Secondary indexes with optional unique constraints; equality, $in and range lookups use them. |
| Writes | create, update (full replace or $set/$inc/$unset), upsert, updateMany, destroy, destroyMany. |
| Relations | populate resolves foreign keys against another collection. |
| Durability | Atomic temp-file-and-rename writes, an optional append only log with an appendfsync policy, and an advisory cross process lock. |
| Operations | export/import/snapshot, versioned migrate, TTL expiry, change events, gzip compression, an LRU cache with a memory ceiling. |
- CLI tools that need durable local state without a setup step.
- Electron, Tauri and other desktop apps where the database lives next to the app.
- Prototypes, demos and small internal tools that may outgrow plain JSON but do not need a server database yet.
- Test fixtures and integration tests that should exercise persistence without booting infrastructure.
- Small bots, automation scripts and build tools with one writer process and predictable data sizes.
Every option is optional.
new SencilloDB({
file: "./app.json", // single file mode (the default)
folder: "./data", // one file per collection, loaded on demand
sharding: true, // folder mode only: one file per index bucket
compression: true, // gzip the persisted files
aof: true, // append only log instead of rewriting the store
appendfsync: "everysec", // "always" | "everysec" | "no"
maxCacheSize: 50, // collections/shards kept in memory (0 = no limit)
clone: true, // return copies instead of live references
lock: true, // advisory lock file for multi process access
loadHook: async () => "{}", // single file mode: load from elsewhere
saveHook: async (json) => { /*…*/ }, // single file mode: save elsewhere
debug: false, // also print internal warnings
});- Getting Started
- Use Cases and Limits — when SencilloDB is the right tool, and when it is not
- Core Concepts — collections, index buckets, transactions
- API Reference
- Querying — operators, sorting, pagination, populate
- Indexes, Unique Constraints and TTL
- Persistence Modes — single file, folder, sharding, compression
- Append Only Log
- LRU Cache
- Sharding
- Compression
- Schemas and Resource Managers
- Events and Hooks
- Backups and Migrations
- Concurrency and Crash Safety
- Stream Processing
- Advanced Usage
- Architecture — how the source is laid out
- Changelog
npm install
npm run build # compile src/ to dist/
npm test # jest
npm run bench # compare persistence modesExamples live in examples/ and import the compiled output, so run npm run build before them.
ISC © Alex Merced