---
url: /guide/how-it-works.md
description: >-
  The duploy.toml config model, staged edits, builds, rolling deploys and
  internal networking.
---

# How Duploy works

## The file is the truth

The source of truth for a project is `duploy.toml` in your repository. Duploy
parses and validates it, then materializes services and databases from it.

* **A push syncs the project.** The webhook from your git provider re-reads
  the file; nothing needs to be clicked.
* **Panel edits go back to the repository.** Changing a port, a domain or a
  replica count in the panel stages the edit. You review the combined diff
  once, and Duploy writes it as a commit or a pull request. The file and the
  running project never drift apart.
* **Secret values never live in the file.** The file only says that a key is a
  secret; the value is stored encrypted and written with
  `duploy secret set` or in the panel.

An invalid file is rejected as a whole, with the path and line of each
problem. Nothing from it is applied.

## Builds

A service with a `path` or `repo` source is built from its Dockerfile with
BuildKit and pushed to Duploy's built-in registry.

Services that share the same repository, branch, path, Dockerfile and build
args form one **build unit** and are built once. A push only rebuilds the
units whose files changed. To run a build by hand: `duploy build [service]`.

## Deploys

A deploy starts when a build succeeds, when a push changes the config of a
service that needs no build, when you run `duploy deploy`, or when you roll
back.

* **Rolling update.** A new instance has to pass its health check before the
  old one is stopped, so a broken release never takes the service down. If the
  new instance never becomes healthy, the deploy fails and the old one keeps
  serving.
* **Recreate for volumes.** A service with a volume can only have one writer,
  so it is stopped first and started again on the new release. Expect a short
  gap.
* **Exact rollback.** Every deploy keeps the image and the config it ran with.
  `duploy rollback <deploy-id>` starts a new deploy from that snapshot.

## Networking

Each project gets its own private network. Services and databases reach each
other by name:

| From a service in project `shop` | Resolves to |
|---|---|
| `api` | the `api` service of the same project |
| `api.shop.internal` | the same, fully qualified |
| `db.shop.internal` | the managed database `db` |

Only services with `domains` are reachable from the internet, through
Duploy's edge proxy. Other projects' networks are not reachable at all.

## Events, not polling

Everything that happens is an event: builds, deploys, health changes,
backups, certificates. The panel and `duploy events` stream them live, and
`duploy until` waits for one, which is how CI gates on a deploy. See
[CI and automation](/guide/ci).
