# OpenMAIC Storage Backends: IndexedDB, PostgreSQL, and In-Memory Support

> Discover OpenMAIC storage backends: IndexedDB for offline, PostgreSQL for server data, and in-memory for testing. Optimize your application's data management.

- Repository: [MAIC/OpenMAIC](https://github.com/THU-MAIC/OpenMAIC)
- Tags: architecture
- Published: 2026-09-11

---

**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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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:

```typescript
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:

```bash

# .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`:

```typescript
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:

```typescript
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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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/storage` package based on the `NEXT_PUBLIC_PERSISTENCE` build flag.
- Source code for browser storage lives in `packages/@openmaic/storage/src/document-store.ts`, while PostgreSQL implementations are in `packages/@openmaic/storage/src/server/document.ts`.
- **Asset storage** supports both PostgreSQL binary columns and S3-backed blob storage.
- The `MemoryStorage` class in `packages/@openmaic/storage/test/setup.ts` enables 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.