Skip to main content
Strait is designed as a single Go binary that can be deployed in various environments, from local development with Docker Compose to production on Fly.io or Kubernetes.

Architecture Overview

Production deployment consists of the following services:

Region Strategy

  • Primary region: iad (Ashburn, Virginia) — co-located with the database for lowest latency.
  • Edge regions: lhr (London), gru (São Paulo) — for faster API responses globally.
  • Sequin: Single instance in iad only. CDC requires a persistent WAL connection and must run next to the database. Multiple instances would cause duplicate event processing.

Secrets Management

All environment variables are managed via Doppler under the strait project with three configs:

Local Development

Fly.io Integration

Secrets are synced from Doppler to Fly.io via the Doppler-Fly integration. When you update a secret in Doppler, it automatically propagates to Fly machines.

Operation Modes

Strait can run in three different modes, controlled by the --mode flag or the MODE environment variable:
  • api: Runs only the HTTP API server. Stateless and can be scaled horizontally.
  • worker: Runs only the job execution engine. Scales based on queue depth.
  • all (Default): Runs both the API and the worker in a single process. Ideal for small deployments or development.

Infrastructure Requirements

Strait requires the following backing services:
  • PostgreSQL 18: Primary data store and job queue (uses SKIP LOCKED).
  • Redis 8: Used for pub/sub, SSE streaming, and CDC event publishing.
  • Sequin: Required for Change Data Capture (CDC) from the Postgres WAL.

Docker Compose (Development)

For local development, use apps/strait/docker-compose.yml:

Fly.io Deployment

Project Structure

Deploying the Main App

The Dockerfile uses a multi-stage build: Go compile on Alpine, then copy the binary to a minimal runtime image (~16 MB).
The deploy workflow runs preflight checks (go vet, golangci-lint, go build, go test) before pushing to Fly. If any check fails, the deploy is aborted.

Deploying Sequin

Sequin uses the official sequin/sequin:latest Docker image — no build step needed.
Sequin requires the following secrets set on Fly (managed via fly secrets set):

CI/CD

The GitHub Actions workflow (.github/workflows/deploy.yml) automatically deploys to Fly when:
  1. Code is pushed to master
  2. Changes are in apps/strait/**
  3. All required workflows pass (Test, Lint, Security)
Required GitHub secret: FLY_API_TOKEN — generate a deploy token scoped to the app:

Production Configuration

Required Environment Variables

See Environment Variables for the full reference.

Scaling Strategy

For high-traffic production environments, it is recommended to separate the API and worker processes:
  1. Scale API: Increase the number of instances running in api mode to handle more concurrent HTTP requests.
  2. Scale Workers: Increase the number of instances running in worker mode to process more jobs from the queue. Since workers use SKIP LOCKED, they can safely compete for jobs without double-processing.

Graceful Shutdown

Strait implements graceful shutdown for both the API and the worker:
  • API: Stops accepting new requests and waits for active requests to finish (up to the configured timeout).
  • Worker: Stops dequeuing new jobs and waits for currently executing jobs to complete or reach a checkpoint before exiting.
Always use a process manager or orchestrator (like Kubernetes or Fly.io) that respects SIGTERM signals to ensure no jobs are abruptly interrupted.

Quick Reference