# Concepts

> Workspace, project, environment, resource, target — what each one is and how they nest

URL: https://pier.run/docs/concepts

Pier organises everything in this tree. Every command and every line of `pier.yaml` is an
operation on one of these levels.

```text
Workspace   acme-inc                       billing and access
└── Project   acme                         one system, one pier.yaml
    ├── Environment   prod                 a complete, isolated set of resources
    │   ├── App        api                 ├── target  primary    https://k7f2m9.app.pier.run
    │   │                                  └── target  canary     https://q2d8xa.app.pier.run
    │   ├── Site       www                 └── target  primary    https://m3p1zr.site.pier.run
    │   ├── Postgres   main                one instance
    │   ├── Bucket     uploads
    │   └── Volume     data
    └── Environment   staging              its own api, www, main — nothing shared with prod
```

| Level           | Is                                                                                 | Boundary of                         | You pick it with                                            |
| --------------- | ---------------------------------------------------------------------------------- | ----------------------------------- | ----------------------------------------------------------- |
| **Workspace**   | the account: members, roles, subscription, overage cap                             | billing and access                  | `-w`, `pier workspaces use`                                 |
| **Project**     | one system — an API, its site, its database; one `pier.yaml`                       | configuration and history           | the `pier.yaml` in the directory, `-p`, `pier projects use` |
| **Environment** | a complete declaration of resources and variables — `prod`, `staging`              | isolation: network, data, variables | `pier use`, `-e`                                            |
| **Resource**    | an app, site, Postgres, bucket or volume declared in an environment                | the thing you name in `pier.yaml`   | its name: `api`, `main`                                     |
| **Target**      | a running instance of an app or site: its own hostname, plan, deploy history, logs | what runs                           | a ref: `api`, `api/canary`                                  |

## Workspace

A workspace holds billing, members and roles, and nothing else: one subscription, one
overage cap, one set of members (owner, admin, developer, viewer). Most accounts have one
workspace, so its name is rarely typed. `pier whoami` shows which workspace a session is in.

## Project

A project is one system and one `pier.yaml`. The file links a directory to the project:
`pier` finds the project by walking up from the current directory to the nearest
`pier.yaml` and reading its `project:` key, so commands run inside the repository need no
project flag. A project contains environments and nothing else.

## Environment

**The environment is the unit of work.** Every command that reads or changes something
does so in the current environment. `pier use staging` sets it; `-e staging` overrides it
for one command. `pier ls` lists what the environment contains; `pier deploy` rolls what
changed in it.

An environment is a **complete, independent declaration**. `staging` does not inherit
from `prod`: each `environments.<name>` block in `pier.yaml` lists every app, site,
Postgres, bucket, volume and variable it has. This repeats configuration between
environments, and in return the block is a complete description of what runs in that
environment. Environments do not share a network, a database or a variable.

```yaml title="pier.yaml"
environments:
  prod:
    env: { LOG_LEVEL: { value: info } }
    apps: [{ name: api, build_context: ., targets: [{ name: primary, plan: app-m }] }]
    postgres: [{ name: main, targets: [{ name: primary, plan: pg-s }] }]
  staging:
    env: { LOG_LEVEL: { value: debug } }
    apps: [{ name: api, build_context: ., targets: [{ name: primary, plan: app-s }] }]
    postgres: [{ name: main, targets: [{ name: primary, plan: pg-s }] }]
```

## Resource

A resource is what you declare and name inside an environment: **apps** (containers Pier
builds or pulls), **sites** (static files served from the edge), **Postgres** (instances),
**buckets** (objects), **volumes** (block storage mounted into an app). Custom **domains**
attach to an app or site target. Resources in one environment can reference each other,
for example an app variable declared as `{ from: postgres.main.url }`. A resource cannot
reference another environment.

## Target

An app or site is a declaration; its **targets** are what run. A target is a named running
instance inside one environment, with its own hostname (`https://<id>.app.pier.run`), plan,
replicas, deploy history, logs and metrics. Most apps have one target, named `primary`,
and are addressed by the app name alone: `pier logs api`. A second target is a second
running copy of the same app, addressed as `api/canary`: for example a `canary` that
tracks a branch, or a `worker` built from a different Dockerfile.

* Every app and site has exactly one **primary** target. It is what `pier info api` and
  the console show when no target is named. `pier promote api/canary` makes another target
  the primary; hostnames and variables are unchanged.
* **Previews** are targets Pier creates automatically. With `previews:` on an app, each
  push to a matching branch runs its own target against the environment's Postgres, and
  the target is removed when the branch is deleted. A preview is a target inside the
  environment, not a new environment.
* Postgres has one target per environment (the instance). Buckets and volumes have none.

## Ref

The grammar every runtime command accepts:

| Ref              | Means                                                 |
| ---------------- | ----------------------------------------------------- |
| `api`            | the app; for a single-target app, its only target     |
| `api/canary`     | one target                                            |
| `api/canary/2`   | one instance of that target (`pier logs`, `pier ssh`) |
| `--type pg main` | breaks a name shared across kinds                     |

## Apply, deploy, staged

`pier.yaml` is the source of truth; two verbs move the platform toward it.

* **`pier apply`** converges *declarations*: creates, changes and removes resources so
  the environment matches the file. It never rolls a workload.
* **`pier deploy`** builds and rolls the targets whose source changed. It implies
  `apply`.
* **`--stage`** on `pier add`, `pier set` and `pier rm` writes the change to `pier.yaml`
  only. Nothing reaches the platform until the next `apply` or `deploy`, so several edits
  can be reviewed and applied as one change.

## Trash

`pier rm` removes a resource from the environment and keeps its data for 30 days. `pier
trash` lists what is recoverable, `pier trash restore` restores it, and `pier trash purge`
(or `--purge` on the removal) deletes the data before the window ends.

## When you say…

| You want                                | In Pier that is                                                                      |
| --------------------------------------- | ------------------------------------------------------------------------------------ |
| a staging copy of production            | a second environment block in `pier.yaml`; `pier copy app api --to staging` seeds it |
| a preview for every pull request        | `previews:` on the app or site: ephemeral targets in the same environment            |
| a canary next to production             | a second target on the app: `pier add target api canary --branch main`               |
| separate databases for prod and staging | a `postgres` entry in each environment; environments never share an instance         |
| a worker and an API from one repo       | two targets with different `dockerfile:` values, or two apps                         |
| one bill for several products           | one workspace, one project per product                                               |
