Architecture
VersionGate is a Fastify API plus a background worker, backed by PostgreSQL via Drizzle ORM and Redis event pub/sub. It orchestrates the Docker CLI and rewrites Nginx upstreams to switch traffic atomically.
Deployment pipeline
Every deploy runs the same locked, crash-safe sequence:
POST /api/v1/deploy { projectId }
│
├─ Acquire lock → 409 if a deploy is already running
├─ Git clone / pull → fetch the configured branch
├─ Pick color & port → ACTIVE=BLUE ? use GREEN : use BLUE
├─ DB: DEPLOYING → crash-safety marker
├─ docker build → versiongate-<name>:<timestamp>
├─ docker run → <name>-blue | <name>-green
├─ Health check → GET :port/health (retries + latency cap)
│ ├─ PASS → Nginx upstream rewrite + reload
│ └─ FAIL → stop + rm container, DB: FAILED
├─ DB: new=ACTIVE, old=ROLLED_BACK
├─ Stop + remove old container
└─ Release lock (always)Blue-green slots
Each environment owns two container slots. The active slot serves traffic on basePort or basePort + 1; deploys always target the idle one. Nginx flips the upstream only after the new container is confirmed healthy, so there is no moment where traffic hits a cold or broken build.
Status lifecycle
PENDING → DEPLOYING → ACTIVE
│ │
└→ FAILED └→ ROLLED_BACK (after next deploy or rollback)Crash recovery
On startup, reconciliation finds any deployment stuck in DEPLOYING, stops and removes its containers, and marks it FAILED. Records marked ACTIVE are verified against docker inspect — if the container is not running, they are marked failed too. Only then does the engine accept requests.