---
title: PostgreSQL Store
description: Production MetadataStore backed by PostgreSQL using Grove ORM.
---

The `store/postgres` package provides a production-ready MetadataStore for collections, documents, and chunks using PostgreSQL and the Grove ORM.

## Installation

```bash
go get github.com/xraph/weave/store/postgres
```

## Setup

```go
import (
    "github.com/xraph/grove"
    "github.com/xraph/grove/drivers/pgdriver"
    pgstore "github.com/xraph/weave/store/postgres"
)

db, err := grove.Open(pgdriver.Open("postgres://user:pass@localhost:5432/mydb?sslmode=disable"))
if err != nil {
    log.Fatal(err)
}

store := pgstore.New(db)
```

Pass the store to the engine:

```go
eng, err := engine.New(
    engine.WithStore(store),
    engine.WithVectorStore(pgvec.New(pool)), // see pgvector doc
    engine.WithEmbedder(emb),
)
```

## Migrations

Call `store.Migrate(ctx)` before starting the engine to create the required tables:

```go
if err := store.Migrate(ctx); err != nil {
    log.Fatal("migrate:", err)
}
```

This is idempotent — running it on an already-migrated database is safe. Migrations use Grove's `pgmigrate` driver internally.

## Schema

The PostgreSQL store creates three tables:

| Table | Description |
|-------|-------------|
| `weave_collections` | Collection metadata — name, model, chunk config, counters |
| `weave_documents` | Document records — state, hashes, source info |
| `weave_chunks` | Chunk text and byte offsets |

All tables include `tenant_id` and `app_id` columns for multi-tenant isolation.

## Connection pool configuration

The PostgreSQL store accepts any `*grove.DB` opened with the `pgdriver`. Configure the underlying connection pool via Grove's driver options:

```go
db, err := grove.Open(pgdriver.Open(dsn,
    pgdriver.WithMaxOpenConns(25),
    pgdriver.WithMaxIdleConns(5),
    pgdriver.WithConnMaxLifetime(5 * time.Minute),
))
```

## Lifecycle

| Method | Behaviour |
|--------|-----------|
| `Migrate(ctx)` | Creates tables and indexes if they don't exist |
| `Ping(ctx)` | Verifies database connectivity |
| `Close()` | Closes the underlying `*grove.DB` |

## Forge extension

When using Weave as a Forge extension with Grove integration, you can let the extension auto-construct the store from a shared `grove.DB`:

```go
ext := extension.New(
    extension.WithGroveDatabase(""),  // use default grove.DB from DI
)
```

Or provide an explicit store:

```go
ext := extension.New(
    extension.WithStore(store),
    extension.WithDisableMigrate(), // disable auto-migration if needed
)
```
