Postgres World

This page is a work in progress.

This world is a reference implementation, not a production-ready product. We do not recommend using it in production. However, you can definitely use it as inspiration for a real-world database-backed solution that might run workflow and step workers separately from the triggering applications.

The PostgreSQL world is a reference implementation of a world that's fully backed by PostgreSQL, including job processing (using pg-bossExternal link) and streaming (using PostgreSQL's NOTIFY and LISTEN).

This world is designed for long-running processes, so it can receive and dispatch events from a PostgreSQL database, and isn't meant to be deployed on serverless platforms like Vercel due to that nature.

Setup

Install the package

Install the @workflow/world-postgres package:

npm install @workflow/world-postgres

Set up the database schema

Run the setup script to create the required database tables:

pnpm exec workflow-postgres-setup

This will create the following tables in your PostgreSQL database:

  • workflow_runs - Stores workflow execution state
  • workflow_events - Stores workflow events
  • workflow_steps - Stores workflow step state
  • workflow_hooks - Stores workflow hooks
  • workflow_stream_chunks - Stores streaming data

You should see output like:

🔧 Setting up database schema...
📍 Connection: postgres://postgres:****@db.yourcloudprovider.co:5432/postgres
✅ Database schema created successfully!

Configure environment variables

Add the following environment variables to your .env file:

WORKFLOW_TARGET_WORLD="@workflow/world-postgres"
WORKFLOW_POSTGRES_URL="postgres://postgres:password@db.yourdb.co:5432/postgres"
WORKFLOW_POSTGRES_JOB_PREFIX="workflow_"
WORKFLOW_POSTGRES_WORKER_CONCURRENCY=10
VariableDescriptionDefault
WORKFLOW_TARGET_WORLDTarget world implementation to useRequired
WORKFLOW_POSTGRES_URLPostgreSQL connection stringpostgres://world:world@localhost:5432/world
WORKFLOW_POSTGRES_JOB_PREFIXPrefix for queue job namesworkflow_
WORKFLOW_POSTGRES_WORKER_CONCURRENCYNumber of concurrent workers10

Initialize the world

Create an instrumentation.ts file in your project root to initialize and start the world:

instrumentation.ts
import { createWorld } from "@workflow/world-postgres";

export async function register() {
  if (process.env.NEXT_RUNTIME !== "edge") {
    console.log("Starting workflow workers...");

    const world = createWorld({
      connectionString: process.env.WORKFLOW_POSTGRES_URL!,
      jobPrefix: process.env.WORKFLOW_POSTGRES_JOB_PREFIX || "workflow_",
      queueConcurrency: parseInt(
        process.env.WORKFLOW_POSTGRES_WORKER_CONCURRENCY || "10",
        10
      ),
    });

    await world.start?.();
    console.log("Workflow workers started!");
  }
}

Configure Next.js

Enable the instrumentation hook in your next.config.ts:

next.config.ts
import type { NextConfig } from "next";
import { withWorkflow } from "workflow/next";

const nextConfig: NextConfig = {
  // … rest of your Next.js config
};

export default withWorkflow(nextConfig);

How it works

The Postgres World uses PostgreSQL as a durable backend for workflow execution:

  • Job Queue: Uses pg-bossExternal link for reliable job processing
  • Event Streaming: Leverages PostgreSQL's NOTIFY/LISTEN for real-time event distribution
  • State Persistence: All workflow state is stored in PostgreSQL tables
  • Worker Management: Supports configurable concurrent workers for job processing

This setup ensures that your workflows can survive application restarts and failures, with all state reliably persisted to your PostgreSQL database.