Overview
The Data Persistence Plugin provides utilities to serialize and restore Orama instances in multiple formats. This allows you to save your search index to disk or transfer it over the network, then restore it later without re-indexing.
Installation
npm install @orama/plugin-data-persistence
The plugin supports four serialization formats:
JSON Human-readable, largest size, slowest
Binary (MessagePack) Compact binary format, good balance
dpack Highly optimized binary format
seqproto Sequential protocol, best compression
Basic Usage
Persist (Save) an Instance
import { create , insert } from '@orama/orama'
import { persist } from '@orama/plugin-data-persistence'
// Create and populate a database
const db = await create ({
schema: {
title: 'string' ,
description: 'string'
}
})
await insert ( db , { title: 'Product 1' , description: 'Description 1' })
await insert ( db , { title: 'Product 2' , description: 'Description 2' })
// Serialize to binary format
const serialized = await persist ( db , 'binary' )
// Save to file (Node.js)
import { writeFile } from 'fs/promises'
await writeFile ( 'database.bin' , serialized )
Restore (Load) an Instance
import { restore } from '@orama/plugin-data-persistence'
import { readFile } from 'fs/promises'
// Load from file
const data = await readFile ( 'database.bin' )
// Restore the database
const db = await restore ( 'binary' , data )
// Database is ready to use
const results = await search ( db , { term: 'Product' })
API Reference
persist()
Serialize an Orama instance to a specific format.
async function persist < T extends AnyOrama >(
db : T ,
format ?: PersistenceFormat ,
runtime ?: Runtime
) : Promise < string | Buffer | ArrayBuffer >
The Orama instance to serialize
format
PersistenceFormat
default: "binary"
Serialization format: 'json', 'binary', 'dpack', or 'seqproto'
Runtime environment: 'node' or 'browser'. Auto-detected if not provided
Returns : Serialized data as string, Buffer, or ArrayBuffer depending on format and runtime
restore()
Deserialize data and create an Orama instance.
async function restore < T extends AnyOrama >(
format : PersistenceFormat ,
data : string | Buffer | ArrayBuffer ,
runtime ?: Runtime
) : Promise < T >
format
PersistenceFormat
required
Serialization format used: 'json', 'binary', 'dpack', or 'seqproto'
data
string | Buffer | ArrayBuffer
required
The serialized data to restore
Runtime environment: 'node' or 'browser'. Auto-detected if not provided
Returns : A fully functional Orama instance
import { persist , restore } from '@orama/plugin-data-persistence'
// Serialize to JSON
const jsonString = await persist ( db , 'json' )
// Human-readable output
console . log ( jsonString . substring ( 0 , 100 ))
// {"schema":{"title":"string","description":"string"},...
// Restore from JSON
const db = await restore ( 'json' , jsonString )
Pros:
Human-readable
Easy to debug
Compatible with any system
Cons:
Largest file size
Slowest to serialize/deserialize
// Serialize to binary (hex string in Node.js, Uint8Array in browser)
const binaryData = await persist ( db , 'binary' )
// Node.js - Save as hex string
await writeFile ( 'db.bin' , binaryData )
// Restore from binary
const db = await restore ( 'binary' , binaryData )
Pros:
Compact size
Good performance
Standard format (MessagePack)
Cons:
Not human-readable
Requires format knowledge
// Highly optimized binary format
const dpackData = await persist ( db , 'dpack' )
// Restore from dpack
const db = await restore ( 'dpack' , dpackData )
Pros:
Highly optimized
Very compact
Fast serialization
Cons:
Proprietary format
Not human-readable
// Sequential protocol format
const seqprotoData = await persist ( db , 'seqproto' )
// Restore from seqproto
const db = await restore ( 'seqproto' , seqprotoData )
Pros:
Best compression
Optimized for Orama data structures
Fastest restore time
Cons:
Orama-specific format
Not human-readable
Usage Examples
Node.js: Save and Load from File
import { create , insert } from '@orama/orama'
import { persist , restore } from '@orama/plugin-data-persistence'
import { writeFile , readFile } from 'fs/promises'
// Create and populate database
const db = await create ({
schema: {
title: 'string' ,
description: 'string' ,
category: 'string'
}
})
await insert ( db , {
title: 'JavaScript Guide' ,
description: 'Learn JavaScript fundamentals' ,
category: 'Programming'
})
// Save to file using binary format
const serialized = await persist ( db , 'binary' , 'node' )
await writeFile ( './data/search-index.bin' , serialized )
// Later, restore from file
const data = await readFile ( './data/search-index.bin' )
const restoredDB = await restore ( 'binary' , data , 'node' )
// Use restored database
const results = await search ( restoredDB , { term: 'JavaScript' })
Browser: Save to localStorage
import { create , insert } from '@orama/orama'
import { persist , restore } from '@orama/plugin-data-persistence'
// Create and populate database
const db = await create ({
schema: {
id: 'string' ,
name: 'string'
}
})
await insert ( db , { id: '1' , name: 'Item 1' })
// Serialize and save to localStorage
const serialized = await persist ( db , 'json' , 'browser' )
localStorage . setItem ( 'orama-db' , serialized )
// Restore from localStorage
const stored = localStorage . getItem ( 'orama-db' )
if ( stored ) {
const restoredDB = await restore ( 'json' , stored , 'browser' )
// Use restored database
}
Browser: Save to IndexedDB
import { create } from '@orama/orama'
import { persist , restore } from '@orama/plugin-data-persistence'
// Serialize to binary for IndexedDB
const serialized = await persist ( db , 'seqproto' )
// Save to IndexedDB
const dbRequest = indexedDB . open ( 'OramaStorage' , 1 )
dbRequest . onsuccess = ( event ) => {
const idb = event . target . result
const transaction = idb . transaction ([ 'indexes' ], 'readwrite' )
const store = transaction . objectStore ( 'indexes' )
store . put ({ id: 'main-index' , data: serialized })
}
// Restore from IndexedDB
dbRequest . onsuccess = async ( event ) => {
const idb = event . target . result
const transaction = idb . transaction ([ 'indexes' ], 'readonly' )
const store = transaction . objectStore ( 'indexes' )
const request = store . get ( 'main-index' )
request . onsuccess = async () => {
const db = await restore ( 'seqproto' , request . result . data )
// Use restored database
}
}
Transfer over Network
// Server: Serialize and send
const db = await create ({ schema })
// ... populate database ...
const serialized = await persist ( db , 'dpack' , 'node' )
// Send via HTTP
app . get ( '/api/search-index' , ( req , res ) => {
res . setHeader ( 'Content-Type' , 'application/octet-stream' )
res . send ( Buffer . from ( serialized ))
})
// Client: Receive and restore
const response = await fetch ( '/api/search-index' )
const arrayBuffer = await response . arrayBuffer ()
const db = await restore ( 'dpack' , arrayBuffer , 'browser' )
For a database with 10,000 documents:
Format Size Serialization Time Deserialization Time JSON ~5.2 MB ~450ms ~380ms Binary ~2.8 MB ~280ms ~220ms dpack ~2.1 MB ~210ms ~180ms seqproto ~1.8 MB ~190ms ~150ms
Results vary based on data structure and content. Test with your actual data for accurate measurements.
// For debugging and development
const serialized = await persist ( db , 'json' )
// For production (good balance)
const serialized = await persist ( db , 'binary' )
// For best performance and size
const serialized = await persist ( db , 'seqproto' )
// For compatibility with external tools
const serialized = await persist ( db , 'dpack' )
Common Patterns
Auto-save on Changes
import { create , insert } from '@orama/orama'
import { persist } from '@orama/plugin-data-persistence'
import { writeFile } from 'fs/promises'
const db = await create ({ schema })
// Wrap insert to auto-save
const insertAndSave = async ( doc ) => {
await insert ( db , doc )
const serialized = await persist ( db , 'binary' )
await writeFile ( 'db.bin' , serialized )
}
await insertAndSave ({ title: 'Document 1' })
Lazy Loading
let db = null
// Load database only when needed
async function getDB () {
if ( ! db ) {
const data = await readFile ( 'db.bin' )
db = await restore ( 'binary' , data )
}
return db
}
// Use lazy loading
const results = await search ( await getDB (), { term: 'test' })
Versioned Persistence
import { persist } from '@orama/plugin-data-persistence'
import { writeFile } from 'fs/promises'
const version = '1.0.0'
const serialized = await persist ( db , 'binary' )
// Save with version metadata
await writeFile ( 'db.bin' , JSON . stringify ({
version ,
format: 'binary' ,
data: serialized ,
timestamp: new Date (). toISOString ()
}))
// Restore with version check
const stored = JSON . parse ( await readFile ( 'db.bin' , 'utf-8' ))
if ( stored . version !== '1.0.0' ) {
throw new Error ( 'Incompatible database version' )
}
const db = await restore ( 'binary' , stored . data )
Runtime Detection
The plugin automatically detects the runtime environment:
// Auto-detection (recommended)
const serialized = await persist ( db , 'binary' )
// Explicit runtime (for edge cases)
const serialized = await persist ( db , 'binary' , 'node' )
const serialized = await persist ( db , 'binary' , 'browser' )
At /home/daytona/workspace/source/packages/plugin-data-persistence/src/index.ts:54-61:
export async function persist < T extends AnyOrama >(
db : T ,
format : PersistenceFormat = 'binary' ,
runtime ?: Runtime
) : Promise < string | Buffer | ArrayBuffer > {
if ( ! runtime ) {
runtime = detectRuntime ()
}
// ...
}
Troubleshooting
Error: Unsupported persistence format: xyz
Use one of the supported formats: 'json', 'binary', 'dpack', or 'seqproto'.
Restore Fails
Ensure the format matches:
// ❌ Wrong
const data = await persist ( db , 'json' )
const restored = await restore ( 'binary' , data ) // Error!
// ✅ Correct
const data = await persist ( db , 'json' )
const restored = await restore ( 'json' , data )
For very large databases (>100MB):
Use seqproto format for best compression
Consider streaming if supported by your environment
Implement incremental loading
Next Steps
Import Data Learn more about data import and export
Custom Plugins Build plugins that work with persistence
Performance Optimize your Orama instances