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

# How deploys work

> Follow a commit from push to live URL, and trigger a deploy by hand.

A deployment is one attempt to bring **one service** live at one commit. Every service in a
project tracks its own state, so a push to a repository declaring three services starts
three deployments that build, go live and fail independently. Each runs the same steps and
records what happened in an append-only event log.

```mermaid theme={"system"}
flowchart LR
  q["queued"] e1@--> b["building"]
  b e2@--> d["deploying"]
  d e3@--> h["healthy"]
  e1@{animation: slow}
  e2@{animation: slow}
  e3@{animation: slow}
  classDef step fill:#0D857714,stroke:#0D8577,stroke-width:1.5px
  classDef done fill:#2DD4BF22,stroke:#0D8577,stroke-width:2px
  class q,b,d step
  class h done
```

| Step | What happens |
| - | - |
| `queued` | The deployment row exists and is about to start. |
| `building` | The service is built and the output streams into the logs. A service running a prebuilt image skips this step. |
| `deploying` | The image is ready. The service starts and slipway waits for readiness. |
| `healthy` | The service is ready and its public URL is live. |

After `healthy`, a deployment ends in one of three states.

| Status | When |
| - | - |
| `superseded` | A newer healthy deployment of the same service on the same branch took over. Exactly one deployment per service is ever live. |
| `cancelled` | You cancelled it, or a new commit arrived for the same branch mid-build. |
| `failed` | A build, image pull or secret lookup failed, a container kept crashing, a `dependsOn` dependency never came up, or a web service never listened on its declared port. The reason is on the deployment. |

See [Statuses and events](/reference/statuses-and-events) for every value, and
[Troubleshooting](/deploys/troubleshooting) when one goes wrong.

![A service's Logs tab during a deploy](https://mintcdn.com/slipway/XQ-cfaZA6zvMJ_Pi/images/deployments/detail.png?fit=max\&auto=format\&n=XQ-cfaZA6zvMJ_Pi\&q=85\&s=0686d7e55e9ed50cb63d4eff52a5ae9e)

## One push, one deployment per service

A push produces a deployment for every service it ships, and they run in parallel. What
that buys you:

* **Failure stays local.** If `web`'s build breaks, `api` and `db` stay healthy and keep
  serving. The project reads as degraded, and the failure names the service that broke.
* **Every service has its own history.** Its deploys, its logs, its events and its
  rollbacks are its own — a service page shows only its own runs.
* **Rollback and redeploy are per service.** Rolling `api` back to yesterday's commit
  leaves `web` exactly where it is.

The push is still reported as one thing upstream: a pull request gets one commit check and
one comment listing every service's URL, not one per service.

## Triggers

| Trigger | Source | Behaviour |
| - | - | - |
| Push | A push to the tracked branch | Deploys only if auto-deploy is on for that service. |
| Pull request | A PR opened or updated against a tracked branch | Spawns or updates a [preview](/previews/pr-previews). |
| Manual | A button in the console, or the CLI | Deploys on demand. |

Every row in a project's deploy history names who caused it and which branch it deployed.

## Auto-deploy on push

A project created from a single repository has auto-deploy **on**: a push to the tracked
branch rebuilds it in place and cancels any in-flight deploy for the same branch, so the
newest commit wins.

Sources added to a multi-repo project default to **off**, so a push leaves the deploy
pinned at the commit you deployed. Turn it on per source under the project's
**Settings → General**.

The project header shows an "auto-updates on push" or "pinned" chip, so which behaviour
you are getting is always visible.

To deploy only when relevant files change, see [Monorepos](/deploys/monorepo).

## Manual deploys

| Action | What it does |
| - | - |
| Deploy | Deploys the tracked branch's latest commit, or an older commit on it. Scoped to the tracked branch. |
| Redeploy | Re-runs the build and deploy at the currently deployed commit, on the same URL. Use it to pick up a changed base image or secret, or to retry a transient failure. |
| Deploy latest | On a project: re-resolves every tracked ref to its newest commit and redeploys the whole project. |

## Build caching

Builds are content-addressed. The image tag is derived from the commit plus a hash of the
build inputs (`rootDir`, `dockerfilePath`, `dockerTarget`, `buildArgs`) and of the service's
`env`, since the build can read it. If an earlier deploy of the same commit produced the same
inputs, slipway reuses the cached image and skips the build, which is what makes a redeploy
cheap. Changing an environment value and redeploying builds a fresh image, and the steps
that read the value run again.

When a build does run, it reuses the layer cache from that service's previous build, so
only changed layers are rebuilt. The cache is shared per **repository** rather than per
project, so any project deploying the same repo starts warm.

### Rebuilding without the cache

Open the dropdown beside **Deploy latest** and choose **Rebuild without cache**. Use it
when a base image moved under a floating tag, or a build looks stale in a way you cannot
explain.

This runs every build step again **and** ignores the image slipway already holds for the
current commit. Both halves matter: without the second, slipway would find a finished image
for that commit and skip the build entirely.

> [!NOTE]
>
> In a project with several repositories, the dialog lets you choose which to rebuild. Cold
> building every repo when one is misbehaving costs minutes for nothing.

## Cutover

For a public service, slipway waits for readiness, makes the URL live, and records a
`cutover` event. When a newer build for the same branch reaches `healthy`, the previous one
becomes `superseded`.

If the new build exits as soon as it starts, cannot be pulled, or nothing listens on the
service's declared port within five minutes, the deploy fails instead. The reason is
recorded on the deployment and shown on its row in the Events feed, together with the
commit that is still live. Nothing is superseded by a build that never answered.

What a failed deploy leaves at the URL is a per-service setting, **Settings → Failed
deploys**:

* **Keep the last working version serving** (the default): the version that was serving
  stays up and the service is rolled back onto it, so a broken push never takes a working
  service down. While the two differ, the service header and the project grid name the
  commit that is serving next to the one that failed.
* Off: the previous version is taken down as well, so the failure shows at the URL instead
  of hiding behind old code. Use it for a staging service, or when old code must not keep
  running after a migration.

The hostname does not change across deploys, so traffic hands over without anyone updating
a link.

## Teardown

A live deployment has a **Tear down** action that reclaims just that source's services
and URLs, leaving siblings untouched. Tearing down the whole project from its Danger zone
removes every service, every URL and the project's namespace.

Either way the deployment rows stay in history.

slipway also tears down automatically when a newer deploy supersedes a branch. If the
platform restarts mid-deploy, that deployment is marked `failed` and can be redeployed from
its page.

## Appendix: glossary

| Term | Meaning |
| - | - |
| Cutover | The moment a public URL starts serving a new build. |
| Supersession | Marking a previous deployment replaced once a newer one is healthy. |
| Build inputs | The fields hashed into the image tag: `rootDir`, `dockerfilePath`, `dockerTarget`, `buildArgs` and the service's `env`. |
| Tracked branch | The branch a source deploys from, set per source. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.