Skip to content

Deploy types#

Every deploy in manent runs the same pipeline. What changes is described along four independent axes:

Axis Question Options
Trigger When does it start? immediately, at a given time, recurring, after other deploys, as part of a composite release
Kind Where does the artifact come from? new deploy, promotion, manual rollback, plus dry-run as a mode
Strategy How does it reach the targets? all at once, in waves, with load balancer draining, by traffic percentage, delegated to the cloud service
Platform What is changed on the target? files on servers, containers, Kubernetes objects, managed cloud services, application servers, Windows

The axes combine freely: a recurring promotion released in waves to Kubernetes clusters is a valid deploy, and so is a dry-run of a percentage rollout on Cloud Run.

Trigger#

Immediate#

The default. The deploy enters the DBOS queue at once (ENQUEUED) and starts as soon as a worker has a free slot and no other deploy of the same application and environment is running (dbos.environment_concurrency, default 1).

manent deploy -f deploy.yml

At a given time#

schedule.at enqueues the deploy immediately in state DELAYED; it enters the queue at the given time, for example in a maintenance window. It is cancelled like any deploy.

schedule:
  at: 2026-11-07T02:00:00+01:00

Recurring#

schedule.cron creates (or updates by name) a schedule: at every tick manent enqueues a deploy with the deterministic ID <schedule>@<UTC time>, so a tick never produces two deploys, even with many workers. Typical for nightly releases to development environments.

schedule:
  cron: "0 2 * * 1-5"
  timezone: Europe/Rome
  name: shop-nightly

See Scheduled deploys.

After other deploys#

With after (or --after <id>) the deploy waits, in state WAITING_DEPENDENCY, until the deploys it depends on have succeeded. It takes no slot while it waits; if a dependency fails it ends as DEPENDENCY_FAILED.

after: [shop-db-2.4.0-prod]
afterTimeout: 2h

A deploy can also read what the previous one produced: the infrastructure deploy exports the VMs it created, the configuration deploy imports them as its targets (imports, deploy.targetsFrom). See Exports and imports.

Composite release#

A kind: Release document groups several deploys with the dependencies between them: independent ones run in parallel, the others in order. onFailure decides whether to stop, continue or roll back the deploys already done.

apiVersion: manent/v1
kind: Release
id: shop-2026-10
onFailure: rollback
deploys:
  - {name: db, file: release/db.yml}
  - {name: api, file: release/api.yml, after: [db]}
  - {name: web, file: release/web.yml, after: [api]}

See Deploy chains.

Kind#

The kind is recorded with every deploy (kind in the status and in the inventory).

Kind Started by Artifact Notes
deploy manent deploy, API, CI, schedules The one in the descriptor. The usual case.
promotion manent promote --from test --to prod The one released successfully in the source environment, with its sha256 pinned. Targets come from the destination environment, never from the source. Subject to the destination's rules.
rollback manent rollback -e prod [--to 1.3.2] A previous release of the same environment, with its sha256. A manual rollback is a new deploy. Allowed only for artifact types whose policy allows rollback.

Automatic rollback is not a kind: it happens inside a failed deploy, which stays ERROR and reports the rollback outcome. See Rollback.

Dry-run is a mode of any kind (--dry-run, dryRun: true): the same workflow runs on a worker, checks secrets, artifact and targets, and changes nothing. A dry-run with an id gets the ID <id>.dry-run, so it does not consume the idempotency key of the real deploy. See Dry-run.

Strategy#

flowchart LR
    A["All at once<br/>(default)"] --> W["Waves<br/>canary · AZ · region"]
    W --> D["Waves + draining<br/>from the load balancer"]
    A --> P["Percentage<br/>canary · blue/green"]
    W --> PW["Percentage in waves<br/>per cluster or region"]
    P --> PW

All at once#

Without rollout the deploy runs the steps once, on all the targets of the environment. The plugin decides how to go through them: remote-copy, for example, releases one target after the other and stops at the first failure. It is the right choice for a single node, for development environments, and for services where the platform itself replaces instances gradually (a Kubernetes Deployment, an ECS service).

Waves#

The rollout.waves strategy releases a canary first, then one region and one AZ at a time, in batches of maxUnavailable targets. After every stage there is a bake time and a health gate (HTTP probes, metrics, alerts). The deploy keeps one ID and one outcome; on failure onFailure stops, rolls back the failed wave or rolls back everything.

rollout:
  waves:
    - {name: canary, select: "canary=true", bake: 15m}
    - {name: eu, select: "region=eu-1", by: az, bake: 10m}
  maxUnavailable: 25%
  onFailure: rollback-wave

With dbos.region_routing each region's passes run on workers of that region, for networks that are separate per region.

Waves with load balancer draining#

When the targets sit behind a load balancer, traffic.pool in the environment configuration drains every batch before the deploy and puts it back in service afterwards, with a capacity check. Providers: HAProxy, F5 BIG-IP, NGINX Plus, NGINX open source, AWS ELB, IIS ARR, Windows NLB and a health-flag file.

Percentage (canary and blue/green)#

The traffic strategy releases the candidate next to the stable version without traffic, then moves traffic in steps (for example 1, 5, 25, 50, 100%) with a gate after each step. A failure sends the traffic back to the stable version with a weight change, without redeploying. Blue/green is the same mechanism with steps: [100]. Canary analysis can compare candidate and stable statistically (Mann-Whitney).

rollout:
  strategy: traffic
  traffic: {steps: [5, 25, 50, 100], bake: 10m}

Traffic is moved by the plugin (Kubernetes with Gateway API or Istio, Lambda, Cloud Run, App Service, Container Apps) or by an environment router (HAProxy, F5, NGINX Plus, AWS ALB) with targets labelled by slot. With rollout.waves the whole sequence runs per cluster or region.

Delegated to the cloud service#

Some services have their own progressive strategies. With the ecs plugin, a service configured with BLUE_GREEN, LINEAR or CANARY keeps them: manent updates the service and waits for the expected duration, while ECS moves traffic and rolls back on its alarms.

Which strategy#

You want Use
The simplest release, one node or a dev environment All at once
To limit the blast radius across regions and AZs Waves with a canary
No dropped connections behind a load balancer Waves with draining
To expose a small share of users first, with instant return Percentage
To switch all traffic at once after tests on the new version Blue/green (steps: [100], testers, approval at "0")
To keep the cloud service's native strategy Delegated (ECS)

Platform#

Platform Plugin Artifact type What changes Rollback
Linux and Unix servers remote-copy application Files copied over SSH/SFTP, a release directory and the current symlink. with layout: releases
Docker and Podman on VMs container container The container, recreated from an image pinned by digest. yes
Kubernetes kubernetes kubernetes Manifests or a Helm chart, with server-side apply. yes
Amazon ECS ecs ecs A new task definition revision of an existing service. yes
AWS Lambda lambda lambda Function code and a published version behind an alias. yes
Google Cloud Run cloudrun cloudrun A new revision of an existing service. yes
Azure App Service appservice appservice Package or image, optionally in a slot with swap. yes
Azure Container Apps containerapps containerapps A new revision of an existing app. yes
JBoss EAP, WildFly jboss war, ear A deployment per version, replaced atomically. yes
Windows windows windows IIS applications, services, scheduled tasks, MSI packages. yes
Anything else external plugin your own Whatever your plugin does, over gRPC. if declared

The artifact type also selects the rollback policy: migration, for example, never allows it.