Skip to content

Deployment

This guide covers deploying DuraGraph, configuring environment variables, and tuning production settings.


  • PostgreSQL 14+ — Event store, projections, outbox
  • NATS Server 2.9+ with JetStream enabled — Event streaming
  • Docker (optional) — For containerized deployments

The quickest way to start all services:

Terminal window
cd duragraph/
task up # Starts PostgreSQL, NATS, and the API server
task health # Verify all services are healthy

This uses docker-compose.yml which provisions PostgreSQL, NATS, and the DuraGraph server with sensible defaults.


VariableDefaultDescription
PORT8080HTTP server port
HOST0.0.0.0HTTP server bind address
DB_HOSTlocalhostPostgreSQL host
DB_PORT5432PostgreSQL port
DB_USERappuserPostgreSQL user
DB_PASSWORDapppassPostgreSQL password
DB_NAMEappdbPostgreSQL database name
NATS_URLnats://localhost:4222NATS connection URL
VariableDefaultDescription
AUTH_ENABLEDfalseEnable JWT authentication
JWT_SECRETJWT signing secret
VariableDefaultDescription
RATE_LIMIT_ENABLEDfalseEnable rate limiting middleware
RATE_LIMIT_RPS10Requests per second per client
RATE_LIMIT_BURST20Maximum burst size (token bucket capacity)

When enabled, the server uses in-memory token bucket rate limiting (SimpleRateLimit) keyed by client IP. If a request arrives from an authenticated user, the user_id from the auth context is used as the rate limit key instead.

Rate limit headers returned on every response:

HeaderDescription
X-RateLimit-LimitBurst capacity
X-RateLimit-RemainingTokens remaining
Retry-AfterSeconds until next allowed request (only on 429)

Endpoints /health, /metrics, and /ok are excluded from rate limiting.

VariableDescription
OPENAI_API_KEYOpenAI API key
ANTHROPIC_API_KEYAnthropic API key

Migrations are in deploy/sql/ and must be applied in order:

Terminal window
# Using task runner
task db:migrate
# Or manually
psql -h $DB_HOST -U $DB_USER -d $DB_NAME -f deploy/sql/001_init.sql
psql -h $DB_HOST -U $DB_USER -d $DB_NAME -f deploy/sql/002_event_store.sql
psql -h $DB_HOST -U $DB_USER -d $DB_NAME -f deploy/sql/003_outbox.sql
psql -h $DB_HOST -U $DB_USER -d $DB_NAME -f deploy/sql/004_projections.sql
psql -h $DB_HOST -U $DB_USER -d $DB_NAME -f deploy/sql/010_horizontal_scaling.sql

The 010_horizontal_scaling.sql migration adds version and lease_epoch columns to the runs table for optimistic concurrency control and lease fencing in multi-instance deployments.


DuraGraph supports running multiple API server instances behind a load balancer. No external coordination (etcd, ZooKeeper) is required — all coordination uses PostgreSQL primitives.

  • Optimistic concurrency — Version columns prevent lost updates
  • Advisory locks — Singleton background jobs (lease monitor) run on exactly one instance
  • Skip locked — Outbox relay and lease scanning work concurrently across instances
  • Lease epoch fencing — Stale workers cannot complete reassigned tasks
  1. All instances connect to the same PostgreSQL database
  2. All instances connect to the same NATS cluster
  3. Place instances behind a load balancer (round-robin is fine)
  4. No sticky sessions required
  5. Run task db:migrate once (not per instance)

EndpointPurposeRate Limited
/healthFull health check (DB + NATS connectivity)No
/okSimple liveness probeNo
/metricsPrometheus metricsNo

Configure your load balancer or Kubernetes liveness/readiness probes to use /health.


DuraGraph exposes Prometheus metrics at /metrics. See Observability for dashboard configuration and key metrics.