> ## Documentation Index
> Fetch the complete documentation index at: https://openworkflow.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# PostgreSQL Backend

> Production-ready PostgreSQL storage for OpenWorkflow

The PostgreSQL backend is recommended for production. It supports multiple
concurrent workers, provides strong durability guarantees, and scales with your
application.

## Install

The PostgreSQL backend requires the `postgres` driver. Install it alongside
OpenWorkflow:

<CodeGroup>
  ```bash npm theme={null}
  npm i openworkflow postgres
  ```

  ```bash pnpm theme={null}
  pnpm add openworkflow postgres
  ```

  ```bash bun theme={null}
  bun add openworkflow postgres
  ```
</CodeGroup>

## Setup

```ts theme={null}
import { OpenWorkflow } from "openworkflow";
import { BackendPostgres } from "openworkflow/postgres";

const backend = await BackendPostgres.connect(
  process.env.OPENWORKFLOW_POSTGRES_URL, // e.g., "postgresql://user:pass@localhost:5432/mydb"
);

const ow = new OpenWorkflow({ backend });
```

## Connection URL

The connection URL follows the standard PostgreSQL format:

```
postgresql://[user]:[password]@[host]:[port]/[database]
```

Examples:

* Local: `postgresql://postgres:postgres@localhost:5432/openworkflow`
* With SSL: `postgresql://user:pass@host.com:5432/db?sslmode=require`

## Configuration Options

```ts theme={null}
const backend = await BackendPostgres.connect(url, {
  // Namespace for multi-tenant isolation (default: "default")
  namespaceId: "production",

  // Database schema for OpenWorkflow tables (default: "openworkflow")
  schema: "openworkflow",

  // Whether to run migrations on connect (default: true)
  runMigrations: true,
});
```

## Migrations

By default, `BackendPostgres.connect()` runs database migrations automatically.
This creates the configured schema (default: `openworkflow`) and required tables.

To disable automatic migrations:

```ts theme={null}
const backend = await BackendPostgres.connect(url, {
  runMigrations: false,
});
```

When disabled, ensure you run migrations separately before starting workers.

## Schema

OpenWorkflow creates tables in the configured schema (default: `openworkflow`):

* `<schema>.workflow_runs` - Stores workflow run state
* `<schema>.step_attempts` - Stores step execution history

This keeps OpenWorkflow data separate from your application tables.

## Namespaces

Use `namespaceId` to isolate environments or tenants:

```ts theme={null}
// Production environment
const prodBackend = await BackendPostgres.connect(url, {
  namespaceId: "production",
});

// Staging environment (same database, different namespace)
const stagingBackend = await BackendPostgres.connect(url, {
  namespaceId: "staging",
});
```

See [Namespaces](/docs/namespaces) for more details.

## Config File Example

For use with the CLI, create `openworkflow.config.ts`:

```ts theme={null}
import { defineConfig } from "@openworkflow/cli";
import { BackendPostgres } from "openworkflow/postgres";

export default defineConfig({
  backend: await BackendPostgres.connect(
    process.env.OPENWORKFLOW_POSTGRES_URL!,
  ),
  dirs: ["./openworkflow"],
});
```

## Connection Pooling

The PostgreSQL backend uses connection pooling internally. For most
applications, the default pool settings work well. The pool is managed
automatically and connections are reused across workflow executions.

## Requirements

* PostgreSQL 14 or later
* The connecting user needs permissions to:
  * Create schemas (for migrations)
  * Create tables (for migrations)
  * Read/write to the configured schema (default: `openworkflow`)
