Skip to content

Branching and promoting environments

Branching lets you fork an entire namespace — services, volumes, routing — into a new environment as a single atomic operation. The typical use case is creating an isolated environment for a pull request, then promoting it to production when the PR is approved. Every branch lineage fact is committed to the control plane as durable evidence of where each service revision came from.

When you branch a namespace, Ployz copies service configurations and optionally volumes from a source namespace into a new target namespace. Each resource can be either branched (copied from the source) or fresh (created independently in the target):

  • Branch — the target resource starts from the source’s current revision or volume state.
  • Fresh — the target resource is created independently, with no lineage link to the source.

The default behavior is Branch for services (so they inherit the source’s container spec) and Fresh for volumes (so the PR environment gets a clean data set rather than a live copy of production data).

SubcommandWhat it does
branch previewComputes the branch plan and prints it without making any changes
branch prepareResolves the plan and saves it as a prepared deploy, but does not apply it
branch applyPreviews, plans, and applies in one step
branch apply-preparedApplies a previously prepared branch deploy by its ID

All branch subcommands (except apply-prepared) accept the same arguments:

Terminal window
ployzctl branch preview <source-namespace> <target-namespace> [flags]
ployzctl branch prepare <source-namespace> <target-namespace> [flags]
ployzctl branch apply <source-namespace> <target-namespace> [flags]
FlagDefaultDescription
--service-modebranchDefault mode for services: branch or fresh
--volume-modefreshDefault mode for volumes: branch or fresh
--service NAME=MODEPer-service mode override; repeatable
--volume NAME=MODEPer-volume mode override; repeatable

Use --service and --volume to override the mode for individual resources:

Terminal window
ployzctl branch apply production pr-42 \
--service-mode branch \
--volume-mode fresh \
--volume db=branch \
--service worker=fresh

In this example, the db volume is cloned from production (copy-on-write, instant), while the worker service gets a fresh empty instance instead of inheriting the production spec.

Typical workflow: preview → prepare → apply-prepared

Section titled “Typical workflow: preview → prepare → apply-prepared”

For production environments, use the three-step workflow to separate the planning phase from the apply phase. This lets you inspect the plan and apply it later — for example, after a CI check passes — without the plan becoming stale:

Compute the plan and verify what will be created in the target namespace.

Terminal window
ployzctl branch preview production pr-42 \
--service-mode branch \
--volume-mode fresh

The preview shows which services will be created, which volumes will be cloned or freshly provisioned, and which machines will participate.

Resolve and save the plan as a prepared deploy. The command prints the prepared_deploy_id.

Terminal window
ployzctl branch prepare production pr-42 \
--service-mode branch \
--volume-mode fresh

The prepared deploy is stored in the control plane and has a TTL. It will expire if not applied within the configured window.

Apply the saved plan by its ID. This step acquires the deploy lock and commits the facts.

Terminal window
ployzctl branch apply-prepared <prepared-deploy-id>

Once applied, the target namespace is live with its own routing, DNS entries, and gateway rules.

Promotion atomically switches traffic from one namespace to another. It is implemented through the deploy path: you apply a manifest in the target namespace that references the branched services, and the routing commit point flips traffic.

Terminal window
# After validating the PR environment, promote by deploying the
# branched service spec back into production
ployzctl deploy -f promote.toml

The old production namespace remains snapshotted by ZFS until you explicitly remove it, giving you an instant rollback point.

ModeServicesVolumes
BranchTarget service inherits the source’s container spec and revision. Lineage is recorded.Target volume is a ZFS clone of the source — instant, copy-on-write.
FreshTarget service is created independently with no source lineage.Target volume is provisioned as a new empty dataset.

Understand the deploy phases and commit model that powers branch and promote.

Restore a previous deploy point if a promotion goes wrong.