Host your own email and enhance your privacy
The quiesce workflow scales a development or stage environment’s running compute to zero so it stops accruing hourly charges. Mail data, address data, and other state-bearing resources are left alone, so the environment can be brought back up with a single workflow run.
| Resource | Behavior when quiesced |
|---|---|
ECS services for imap, smtp-in, smtp-out |
desired_count = 0 |
| ECS services for the monitoring stack (Prometheus, Alertmanager, Grafana, Uptime Kuma, Healthchecks, ntfy, cloudwatch-exporter, blackbox-exporter) | desired_count = 0 |
ECS Application Auto Scaling targets for smtp-in and smtp-out |
min_capacity = 0, max_capacity = 0 |
| ECS-instance Auto Scaling Group | min_size = 0, desired_capacity = 0, max_size = 0 |
ASG instance scale-in protection (protect_from_scale_in) |
Disabled, so the running instance can actually be terminated |
ECS capacity provider managed_termination_protection |
Disabled, so the capacity provider stops fighting the ASG drain |
| NAT instances | count = 0. The Elastic IPs are kept, so SMTP allow-lists do not need to be re-issued on resume. |
| Private subnet default route | Removed. The NAT-instance NIC it pointed to is gone, and nothing runs in private subnets while quiesced. |
The DAEMON node-exporter ECS service is not gated explicitly. It places one task per EC2 instance in the cluster; with the ASG at zero, it has no instances to schedule on and naturally goes to zero with the rest of the compute.
cabal-addresses, cabal-user-preferences, cabal-dmarc-reports, the Cognito counter table)smtp.<control-domain> recordA quiesced environment will fail TCP health checks on IMAP/SMTP and serve no monitoring UI. DNS still resolves; clients see connection timeouts rather than NXDOMAIN.
The workflow is in .github/workflows/quiesce.yml. It is workflow_dispatch only.
stage for the stage environment, anything else for development). The main branch is rejected outright.environment = development or stageaction = down to scale to zero, or up to restoreinfra.yml does, and runs terraform apply with quiesced = true|false written directly into the tfvars file.infra.yml runs on any push that touches terraform/infra/** (or terraform/dns/**) and on workflow_dispatch. It writes quiesced = $ to its tfvars, so by default it un-quiesces.
To keep an environment quiesced across other runs:
quiesce with action: down, set TF_VAR_QUIESCED=true on the matching GitHub Environment (development or stage) under Settings -> Environments.quiesce with action: up, clear TF_VAR_QUIESCED (set to false or remove the variable).Forgetting this step is recoverable: the next infra.yml run will simply restore compute. The state-bearing resources are unaffected either way.
imap.<control-domain> and smtp.<control-domain> are dropped at the NLB once tasks deregister.UnHealthyHostCount on the NLB target groups will fire continuously while quiesced. This is expected; suppress or accept the noise on non-prod.monitoring = true. Same rationale.