Skitflow
Self-hosted

Compose Service Autoscaling

Automatically scale a Swarm stack service's replica count from live CPU/memory usage (self-hosted only).

Compose service autoscaling is self-hosted only, and only for compose stacks deployed to Swarm.

Requirements

  • The compose service must be part of a stack (Swarm-deployed compose), not a plain Docker Compose deployment.
  • Swarm Monitoring must be enabled for the organization — autoscaling reads the same per-replica CPU/memory samples.
  • The runtime swarm service (${appName}_${serviceName}) must be a replicated service; global or job-mode services are skipped.

Configure

Open the compose stack's Advanced tab. The Autoscaling card appears once both requirements above are met. Pick a service, then set:

  • Enable autoscaling — while on, the replica count is managed automatically; manual replica changes made elsewhere are overridden on the next tick.
  • Min / Max Replicas — defaults 2 / 15.
  • CPU Scale-Up (%) / CPU Scale-Down (%) — defaults 85 / 25.
  • Memory Scale-Up (%) / Memory Scale-Down (%) — defaults 85 / 25.

sustainedChecks (default 3), cooldownMinutes (default 5), and stepSize (default 1) aren't exposed in this form — they use their defaults unless set through the API directly (see below).

Reading configs requires the autoscaler.read custom-role permission; saving requires autoscaler.update. Both endpoints also verify the compose stack belongs to your active organization.

Scale decision

A background tick runs every minute for every enabled (compose, service) config. It reads the average CPU/memory over the last 5 minutes and decides:

  • Scale up by stepSize replicas (capped at maxReplicas) when CPU is above targetCpuMax or memory is above targetMemMax, sustained for sustainedChecks consecutive ticks, and cooldownMinutes has passed since the last scale action.
  • Scale down by stepSize replicas (floored at minReplicas) when CPU is below targetCpuMin and memory is below targetMemMin (memory is ignored for scale-down if it has no samples), and the cooldown has elapsed.
  • Otherwise — inside the dead-band between the min/max targets, still in cooldown, or already at a bound — nothing happens.

The service is scaled in place with a live docker service update, not a full docker stack deploy, so the rest of the compose spec is untouched. The resulting replica count is persisted and re-applied on the next real docker stack deploy, so a redeploy doesn't clobber an autoscaled count. A tick that finds no recent metrics, a missing service, or a scale error for one service logs it and moves on — it never aborts the whole tick.

API

POST /api/trpc/autoscaler.list
POST /api/trpc/autoscaler.upsert

list returns every per-service config for a compose stack:

{ "composeId": "compose_123" }

upsert creates or updates the config for one service:

{
  "composeId": "compose_123",
  "serviceName": "web",
  "enabled": true,
  "minReplicas": 2,
  "maxReplicas": 10,
  "targetCpuMax": 80,
  "targetCpuMin": 20,
  "targetMemMax": 80,
  "targetMemMin": 20,
  "sustainedChecks": 3,
  "cooldownMinutes": 5,
  "stepSize": 1
}

All fields except composeId and serviceName are optional and patch only what's provided. The API rejects a patch where minReplicas > maxReplicas, targetCpuMin >= targetCpuMax, or targetMemMin >= targetMemMax (checked only when both sides of a pair are present). minReplicas/maxReplicas accept 1–100, the CPU/memory targets accept 1–100, sustainedChecks accepts 1–60, cooldownMinutes accepts 0–1440, and stepSize accepts 1–10. Each upsert is recorded in the organization audit log as an autoscaler-config update.

On this page