Skip to content

How Guv fits together

View as Markdown

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

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

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

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.

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.

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.

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.

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 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.

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.