Skip to main content
Every deploy records the same structured trace: a pre-built image, a rollback, an image tag deploy, a Compose stack and a Git build all produce it. Each step has a status, a start and end time, a duration and a short reason code. A failure names the step that failed and carries the underlying Docker or registry error text instead of a generic message. The trace is stored with the deploy attempt, so it is still there after the deploy ends. It is shown in three places that read the same data:
  • the deploy detail page in the dashboard (the Pipeline trace section of the Build or Image tab)
  • levelrail-cli apps deploys steps <app> <deploy-id>
  • the deploy log stream and download (apps deploys logs), as [trace] lines mixed in with build output

Steps

For Compose, compose_parse and compose_plan (service list and start order) are recorded on every service’s attempt, plus a compose_service row for that service and a depends_on row once the services it waits for are up (started or healthy). Each service pulls, starts and probes under its own deploy attempt. Statuses are running, done, failed, skipped and warning. A step that is retried keeps one row and counts its attempts.

Reading a trace

The command exits when deploy_summary arrives: 0 for done, non-zero for failed. Use --json for one JSON object per step event.

A deploy that fails and leaves the old release serving

Streams

GET /api/v1/apps/{name}/deploys/{deployId}/steps is a server-sent events stream of step rows. A traced step event carries step, key, status, reason, detail, service, started_at, ended_at, duration_ms and attempts; build steps keep their original three fields. The stream replays the stored rows and then follows new ones, because the reconciler keeps writing pull, probe and cutover steps after the deploy request itself has finished. GET .../logs and .../logs/download include the same steps as [trace] lines. Attempts that were recorded before traces existed still show the short two point summary.

Settings

All thresholds are environment variables on the control plane.

Limits

  • Docker daemon events are matched to a deploy by container name, which is unique per image, not by a label: adding a label would change the container config and force a recreate. They are recorded for the local node only. A node reached over the agent transport reports a coarse container_create step without per-layer pull progress.
  • A deploy refused before an attempt exists (for example a registry error while resolving an image tag in a trigger request) is returned to the caller and has no trace.
  • deploy-spec fan-out and the multi-service webhook path do not create deploy attempts yet, so they have no trace. The Compose deploy endpoint and one-click templates do.
Last modified on October 16, 2026