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 -d3. 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.