DEV Community

KAMATIL
KAMATIL

Posted on

Meet Inibase: a file-based TypeScript database with column storage

An article listing usually needs a title and a slug. The full article body can wait until someone opens the page.

That distinction is a useful way to introduce Inibase: a file-based database written in TypeScript that stores columns in separate files and lets you select the fields you want to read.

I'm the creator of Inibase. In this article, I'll walk through a small example and explain some of the design's tradeoffs.

A database inside your application

Inibase runs in your Node.js application and persists data on the filesystem. You don't start a separate database server to use it.

It supports schemas, relations, column selection, caching, optional gzip compression, and an explicit transaction API. Its API uses JavaScript objects rather than SQL strings.

File-based storage still needs a suitable home: your deployment must provide writable, persistent storage. A temporary filesystem in a short-lived function is not a durable database location.

Create a small article database

For this example, use Node.js 22 or later on macOS or Linux. Windows users should check the repository's Unix utility requirements; WSL is one option.

In a fresh directory, install the version used for this example:

npm init -y
npm install inibase@3.8.0
Enter fullscreen mode Exit fullscreen mode

Create demo.mjs:

import Inibase from "inibase";

const db = new Inibase("article-demo");

await db.createTable("articles", [
  { key: "title", type: "string", required: true },
  { key: "slug", type: "string", required: true },
  { key: "body", type: "string" },
]);

await db.post("articles", {
  title: "Getting started with Inibase",
  slug: "getting-started-with-inibase",
  body: "This is the full article content.",
});

const articles = await db.get("articles", undefined, {
  columns: ["title", "slug"],
});

console.log(articles);
Enter fullscreen mode Exit fullscreen mode

Run it once:

node demo.mjs
Enter fullscreen mode Exit fullscreen mode

This example creates a table, inserts an article, and requests its title and slug without requesting the body. It is an initial setup script, not an idempotent migration: use a fresh database directory when repeating the complete example.

Why store columns separately?

Inibase organizes storage into databases, tables, and column files.

For a listing page, selecting two columns can avoid reading the article body column. That is especially interesting when bodies are much larger than titles and slugs.

The practical benefit depends on the workload: row count, field sizes, compression, filesystem behavior, and caching all matter. Column selection alone does not establish that one database is faster than another.

Updates also involve a tradeoff. On a plain table, an update rewrites the affected column files. Inibase offers an opt-in update log that appends update frames instead, with later compaction and additional restrictions. Start with the basic storage path, then evaluate logging against your actual write pattern.

What happens if a write fails?

Writing a row across multiple column files raises an obvious question: what if the process stops halfway through?

Inibase documents a journal and recovery protocol for crash-atomic single-table data mutations. Its default full durability mode uses fsync; the guarantees depend on the operating system and filesystem honoring those operations.

It also provides begin, commit, and rollback for explicit multi-table transactions. The current transaction model has important limits, including one mutation per table per transaction and no read-your-writes behavior. Cross-table operations outside a transaction do not acquire its atomicity guarantees automatically.

The durability documentation explains the scope and limitations in detail.

Where I would evaluate it

Inibase is worth exploring if you want a TypeScript API, file-based persistence, and control over which columns an application reads. A small content application is one concrete workload to try.

For applications built around frequent indexed lookups, heavy concurrent writes, or richer transaction semantics, compare alternatives using representative data. SQLite and other established databases are valuable baselines.

Inibase is MIT-licensed. You can find installation instructions, examples, and benchmark methodology in the GitHub repository.

Try the example with your own content structure. What read or write pattern would you want to see tested next?

Top comments (0)