Skip to main content
Every deployment on ezForge goes through a multi-stage pipeline designed for reliability and security. Understanding it helps you build servers that deploy smoothly and recover quickly from failures.

Pipeline stages

ezforge deploy


1. Build ──────── Dockerfile → OCI image


2. Scan ───────── Trivy vulnerability scan


3. Push ───────── ezForge private registry


4. Provision ──── Fly.io Machines (Firecracker microVM)


5. Health check ─ GET {healthCheckPath} → 200 required


6. Traffic swap ─ Live traffic routed to new machine


7. Cleanup ─────── Old machine stopped (kept 1 hour)
If any stage fails, the pipeline stops and (by default) auto-rollback is triggered.

Stage details

1. Build

ezForge builds your container image from the Dockerfile in your project root. You can skip this stage by providing a pre-built OCI image URI:
ezforge deploy --image registry.fly.io/my-org/my-server:v1.2.0
Build uses BuildKit with layer caching to minimize build times.

2. Trivy vulnerability scan

Every image is scanned with Trivy before deployment. Results are:
  • Logged to the deployment record (visible in the dashboard and via ezforge servers status)
  • HIGH severity CVEs flag the deployment with a warning but do not block it
  • CRITICAL severity CVEs block the deployment; the pipeline stops and auto-rollback is triggered
Scan results are available per-deployment in the API response:
{
  "trivyScanResult": {
    "critical": 0,
    "high": 0,
    "medium": 2
  }
}

3. Push to registry

The built and scanned image is pushed to the ezForge private registry. Images are namespaced per-project for isolation.

4. Provision microVM

ezForge creates or updates a Fly.io Machine running your container in a Firecracker microVM. Each server gets its own isolated VM — no shared processes, no shared filesystem, no shared network with other customers. Machine configuration comes from ezforge.toml or server settings:
  • cpu: shared-1x, shared-2x, performance-1x
  • memoryMb: 256, 512, 1024, 2048
  • Region: one of ord, iad, lax, ams, syd

5. Health check

After the VM starts, ezForge polls GET {healthCheckPath} (default: /healthz) until it returns HTTP 200 or the timeout is reached (default: 30s). Your server must implement this endpoint:
// Node.js
app.get('/healthz', (_req, res) => {
  res.status(200).json({ status: 'ok' });
});
# Python
@app.route('/healthz')
async def health():
    return {'status': 'ok'}

6. Traffic swap

Once the health check passes, ezForge atomically routes all incoming traffic to the new machine. The swap is near-instantaneous; in-flight requests on the old machine are drained gracefully. Your server subdomain ({slug}.mcp.ezforge.ai) always points to the currently healthy deployment.

7. Cleanup

The previous machine is stopped (not deleted) immediately after the traffic swap. It remains in stopped state for 1 hour for emergency recovery, then is permanently deleted.

Auto-rollback

If the health check fails or times out, ezForge automatically:
  1. Stops the new machine
  2. Restores the previous deployment (same process as a manual rollback)
  3. Sets the deployment status to failed
Auto-rollback is enabled by default. Disable it with:
ezforge deploy --no-rollback
Or in ezforge.toml:
[deploy]
auto_rollback = false

Manual rollback

Roll back to any of the last 10 deployments at any time:
ezforge rollback my-server --version dep_abc123
See ezforge rollback for details.

Deployment retention

By default, ezForge keeps the last 10 deployments per server (3 on Free), not counting the currently active one. Older deployments are automatically cleaned up. You can adjust this:
[deploy]
retention_count = 5   # keep fewer to save storage

Zero-downtime deploys

ezForge achieves zero-downtime deploys through:
  • Health check gate before traffic swap
  • Graceful drain of in-flight requests on the old machine
  • Atomic subdomain routing switch
  • Auto-rollback if anything goes wrong

Deployment status values

StatusDescription
pendingQueued, pipeline not yet started
buildingBuild/scan/push in progress
runningSuccessfully deployed and serving traffic
failedPipeline failed; auto-rollback triggered
rolled_backSuperseded by a newer deploy or rollback