MDX.org.ai
Structured Datamdxdb

Storage Adapters

Choose the right storage backend for your needs

Storage Adapters

mdxdb supports multiple storage backends through adapter packages. All of them run on Cloudflare (Durable Objects, Vectorize, R2-backed parquet) or are runtime-agnostic HTTP clients; the former @mdxdb/postgres, @mdxdb/mongo and @mdxdb/git adapters were removed and are deprecated on npm.

Available Adapters

PackageBackendDescription
@mdxdb/fsFile SystemStore documents as files
@mdxdb/sqliteDurable Object SQLiteGraph database inside a Durable Object
@mdxdb/doDurable ObjectsParent/child hierarchy, hibernatable WebSockets, parquet export
@mdxdb/vectorizeCloudflare VectorizeVector search
@mdxdb/clickhouseClickHouseAnalytics database
@mdxdb/apiHTTPRemote mdxdb server

Choosing an Adapter

@mdxdb/fs - File System

Best for:

  • Local development
  • Static site generation
  • Git-based content workflows
  • Simple deployments

Pros:

  • No database setup required
  • Files can be edited directly
  • Works with Git version control
  • Easy to backup and migrate

Cons:

  • No full-text search (requires external indexing)
  • Limited query capabilities
  • Not suitable for high-traffic applications

@mdxdb/sqlite - SQLite

Best for:

  • Embedded applications
  • Edge computing (Cloudflare Workers, etc.)
  • Serverless functions
  • Single-server deployments

Pros:

  • Zero configuration
  • Full SQL query support
  • Full-text search built-in
  • Single file storage

Cons:

  • Single-writer limitation
  • Not suitable for distributed systems

@mdxdb/do - Durable Objects

Best for:

  • Production applications on Cloudflare
  • Per-tenant or per-document isolation
  • Real-time collaboration (hibernatable WebSockets)

Pros:

  • Strongly consistent, single-writer per object
  • Parent/child hierarchy across objects
  • Parquet export to R2 for analytics

Cons:

  • Cloudflare-only

@mdxdb/clickhouse - ClickHouse

Best for:

  • Analytics workloads
  • Time-series data
  • Large datasets
  • Aggregation queries

Pros:

  • Extremely fast analytics
  • Excellent compression
  • Column-oriented storage

Cons:

  • Not designed for frequent updates
  • Complex setup

Adapter Interface

All adapters implement the same interface:

interface Database {
  get(path: string, options?: GetOptions): Promise<MDXLDDocument | null>
  set(path: string, doc: MDXLDDocument, options?: SetOptions): Promise<SetResult>
  delete(path: string, options?: DeleteOptions): Promise<DeleteResult>
  list(prefix?: string, options?: ListOptions): Promise<ListResult>
  search(query: string, options?: SearchOptions): Promise<SearchResult>
}

Switching Adapters

The unified interface makes it easy to switch adapters:

// Development: file system
import { createDatabase as createFsDb } from '@mdxdb/fs'
 
// Production: ClickHouse
import { createClickHouseDatabase } from '@mdxdb/clickhouse'
 
const db = process.env.NODE_ENV === 'production'
  ? await createClickHouseDatabase({ url: process.env.CLICKHOUSE_URL })
  : createFsDb({ path: './content' })
 
// Same API regardless of backend
const doc = await db.get('articles/hello-world')

Custom Adapters

Create your own adapter by implementing the Database interface (exported by every adapter):

import type { Database, MDXLDDocument, SetResult, DeleteResult, ListResult, SearchResult } from '@mdxdb/fs'
 
class MyCustomAdapter implements Database {
  async get(path: string): Promise<MDXLDDocument | null> {
    // Your implementation
  }
 
  async set(path: string, doc: MDXLDDocument): Promise<SetResult> {
    // Your implementation
  }
 
  async delete(path: string): Promise<DeleteResult> {
    // Your implementation
  }
 
  async list(prefix?: string): Promise<ListResult> {
    // Your implementation
  }
 
  async search(query: string): Promise<SearchResult> {
    // Your implementation
  }
}

On this page