OpenMAIC Storage Backends: IndexedDB, PostgreSQL, and In-Memory Support
OpenMAIC supports three pluggable storage backends: browser-based IndexedDB for offline-first operation, PostgreSQL for server-persisted data, and an in-memory store for unit testing.
The THU-MAIC/OpenMAIC repository implements a deliberately neutral storage backend architecture that allows the same application to run entirely client-side or with full server persistence. This design swaps storage implementations at build time using the @openmaic/storage package, ensuring course documents and learner state remain accessible across deployment scenarios.
The Three OpenMAIC Storage Backends
OpenMAIC’s persistence layer abstracts storage behind a common interface, enabling three concrete implementations.
Browser-Based IndexedDB (Default)
The default storage backend runs entirely in the browser using IndexedDB. This implementation stores course documents (stages, scenes, outlines), learner runtime state (chat sessions, playback cursor), and asset registries locally without requiring a database server.
The core implementation resides in packages/@openmaic/storage/src/document-store.ts, which exports the DocumentStore abstraction used throughout the application. Configuration constants for local storage keys are defined in configs/storage.ts.
Server-Backed PostgreSQL
When the build-time flag NEXT_PUBLIC_PERSISTENCE=1 is enabled, OpenMAIC swaps the IndexedDB stores for PostgreSQL-backed implementations. This storage backend persists the same document types and runtime state in PostgreSQL tables accessed via an embedded HTTP persistence API at /api/persistence.
The server-side implementation bridges client requests to the database through packages/@openmaic/storage/src/server/document.ts, with authentication stubs located in lib/persistence/server-auth.ts. This backend requires the DATABASE_URL environment variable to connect to the PostgreSQL instance.
In-Memory Storage (Testing)
For unit testing, OpenMAIC provides a lightweight in-memory storage backend that implements the same interface without side effects. The MemoryStorage class defined in packages/@openmaic/storage/test/setup.ts allows tests to mock document persistence and asset storage without writing to disk or network.
Configuring Storage Backends
Switching between storage backends requires environment configuration and rebuilds.
Using Default Browser Storage
No configuration is required to use the IndexedDB backend. Import the store directly:
import { getDocumentStore } from '@/lib/document-store/store';
// Load a stage document from IndexedDB
const doc = await getDocumentStore().loadDocument('stage-123');
console.log(doc?.stage.name);
Enabling PostgreSQL Persistence
Set the required environment variables and rebuild the application:
# .env.local
DATABASE_URL=postgres://openmaic:openmaic-dev@postgres:5432/openmaic
NEXT_PUBLIC_PERSISTENCE=1
NEXT_PUBLIC_PERSISTENCE_TOKEN=openmaic-local-dev
After rebuilding with the flag enabled, the same API calls route to the PostgreSQL-backed DocumentStore:
import { getDocumentStore } from '@/lib/document-store/store';
const doc = await getDocumentStore().loadDocument('stage-123');
// The document is fetched from the PostgreSQL-backed DocumentStore
Using In-Memory Storage for Tests
Import the MemoryStorage class for test scenarios:
import { MemoryStorage } from '@openmaic/storage/test/setup';
const storage = new MemoryStorage(); // implements the same Storage interface
await storage.setItem('MAIC_DISCARDED_DB', '[]');
// Use `storage` in place of the real IndexedDB store for fast unit tests
Asset Storage Options
Beyond document storage, OpenMAIC supports flexible asset storage configurations within the PostgreSQL backend. Assets can reside either in PostgreSQL bytea columns or in external S3 buckets. The HTTP contract supports both direct byte delivery and redirects to signed S3 URLs, as documented in the storage package's asset-http-contract.md.
Summary
- OpenMAIC provides three storage backends: IndexedDB (default), PostgreSQL (server-side), and in-memory (testing).
- The pluggable architecture swaps implementations via the
@openmaic/storagepackage based on theNEXT_PUBLIC_PERSISTENCEbuild flag. - Source code for browser storage lives in
packages/@openmaic/storage/src/document-store.ts, while PostgreSQL implementations are inpackages/@openmaic/storage/src/server/document.ts. - Asset storage supports both PostgreSQL binary columns and S3-backed blob storage.
- The
MemoryStorageclass inpackages/@openmaic/storage/test/setup.tsenables fast, side-effect-free unit testing.
Frequently Asked Questions
What is the default storage backend in OpenMAIC?
The default storage backend is browser-based IndexedDB, implemented in packages/@openmaic/storage/src/document-store.ts. This requires no server infrastructure and stores all course documents, learner state, and asset metadata locally in the browser.
How do I switch from IndexedDB to PostgreSQL storage?
Set the environment variable NEXT_PUBLIC_PERSISTENCE=1 and provide a valid DATABASE_URL pointing to your PostgreSQL instance. Rebuild the application to switch the storage backend from client-side IndexedDB to the server-persisted PostgreSQL implementation exposed via /api/persistence.
Can I use S3 for asset storage with OpenMAIC?
Yes. When using the PostgreSQL storage backend, assets can be configured to use either PostgreSQL bytea columns or external S3 buckets. The HTTP persistence API supports direct byte delivery or redirects to signed S3 URLs, allowing flexible asset hosting strategies.
Is there a way to test OpenMAIC without setting up a database?
Yes. The codebase includes an in-memory storage backend via the MemoryStorage class in packages/@openmaic/storage/test/setup.ts. This implementation mocks the storage interface for unit tests, eliminating the need for IndexedDB or PostgreSQL during development.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →