# How Guv fits together

> Workspaces, projects, environments, services, databases and domains, and how they relate.

If you have used Railway or Heroku, this will feel familiar.

```text
Workspace           billing, members, sign-in rules
└─ Project          one product or one repository
   ├─ Environments  production, staging, pr-123 …  (each has its own network and secrets)
   │  ├─ Services   web apps, APIs, workers and cron jobs
   │  ├─ Databases  Postgres, Valkey, MySQL
   │  ├─ Volumes    persistent disks
   │  └─ Domains    generated and custom
   └─ Shared variables
```

## Workspace

A workspace holds billing, members and agent tokens. Every member signs in with a passkey; Guv does not offer SMS codes. Roles are Owner, Admin, Developer, Viewer, Billing and Agent.

## Project

A project is one product, usually one repository (a monorepo is fine). It has a region (`lon1`, London), a residency setting and a data classification:

| Classification | What changes |
| --- | --- |
| `standard` | The defaults. |
| `personal-data` | Stricter log handling. |
| `special-category` | Health, care and similar data. Personal data is masked in logs, masking is mandatory on database branches, nothing from the project is sent to a third-party AI model, and the project can run on dedicated hosts. |

## Environments

Each environment is a full, isolated copy of the project, with its own private network, variables and secrets. Production can be **protected**, so that changes by agents, or by people without an approver role, wait for a human approval.

**Preview environments** are created for pull requests, with a time limit and their own spend cap. Their databases can be branches of staging, with personal data masked.

## Services

A service is something that runs your code:

- a **web service** has a `port` and gets a public URL;
- a **private service** has `private: true` and is reachable only inside the environment at `<name>.guv.internal`;
- a **worker** has no port and no schedule;
- a **cron job** has a `cron` schedule, in UK time unless you say otherwise.

Services are built from your repository (Guv detects the stack), from a Dockerfile, or from a prebuilt image. You are billed on what each service actually uses, per second, not on what you reserve.

## Databases and volumes

Managed Postgres comes with backups and point-in-time recovery. Databases are private unless you explicitly make them public, and connection strings reach your services as references such as `${{ databases.main.url }}`, so nobody has to copy a password.

Volumes are persistent disks on fast local storage, backed up. They can grow but not shrink.

## Variables, secrets and references

- **Variables** are plain values that project members can read.
- **Secrets** are write-only: once set, nobody can read them back, including you. Reference them as `secret://name`.
- **References** such as `${{ services.api.internal_host }}` are filled in at deploy time.

If a variable's value turns up in your built client code, Guv blocks the deploy unless the variable is explicitly marked `public`. This stops the classic mistake of shipping a secret key to every visitor.

## Everything is the same API

The dashboard, the CLI, the MCP server and Guv's own AI operations team all use one public API. Every change can be previewed as a plan with `dry_run`, and every action is recorded in the audit log with who, or which agent, did it.
