Skip to content

Self-Hosting & Operations

Invariant is 100% open-source and designed to be self-hosted on your own infrastructure (AWS, GCP, Azure, or bare-metal Linux servers) with PostgreSQL.

1. Prerequisites

  • Node.js: v18.x or v20.x+
  • PostgreSQL: v14+ (Cloud SQL, RDS, Supabase, or self-hosted Docker)

2. Quick Setup with Docker Compose

Spin up a local PostgreSQL database configured for Invariant:

yaml
# docker-compose.yml
version: "3.8"

services:
  postgres:
    image: postgres:16-alpine
    container_name: invariant-db
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgrespassword
      POSTGRES_DB: invariant
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata:

Run Docker Compose:

bash
docker-compose up -d

3. Database Schema Setup

Run the migrations script provided by @invariant/postgres to initialize the tables (workflow_runs, workflow_events, workflow_states, workflow_outbox, workflow_leases):

bash
npx @invariant/postgres migrate --connection "postgres://postgres:postgrespassword@localhost:5432/invariant"

4. Production Configuration & Scaling Workers

In production, you can scale worker nodes horizontally across multiple containers or VMs:

ts
import { invariant } from "@invariant/sdk";
import { postgres } from "@invariant/postgres";
import os from "os";

const app = invariant({
  store: postgres({
    connectionString: process.env.DATABASE_URL,
    maxConnections: 20,
  }),
  workerId: `${os.hostname()}-${process.pid}`, // Unique per container instance
  leaseTtlMs: 30000,
});

await app.start();

Worker Scaling Behavior:

  • Multiple workers can poll the same PostgreSQL database concurrently.
  • Row locks (FOR UPDATE) and leases (worker_id, lease_expires_at) prevent worker conflicts.
  • If Worker A dies, Worker B will automatically claim its expired runs within 30 seconds.

Invariant Durable Execution Engine.