> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ezforge.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Deployment Pipeline

> How ezForge builds, scans, deploys, and rolls back your MCP servers

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:

```bash theme={null}
ezforge deploy --image registry.fly.io/my-org/my-server:v1.2.0
```

Build uses [BuildKit](https://docs.docker.com/build/buildkit/) with layer caching to minimize build times.

### 2. Trivy vulnerability scan

Every image is scanned with [Trivy](https://trivy.dev) 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:

```json theme={null}
{
  "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](https://fly.io/docs/machines/) 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:**

```typescript theme={null}
// Node.js
app.get('/healthz', (_req, res) => {
  res.status(200).json({ status: 'ok' });
});
```

```python theme={null}
# 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:

```bash theme={null}
ezforge deploy --no-rollback
```

Or in `ezforge.toml`:

```toml theme={null}
[deploy]
auto_rollback = false
```

## Manual rollback

Roll back to any of the last 10 deployments at any time:

```bash theme={null}
ezforge rollback my-server --version dep_abc123
```

See [ezforge rollback](/cli-reference/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:

```toml theme={null}
[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

| Status        | Description                               |
| ------------- | ----------------------------------------- |
| `pending`     | Queued, pipeline not yet started          |
| `building`    | Build/scan/push in progress               |
| `running`     | Successfully deployed and serving traffic |
| `failed`      | Pipeline failed; auto-rollback triggered  |
| `rolled_back` | Superseded by a newer deploy or rollback  |
