Adapters Overview
Storage backends
Adapters handle persistence. ctrodb ships with two.
Built-in adapters
| Adapter | Environment | Persistence |
|---|---|---|
MemoryAdapter | Node, browser | Not persisted |
IndexedDBAdapter | Browser only | Persists in IndexedDB |
Auto-detection
const db = new Database()
// In browser with indexedDB → IndexedDBAdapter
// In Node or Deno → MemoryAdapter
You can also pick explicitly:
import { Database, createAdapter } from "ctrodb"
const db = new Database({
adapter: "memory",
})
// Or pass an adapter instance:
const db2 = new Database({
adapter: new MemoryAdapter(),
})
Custom adapters
Any object implementing the StorageAdapter interface works:
import type { StorageAdapter } from "ctrodb"
class MyAdapter implements StorageAdapter {
readonly name = "my-adapter"
async connect(name: string, schema: SchemaConfig | null): Promise<void> { ... }
async disconnect(): Promise<void> { ... }
isConnected(): boolean { ... }
// ... implement all required methods
}
Full StorageAdapter interface in API reference.
Transaction API
All adapters implement transaction<T>(fn). If the callback throws, all changes
are rolled back. See the Transactions guide
for details.
IndexedDBAdapter: ctx.collection(name) returns bound methods — call methods
without passing the collection name.
MemoryAdapter: ctx.collection(name) returns the raw adapter — pass the
collection name to each method.
// IndexedDB
await db.transaction(async (ctx) => {
const todos = ctx.collection("todos")
await todos.create({ title: "A" })
})
// Memory adapter
await db.transaction(async (ctx) => {
const adapter = ctx.collection("todos")
await adapter.create("todos", { title: "A" })
})How is this guide?
Last updated on Jun 20, 2026