# DuckDB storage

[DuckDB](https://duckdb.org/) is an embedded, in-process analytical database. The `@mastra/duckdb` package provides an OLAP-backed observability store for local development, suitable for traces, logs, metrics, scores, and feedback without running an external service.

For vector search, see the [DuckDB vector store reference](https://mastra.ai/reference/vectors/duckdb), which is a separate API in the same package.

## When to use DuckDB

Local development of observability features. DuckDB is embedded and file-based, so it does not require a server and starts instantly. It supports the same observability signals as ClickHouse, which makes it useful for testing dashboards and trace exploration before deploying to a production backend.

DuckDB currently implements only the `observability` domain. Pair it with another storage adapter (such as [LibSQL](https://mastra.ai/reference/storage/libsql)) for `memory` and `workflows` in a [composite storage](https://mastra.ai/reference/storage/composite) setup.

> **Warning:** DuckDB is for development and not recommended for production. It runs in-process, persists to a single local file, and does not work on platforms with ephemeral filesystems (such as Railway, Fly.io, Render, Heroku, or serverless containers). For production observability, use [ClickHouse](https://mastra.ai/reference/storage/clickhouse).

## Installation

**npm**:

```bash
npm install @mastra/duckdb@latest
```

**pnpm**:

```bash
pnpm add @mastra/duckdb@latest
```

**Yarn**:

```bash
yarn add @mastra/duckdb@latest
```

**Bun**:

```bash
bun add @mastra/duckdb@latest
```

## Usage

### As the observability domain in a composite store

This is the standard local-development setup. LibSQL handles the other domains, and DuckDB handles observability.

```typescript
import { Mastra } from '@mastra/core'
import { MastraCompositeStore } from '@mastra/core/storage'
import { LibSQLStore } from '@mastra/libsql'
import { DuckDBStore } from '@mastra/duckdb'
import { Observability, MastraStorageExporter } from '@mastra/observability'

export const mastra = new Mastra({
  storage: new MastraCompositeStore({
    id: 'composite-storage',
    default: new LibSQLStore({
      id: 'mastra-storage',
      url: 'file:./mastra.db',
    }),
    domains: {
      observability: new DuckDBStore().observability,
    },
  }),
  observability: new Observability({
    configs: {
      default: {
        serviceName: 'mastra',
        exporters: [new MastraStorageExporter()],
      },
    },
  }),
})
```

The `.observability` accessor returns the observability domain store directly. The equivalent generic form uses `getStore()`, which works for any composite-style storage adapter:

```typescript
const observability = await new DuckDBStore().getStore('observability')
```

### Standalone

When you need only observability storage outside the `Mastra` composite, instantiate `DuckDBStore` directly and access the observability domain:

```typescript
import { DuckDBStore } from '@mastra/duckdb'

const duckdb = new DuckDBStore({ path: './traces.duckdb' })
const observability = duckdb.observability

await observability.init()
```

### In-memory database

Pass `:memory:` to use an ephemeral DuckDB instance. Data is lost when the process exits, which is appropriate for unit tests and short-lived scripts.

```typescript
const duckdb = new DuckDBStore({ path: ':memory:' })
```

## Configuration

### `DuckDBStore` options

**id** (`string`): Unique identifier for this storage instance. (Default: `'duckdb'`)

**path** (`string`): Path to the DuckDB database file. Use \`:memory:\` for an ephemeral in-memory database. (Default: `'mastra.duckdb'`)

### Lower-level types

`@mastra/duckdb` also exports `DuckDBConnection` for sharing a single underlying database across multiple Mastra storage instances, and the corresponding `DuckDBStorageConfig` type. Most applications will not need these directly.

## Supported domains

DuckDB currently implements one storage domain:

| Domain          | Supported |
| --------------- | --------- |
| `observability` | Yes       |
| `memory`        | No        |
| `workflows`     | No        |
| `scores`        | No        |
| `agents`        | No        |

For a full storage solution, compose `DuckDBStore` with an adapter that covers the missing domains (most commonly [LibSQL](https://mastra.ai/reference/storage/libsql) for local development).

## Initialization

When passed to `Mastra` through `MastraCompositeStore`, the observability domain initializes itself on first use. To run initialization explicitly outside of `Mastra`, call `init()` on the observability store:

```typescript
import { DuckDBStore } from '@mastra/duckdb'

const duckdb = new DuckDBStore({ path: './traces.duckdb' })
await duckdb.observability.init()
```

## Observability strategy

DuckDB supports the `event-sourced` strategy used by `MastraStorageExporter`, which buffers spans in memory and writes completed events in batches. This is appropriate for development-scale traffic. For high-volume production workloads, see [`MastraStorageExporter` storage provider support](https://mastra.ai/docs/observability/tracing/exporters/mastra-storage).

## Related

- [Storage overview](https://mastra.ai/reference/storage/overview)
- [Composite storage](https://mastra.ai/reference/storage/composite)
- [ClickHouse storage](https://mastra.ai/reference/storage/clickhouse): Production observability backend
- [DuckDB vector store](https://mastra.ai/reference/vectors/duckdb): Vector search using the same package
- [Observability overview](https://mastra.ai/docs/observability/overview)