Configuration & Deployment
Deployment options
Orch8 ships as a single static binary. No JVM, no Node.js runtime, no cluster to manage. Three deployment paths:
# 1. Binary — download from GitHub Releases (linux-amd64, linux-arm64, darwin-*)
./orch8-server --config orch8.toml
# 2. Docker — published to GitHub Container Registry on every release tag
docker run -d \
-e ORCH8_DATABASE_URL=postgres://user:pass@host:5432/orch8 \
-p 8080:8080 \
ghcr.io/orch8-io/orch8-server:latest
# 3. Helm (Kubernetes)
helm repo add orch8 https://orch8-io.github.io/helm-charts
helm install orch8 orch8/orch8 \
--set database.url=postgres://user:pass@host:5432/orch8 \
--set engine.encryptionKey=<64-hex-chars> # optional: encryption at restThe Helm chart includes a Deployment with liveness/readiness probes, Service (HTTP 8080 + gRPC 50051), ConfigMap, Secret for database URL and encryption key, optional ingress with TLS, and HPA autoscaling support.
Configuration
Configuration via TOML file with environment variable overrides. All env vars use the ORCH8_ prefix.
# orch8.toml
[database]
backend = "postgres" # or "sqlite" for local dev
url = "postgres://user:pass@localhost:5432/orch8"
max_connections = 64
run_migrations = true
[engine]
tick_interval_ms = 100
batch_size = 256
max_concurrent_steps = 128
shutdown_grace_period_secs = 30
stale_instance_threshold_secs = 300
encryption_key = "" # set to 64 hex chars to enable AES-256-GCM at rest
[api]
http_addr = "127.0.0.1:8080"
grpc_addr = "127.0.0.1:50051"
api_key = "" # set to require Authorization: Bearer <key>
require_tenant_header = false
rate_limit_rps = 0 # 0 = unlimited
[logging]
level = "info"
json = true
[engine.webhooks]
urls = ["https://your-app.com/webhooks/orch8"]
timeout_secs = 10
max_retries = 3Environment variables
All configuration can be set via environment variables. TOML file values are overridden by env vars when both are present.
| Variable | Default | Description |
|---|---|---|
| ORCH8_STORAGE_BACKEND | postgres | Storage backend: postgres or sqlite |
| ORCH8_DATABASE_URL | — | PostgreSQL connection string (required) |
| ORCH8_DATABASE_MAX_CONNECTIONS | 64 | Database connection pool size |
| ORCH8_DATABASE_SEARCH_PATH | (empty) | PostgreSQL search_path override |
| ORCH8_HTTP_ADDR | 127.0.0.1:8080 | HTTP API listen address |
| ORCH8_GRPC_ADDR | 127.0.0.1:50051 | gRPC listen address |
| ORCH8_CORS_ORIGINS | (empty) | Comma-separated CORS origins |
| ORCH8_LOG_LEVEL | info | Log level: debug, info, warn, error |
| ORCH8_LOG_JSON | false | Emit logs as JSON |
| ORCH8_TICK_INTERVAL_MS | 100 | Scheduler tick interval in ms |
| ORCH8_CRON_TICK_SECS | 60 | Cron evaluation interval in seconds |
| ORCH8_BATCH_SIZE | 256 | Instances claimed per tick |
| ORCH8_MAX_CONCURRENT_STEPS | 128 | Max concurrent step executions |
| ORCH8_MAX_INSTANCES_PER_TENANT | 0 | Per-tenant instance limit (0 = unlimited) |
| ORCH8_EXTERNALIZE_THRESHOLD | 0 | Bytes — externalize step outputs above this size (0 = disabled) |
| ORCH8_WEBHOOK_URLS | (empty) | Comma-separated webhook URLs |
| ORCH8_ENCRYPTION_KEY | (empty) | 64 hex chars — enables AES-256-GCM encryption at rest for context fields |
| ORCH8_API_KEY | (empty) | If set, all requests must include Authorization: Bearer <key> |
| ORCH8_REQUIRE_TENANT_HEADER | false | Enforce X-Tenant-Id header on every request |
| ORCH8_MAX_CONCURRENT_REQUESTS | 0 | Global API rate limit (0 = unlimited). Alias: ORCH8_RATE_LIMIT_RPS |
Observability
Prometheus metrics at /metrics and structured JSON logging via the tracing crate.
Counters
- ✓orch8_instances_claimed — instances picked up by scheduler
- ✓orch8_instances_completed — instances finished successfully
- ✓orch8_instances_failed — instances that failed
- ✓orch8_steps_executed — total steps run
- ✓orch8_steps_failed — steps that errored
- ✓orch8_steps_retried — steps retried after failure
- ✓orch8_signals_delivered — signals processed
- ✓orch8_rate_limits_exceeded — rate limit deferrals
- ✓orch8_webhooks_sent / orch8_webhooks_failed
Histograms
- ✓orch8_tick_duration_seconds — time per scheduler tick
- ✓orch8_step_duration_seconds — time per step execution
- ✓orch8_instance_processing_seconds — total processing time per instance
Gauges
- ✓orch8_queue_depth — current scheduled instances
- ✓orch8_active_tasks — currently executing steps
Graceful shutdown
On SIGINT or SIGTERM, the engine stops accepting new work, waits for in-flight steps to complete (up to shutdown_grace_period_secs), persists all state, and exits. Running instances are recovered on next startup.
Horizontal scaling
Multiple worker nodes can connect to a shared PostgreSQL instance. Work distribution uses SELECT ... FOR UPDATE SKIP LOCKED — no separate coordinator needed. Each node claims and processes its own batch of instances.
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Worker 1 │ │ Worker 2 │ │ Worker N │
└────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │
└─────────────┼─────────────┘
│
┌────────┴────────┐
│ PostgreSQL │
│ (shared state) │
└─────────────────┘