/ Docs

PostgreSQL Adapter

Overview

The PostgreSQL adapter connects to a PostgreSQL database server for durable, concurrent storage. It is the recommended adapter for production deployments.

Installation

The PostgreSQL adapter lives in a separate package:

npm i @bounda-dev/adapter-postgresql

Supported Features

FeatureSupported
Event StoreYes
Read ModelYes
Policy DLQYes
Process Manager DLQYes
SchedulingYes

When to Use

  • Production deployments — Full durability, ACID transactions, and concurrent access.
  • Multi-process applications — Safe concurrent writes from multiple server instances.
  • Environments with existing PostgreSQL infrastructure — Reuse your existing database server.

Configuration

Every PostgreSQL configuration requires a url (connection string) and a schema (database schema name). Bounda creates the schema and tables automatically on first boot.

Event Store

domain: {
  user: {
    eventStore: {
      type: "postgresql",
      url: process.env.DATABASE_URL,
      schema: "bounda",
    },
  },
}

Read Model

read: {
  "my-profile": {
    type: "postgresql",
    url: process.env.DATABASE_URL,
    schema: "bounda",
  },
}

Scheduling

domain: {
  user: {
    scheduling: {
      type: "postgresql",
      url: process.env.DATABASE_URL,
      schema: "bounda",
    },
  },
}

Process Manager DLQ

domain: {
  user: {
    processManagers: {
      dlq: {
        type: "postgresql",
        url: process.env.DATABASE_URL,
        schema: "bounda",
      },
    },
  },
}

Policy DLQ

domain: {
  user: {
    policies: {
      dlq: {
        type: "postgresql",
        url: process.env.DATABASE_URL,
        schema: "bounda",
      },
    },
  },
}
OptionTypeDescription
type"postgresql"Adapter type
urlstringPostgreSQL connection URL (e.g., postgresql://user:pass@host:5432/db)
schemastringDatabase schema name. Bounda creates it if it does not exist.

Environment Variables

Using environment variables for connection details keeps secrets out of your codebase:

import type { Config } from "@bounda-dev/config";

const schema = process.env.BOUNDA_SCHEMA ?? "bounda";

export default {
  domain: {
    user: {
      eventStore: {
        type: "postgresql",
        url: process.env.DATABASE_URL,
        schema,
      },
      scheduling: {
        type: "postgresql",
        url: process.env.DATABASE_URL,
        schema,
      },
      processManagers: {
        dlq: {
          type: "postgresql",
          url: process.env.DATABASE_URL,
          schema,
        },
      },
    },
  },
  read: {
    "my-profile": {
      type: "postgresql",
      url: process.env.DATABASE_URL,
      schema,
    },
  },
} satisfies Config;

Testing

Integration tests for the PostgreSQL adapter use TestContainers to spin up a real postgres:17 instance. A single container is shared across all test suites via vitest’s globalSetup; each suite gets its own schema for isolation.

To run the tests locally, Docker must be running:

npm test --workspace=@bounda-dev/adapter-postgresql