# OpenMAIC Persistence Backends: Browser, HTTP, PostgreSQL, and S3 Explained

> Explore OpenMAIC persistence backends including Browser, HTTP, PostgreSQL, and S3. Learn how to select and configure your RuntimeStore for efficient data management.

- Repository: [MAIC/OpenMAIC](https://github.com/THU-MAIC/OpenMAIC)
- Tags: deep-dive
- Published: 2026-09-01

---

**OpenMAIC provides four concrete persistence backends—Browser (IndexedDB), HTTP (REST API), PostgreSQL (SQL), and S3 (object storage)—that implement a unified RuntimeStore interface and can be selected via the `NEXT_PUBLIC_PERSISTENCE` environment variable.**

OpenMAIC is a modular framework for building AI-driven applications that require reliable data persistence across diverse environments. The library abstracts all storage operations behind a small, runtime-store interface defined in `packages/@openmaic/storage/src/runtime/types.ts`, allowing developers to swap between local browser storage, remote HTTP APIs, production PostgreSQL databases, and Amazon S3 buckets without changing application logic.

## The Runtime Store Interface

All persistence implementations conform to the `RuntimeStore` interface exported from `packages/@openmaic/storage/src/runtime/types.ts`. This contract defines standard methods for session management, append-only record storage, and document persistence. Every concrete backend performs envelope validation and stamps writes with the current DSL version before committing, ensuring data integrity regardless of the underlying storage mechanism.

## Browser Backend: IndexedDB for Client-Side Storage

The **Browser** backend stores runtime sessions, append-only records, and document data directly in the user’s browser using IndexedDB.

Located in `packages/@openmaic/storage/src/runtime/browser.ts`, the `BrowserRuntimeStore` class creates two object stores—`sessions` and `records`—within a versioned IndexedDB database. This backend is the default when `NEXT_PUBLIC_PERSISTENCE` is unset, making it ideal for rapid prototyping and offline-first applications. All writes are atomic at the IndexedDB transaction level and include automatic schema validation against the current DSL version.

```typescript
import { BrowserRuntimeStore } from '@openmaic/storage';

const store = new BrowserRuntimeStore();
// IndexedDB automatically initialized in the client
await store.saveSession({ id: 'session-123', data: {} });

```

## HTTP Backend: REST API Persistence

The **HTTP** backend persists data to a remote OpenMAIC server through the public REST API endpoints under `/api/persistence/*`.

Implemented in `packages/@openmaic/storage/src/runtime/http.ts`, the `HttpRuntimeStore` encodes `RuntimeSession` and `RuntimeRecord` payloads as JSON and transmits them via the Fetch API. This backend validates the same envelopes as the browser store but delegates durable storage to the server. It is the preferred choice for SaaS deployments where client state must survive browser refreshes and be accessible across multiple devices.

```typescript
import { HttpRuntimeStore } from '@openmaic/storage';

const store = new HttpRuntimeStore({
  baseUrl: 'https://my-openmaic.example.com/api/persistence',
});
await store.appendRecord({ type: 'event', payload: {} });

```

## PostgreSQL Backend: Durable Server-Side SQL

The **PostgreSQL** backend provides durable, server-side storage backed by the `node-postgres` library.

Found in `packages/@openmaic/storage/src/runtime/pg.ts`, the `PgRuntimeStore` initializes a `pg.Pool` connection and mirrors the browser store’s validation logic while using SQL transactions for atomicity. This backend stores sessions and records in PostgreSQL tables and supports concurrent access patterns required for production workloads. The implementation validates envelopes before executing parameterized INSERT statements, preventing SQL injection while maintaining type safety.

```typescript
import { PgRuntimeStore } from '@openmaic/storage';

const store = new PgRuntimeStore({
  connectionString: process.env.DATABASE_URL!, // postgres://user:pw@host/db
});
await store.saveSession({ id: 'prod-session-456', data: {} });

```

## S3 Backend: Object Storage for Binary Assets

The **S3** backend handles large binary assets such as audio, video, and PDF files outside the runtime store interface.

Located in `packages/@openmaic/storage/src/asset/s3-bytes.ts`, the `S3AssetStore` wraps the AWS SDK `S3Client` to perform `PUT` and `GET` operations against a configured bucket. Assets are referenced by deterministic keys and can be streamed directly from S3, reducing memory pressure on application servers. Unlike the runtime stores that handle structured session data, this backend is optimized for high-throughput byte storage and retrieval.

```typescript
import { S3AssetStore } from '@openmaic/storage';

const store = new S3AssetStore({
  bucket: 'my-openmaic-assets',
  region: 'us-east-1',
  credentials: {
    accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
  },
});

await store.put('audio/scene-42.wav', new Blob([audioBytes]));
const asset = await store.get('audio/scene-42.wav');

```

## Configuration and Environment Selection

You can select a persistence backend by setting the `NEXT_PUBLIC_PERSISTENCE` environment variable or by importing the specific implementation programmatically. The runtime detects this variable during initialization and instantiates the corresponding store class. For Node.js server environments, PostgreSQL is typically selected for durability, while the Browser backend is automatically chosen for client-side bundles when no override is specified.

## Summary

- **Four concrete implementations** ship with OpenMAIC: `BrowserRuntimeStore` (IndexedDB), `HttpRuntimeStore` (REST), `PgRuntimeStore` (PostgreSQL), and `S3AssetStore` (object storage).
- **Unified interface** (`RuntimeStore` in [`src/runtime/types.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/src/runtime/types.ts)) ensures identical validation, DSL versioning, and transaction semantics across all backends.
- **Environment-driven selection** via `NEXT_PUBLIC_PERSISTENCE` allows deployment-time configuration without code changes.
- **Atomicity guarantees** differ by backend: IndexedDB transactions for Browser, SQL transactions for PostgreSQL, and idempotent PUT operations for S3.
- **Asset separation** distinguishes runtime metadata (sessions/records) stored in Browser/HTTP/PostgreSQL from large binary objects stored in S3.

## Frequently Asked Questions

### How do I switch between persistence backends in OpenMAIC?

Set the `NEXT_PUBLIC_PERSISTENCE` environment variable to `browser`, `http`, or `pg` (PostgreSQL) before building your application. The storage module reads this variable at runtime and exports the corresponding store class. For S3 asset storage, import `S3AssetStore` directly from `@openmaic/storage` and instantiate it with your AWS credentials.

### Can I use a different SQL database like MySQL instead of PostgreSQL?

The official `PgRuntimeStore` in `packages/@openmaic/storage/src/runtime/pg.ts` is the only full-SQL backend shipped with OpenMAIC. If you require MySQL or another RDBMS, you must implement the `RuntimeStore` interface defined in [`src/runtime/types.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/src/runtime/types.ts) and provide your own connection pooling and query logic following the same envelope validation pattern used in the PostgreSQL adapter.

### What is the difference between RuntimeStore and S3AssetStore?

`RuntimeStore` implementations (Browser, HTTP, PostgreSQL) handle structured, queryable data such as user sessions and append-only event records with strict schema validation. `S3AssetStore` operates outside this interface and manages opaque binary blobs (audio, video, PDFs) where only byte-level storage and retrieval are required, not complex querying or transactional updates.

### Is the Browser backend suitable for production applications?

The Browser backend is suitable for production when data privacy requirements mandate client-side storage or for offline-capable progressive web applications. However, because IndexedDB data resides in the user’s browser, it is subject to storage quotas and can be cleared by browser privacy settings. For multi-device synchronization or critical data durability, deploy the HTTP or PostgreSQL backends instead.