# Read a deployment and its build log

> Follow a deployment as it builds and starts, read the end of its build log, and check the health of each replica.

Source: https://docs.coritan.com/apps/read-a-deployment/

In the dashboard:

- /dashboard/apps/…/deployments: https://www.coritan.com/dashboard/apps

Read a deployment to follow it while it builds and starts, to find out why it failed, and to check the health of each of its replicas. Each deployment has its own page in the dashboard, and the API returns the same facts. Every member of an organization can read its apps' deployments.

## Before you begin

- In the [dashboard](https://www.coritan.com/dashboard/apps), open the app. Through the API, find the deployment's ID in the app's history ([List deployments](/apps/deploy-an-app/#list-deployments)). The five newest also come with the app itself.
- [Deployments](/apps/how-apps-work/#deployments) explains what each status means.

## Open a deployment

1. Open the app from **Apps** and select the **Deployments** tab.
2. Select the deployment's row, or **Open deployment** in the menu at the end of it.

When you start a deployment in the dashboard, its page opens on its own. **All deployments** goes back to the list. While the deployment is on its way, the page reads it again every few seconds, and the build log follows the build.

## What the page shows

The header
: The first line of the commit message, or what the deployment was, with its status and **Current** when it serves the app. Under it are its short ID with **Copy deployment ID**, the short commit or the branch, what started it, such as `Push to main`, and when. **Roll back to this…** and **Cancel deployment…** appear when you can use them.

Its progress
: While it is on its way, a bar says what it is doing, such as `Waiting for a builder`, `Building` or `Starting replicas`, and how long it has taken so far.

How it ended
: `The deployment failed` with the reason, `The deployment was cancelled`, or `A newer deployment replaced this one`. A deployment that went live without a region shows `It went live without every region` with the region it left out and why.

**Build log**
: The end of the build log ([The build log](#the-build-log)).

**Replicas**
: Every replica the deployment has had ([Replicas](#replicas)).

**Details**
: **Source**, **Started by**, **Branch or tag**, **Commit** and **Author** for a git deployment, and **Image** and **Digest** once it has an image. **Regions** lists where it runs. **Build** gives the build's status, how it built (`From its Dockerfile` or `Detected by the builder`) and the attempt when it took more than one, and **Build time** how long it took. **Created**, **Ready** and **Ended** give the times.

## The build log

A git deployment keeps the last 64 KB of its build log. The log hides the repository's access token and every secret build value of six characters or more, which appear as `[redacted]`. An image deployment has no build, so it has no log, and a redeploy or a rollback that reuses an image has none either.

The **Build log** card shows the last 40 lines, where a failure usually is. The button at the top of the card, such as `Show all 312 lines`, shows every line that is kept, and **Copy the log lines shown** copies what you see. The card's description says how the build ended and how long it took, such as `Built in 2 min 37 s.`, or `Only the end is kept` when the build wrote more than 64 KB.

## Replicas

The **Replicas** card lists every replica the deployment has had, with its region, such as `Frankfurt (fra)`, its state, when it was last checked, its last error and when it started. A replica that has failed health checks says how many, such as `2 failed checks`.

| State | Meaning |
| --- | --- |
| **Provisioning** | Placed in its region, with its image on the way. |
| **Starting** | Started, and waiting for two health checks in a row to pass. |
| **Healthy** | Passing its health checks, and serving when its deployment is live. |
| **Unhealthy** | Failed its most recent health checks. It keeps serving until it fails three in a row. |
| **Draining** | No longer taking requests. It stops about a minute later. |
| **Stopped** | Stopped. It is removed 30 minutes after it stopped taking requests, unless a rollback starts it again first. |
| **Failed** | Did not start in time, failed three health checks in a row, or was removed after it stopped. |

The API sends each state in lower case, such as `healthy`. A replica's last error says what went wrong, such as `Health check on /healthz: HTTP 500` or `The app did not pass its health check within 10 minutes. Health check on /: the connection failed`.

## Result

You know where the deployment is, and why when it failed. [Troubleshoot Apps](/apps/troubleshooting/) lists the common causes and their fixes.

## Troubleshooting

`Deployment not found` or `This deployment is not on this app`
: The ID belongs to another app's deployment, or to none. Check both IDs, or open the deployment from the app's **Deployments** tab.

The log is empty
: An image deployment has no log (`Image deployments have no build log`), nor does a deployment that reused an image (`Nothing was built for this deployment`). A build that has not started has written nothing yet (`No log yet`).

The log starts partway through
: The build wrote more than 64 KB, and only the end is kept.

## Related

- [Deploy an app](/apps/deploy-an-app/)
- [Roll back to an earlier deployment](/apps/roll-back-a-deployment/)
- [App and deployment fields](/apps/fields/)
- [Troubleshoot Apps](/apps/troubleshooting/)

## With the API

For an organization's app, send the same requests under `/api/v1/orgs/{org_slug}/apps` ([organization apps reference](/api/reference/organizations/organization-apps/#op-get-api-v1-orgs-org-slug-apps-app-uuid-deployments-deployment-uuid)).

### Read a deployment through the API

[`GET /api/v1/client/apps/{app_uuid}/deployments/{deployment_uuid}`](/api/reference/client/apps/#op-get-api-v1-client-apps-app-uuid-deployments-deployment-uuid) returns the deployment with every replica it has had in `replica_list`:

```bash
curl https://api.coritan.com/api/v1/client/apps/3c9e2f4a-8b1d-4f6e-a2c7-5d8b9e0f1a21/deployments/1d7b4e9a-5c2f-4a8e-9d6b-2f8e5a1c7b11 \
  -H "Authorization: Bearer $CORITAN_TOKEN"
```

```json
{
  "deployment": {
    "uuid": "1d7b4e9a-5c2f-4a8e-9d6b-2f8e5a1c7b11",
    "status": "failed",
    "source": "git",
    "trigger": "push",
    "git_ref": "main",
    "git_sha": "9f2c1e7b4a6d8e0f1a2b3c4d5e6f708192a3b4c5",
    "commit_message": "Move the health check to /healthz",
    "commit_author": "Alex Example",
    "image_ref": "registry.example.net/apps/3c9e2f4a-8b1d-4f6e-a2c7-5d8b9e0f1a21:1d7b4e9a-5c2f-4a8e-9d6b-2f8e5a1c7b11",
    "image_digest": "sha256:5b2d0c9e8f7a6b5c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0f9a8b7c6d5e4f3a2b1c",
    "regions": ["fra", "iad"],
    "actor_type": "webhook",
    "error": "Replicas could not start in fra: The app did not pass its health check within 10 minutes. Health check on /healthz: HTTP 404",
    "is_current": false,
    "in_flight": false,
    "can_rollback": false,
    "replicas": {"healthy": 0, "unhealthy": 0, "starting": 0, "total": 0},
    "build": {
      "uuid": "e2a9c4d1-3b5f-4e7a-9c8d-1f2e3a4b5c6d",
      "status": "succeeded",
      "strategy": "railpack",
      "error": null,
      "attempts": 1,
      "log_bytes": 48211,
      "started_at": "2026-09-26T10:05:04Z",
      "finished_at": "2026-09-26T10:07:41Z",
      "created_at": "2026-09-26T10:05:00Z"
    },
    "ready_at": null,
    "promoted_at": null,
    "finished_at": "2026-09-26T10:18:02Z",
    "created_at": "2026-09-26T10:05:00Z",
    "updated_at": "2026-09-26T10:18:02Z",
    "replica_list": [
      {
        "location": "fra",
        "state": "failed",
        "health_failures": 0,
        "last_health_at": null,
        "last_error": "The app did not pass its health check within 10 minutes. Health check on /healthz: HTTP 404",
        "created_at": "2026-09-26T10:07:45Z",
        "drained_at": null
      }
    ]
  }
}
```

The example shows one replica of several. [App and deployment fields](/apps/fields/#deployment) describes every field. These say the most:

The version
: A git deployment has the branch or ref it built and the ID of the commit it checked out. A deployment started by a push also has the commit's message and author. Every deployment that has an image shows its reference and, once known, its digest.

Where it came from
: `source` is `git`, `image`, `redeploy` or `rollback`. `trigger` is `push` for the push webhook, `rollback` for a rollback, and `manual` for a request from you or a member of your organization. `actor_type` is `user` for a person signed in to Coritan, `staff` for a staff console session, `webhook` for a push, and `admin` when Coritan staff started it.

Its progress
: `status`, `in_flight` while it is on its way, `is_current` while it serves the app, and `can_rollback`. `replicas` counts the replicas in `provisioning`, `starting`, `healthy` and `unhealthy`: `starting` counts the first two, and `total` all four.

What went wrong
: When a deployment fails or is cancelled, its `error` says why. A deployment that went live without a region also says so there.

The build
: For a git deployment, its build's `status` (`queued`, `running`, `succeeded`, `failed` or `canceled`), its `strategy` (`dockerfile` or `railpack`), how many `attempts` it took, and when it started and finished. A build that stops reporting is tried once more.

In each replica, `health_failures` counts its failed health checks in a row, and `drained_at` is when it stopped taking requests.

### Read the build log through the API

[`GET /api/v1/client/apps/{app_uuid}/deployments/{deployment_uuid}/log`](/api/reference/client/apps/#op-get-api-v1-client-apps-app-uuid-deployments-deployment-uuid-log) returns the end of the build log:

```bash
curl https://api.coritan.com/api/v1/client/apps/3c9e2f4a-8b1d-4f6e-a2c7-5d8b9e0f1a21/deployments/1d7b4e9a-5c2f-4a8e-9d6b-2f8e5a1c7b11/log \
  -H "Authorization: Bearer $CORITAN_TOKEN"
```

```json
{
  "build": {"uuid": "e2a9c4d1-3b5f-4e7a-9c8d-1f2e3a4b5c6d", "status": "succeeded", "strategy": "railpack"},
  "log": "[builder] Fetching https://github.com/example/web-shop main at 9f2c1e7b4a6d.\n[builder] Checked out 9f2c1e7b4a6d.\n[builder] Planning the build with Railpack.\n...",
  "log_bytes": 48211,
  "truncated": false
}
```

`log` is the text, up to 64 KB. `log_bytes` is how much the build wrote in all, and `truncated` is `true` when that is more than `log` holds. An image deployment answers `{"build": null, "log": "", "log_bytes": 0, "truncated": false}`. The log grows while the build runs, so read it again to see new lines.

## API

- `GET /api/v1/client/apps/{app_uuid}/deployments/{deployment_uuid}`: Get one deployment of an app, with each of its replicas (https://docs.coritan.com/api/reference/client/apps/#op-get-api-v1-client-apps-app-uuid-deployments-deployment-uuid)
- `GET /api/v1/client/apps/{app_uuid}/deployments/{deployment_uuid}/log`: The end of the deployment's build log (secrets redacted as it was written) (https://docs.coritan.com/api/reference/client/apps/#op-get-api-v1-client-apps-app-uuid-deployments-deployment-uuid-log)
- `GET /api/v1/orgs/{org_slug}/apps/{app_uuid}/deployments/{deployment_uuid}`: Get one deployment of an app, with each of its replicas (https://docs.coritan.com/api/reference/organizations/organization-apps/#op-get-api-v1-orgs-org-slug-apps-app-uuid-deployments-deployment-uuid)
- `GET /api/v1/orgs/{org_slug}/apps/{app_uuid}/deployments/{deployment_uuid}/log`: The end of the deployment's build log (secrets redacted as it was written) (https://docs.coritan.com/api/reference/organizations/organization-apps/#op-get-api-v1-orgs-org-slug-apps-app-uuid-deployments-deployment-uuid-log)
