# Preview deployments

> A running target for every branch that matches a pattern, against the environment's shared Postgres, removed when the branch is

URL: https://pier.run/docs/guides/preview-deployments

**Goal.** Every `feat/*` branch pushed to `acme`'s repository runs its own copy of `api`
at its own hostname, using `prod`'s Postgres, and is removed when the branch is deleted.
Requires a connected repository ([Deploy from GitHub](/docs/guides/deploy-from-github)).

### Declare the policy

```yaml title="pier.yaml"
environments:
  prod:
    apps:
      - name: api
        build_context: ./api
        previews:
          branch_pattern: "feat/*"
          plan: app-s
          ttl_hours: 72
          max_targets: 5
          env:
            LOG_LEVEL: { value: debug }
        targets:
          - name: primary
            plan: app-s
            deploy:
              branch: main
```

```bash
pier apply
```

| Key              | Means                                                            |
| ---------------- | ---------------------------------------------------------------- |
| `branch_pattern` | glob a branch must match to get a preview                        |
| `plan`           | size of each preview (apps only)                                 |
| `ttl_hours`      | a preview with no push for this long is removed                  |
| `max_targets`    | at most this many previews at once; older ones are removed first |
| `env`            | variables set on every preview, on top of the app's              |
| `enabled: false` | keep the policy, stop creating previews                          |

### Push a branch

A push to `feat/checkout` builds the branch and runs it as the target `api/feat-checkout`,
with its own hostname and `prod`'s `DATABASE_URL`:

```bash
pier ls apps
pier logs api/feat-checkout
pier info api/feat-checkout
```

The hostname appears in `pier info` and in the pull request's checks.

### Removal

Deleting the branch or closing the pull request removes the target, as does reaching
`ttl_hours` without a push. `pier rm target api/feat-checkout` removes one explicitly.

## Behaviour

* A preview is a **target inside the environment**, not a new environment: it shares the
  Postgres, buckets and variables of `prod`. Use a [staging environment](/docs/guides/set-up-a-staging-environment)
  when data must be separate.
* A preview is never the primary; `pier promote` does not apply to it. To keep a branch's
  deployment permanently, add a named target: `pier add target api canary --branch feat/checkout`.
* Sites take the same block; a docs or marketing site gets a preview per pull request.

## See also

[Concepts: target](/docs/concepts#target) · [Apps](/docs/resources/apps) ·
[`pier add target`](/docs/cli/reference/add#pier-add-target)
