Octopus
1.x
Docs/Octopus/Scaling
Open

Reading3 min
Updated31 Jul 2026
Sourcev1/deployment/scaling.mdx

Scaling

Octopus scales in two directions: up (more worker threads per process) and out (more replicas behind a load balancer). They're complementary — tune workers to use a node's cores, then add replicas for capacity and availability.

Vertical: gateway.workers01

Each Octopus process runs an async runtime with a pool of worker threads. gateway.workers controls the size of that pool:

gateway:
  listen: "0.0.0.0:8080"
  workers: 0          # 0 = auto: one worker per available CPU core
  • 0 (default) — auto: the runtime uses one worker per CPU core it can see.

  • A fixed number — pin the pool to exactly that many threads.

Note

In Kubernetes, "available cores" depends on what the container can see, not on the CPU limit. If you set a CPU limit, consider setting workers explicitly to match it (or set it via the runtime's CPU detection) so the pool size lines up with the cores you've actually allocated. The default 0 is the right starting point on bare hosts and VMs.

The Helm chart and bundled manifests ship workers: 0. See Gateway configuration for the field reference.

Horizontal: replicas02

Octopus instances are interchangeable — run several behind a load balancer (a Kubernetes Service, an external LB, or another ingress) and spread traffic across them. This is also how you get availability: a single replica is a single point of failure.

In Kubernetes, set the replica count on the Deployment. The Helm chart defaults to 2:

helm install octopus deploy/helm/octopus -n octopus --create-namespace \
  --set replicaCount=3

For availability across nodes and zones, the chart also exposes topologySpreadConstraints and a PodDisruptionBudget (enabled by default, minAvailable: 1). See the Helm chart reference.

Autoscaling (HPA)03

The Helm chart can render a HorizontalPodAutoscaler. It's off by default; enable it and the chart stops setting a static replicaCount (the HPA owns the replica count instead):

helm install octopus deploy/helm/octopus -n octopus --create-namespace \
  --set autoscaling.enabled=true \
  --set autoscaling.minReplicas=2 \
  --set autoscaling.maxReplicas=10 \
  --set autoscaling.targetCPUUtilizationPercentage=80

The chart's HPA scales on CPU utilization by default and optionally on memory (autoscaling.targetMemoryUtilizationPercentage). The HPA needs CPU/memory resource requests to compute utilization against — the chart sets those by default. Full values are in the Helm chart reference.

Shared state across replicas04

Once you run more than one replica, any feature that remembers things between requests must share that state — otherwise each replica counts and caches independently. The features that need it include:

  • Rate limiting — counters must be shared so a limit means the same thing fleet-wide.

  • Caching — to avoid each replica caching the same upstream response separately.

  • Circuit breakers — shared failure counts so the breaker trips consistently.

  • Sessions / auth caches — shared so a session isn't tied to one replica.

Octopus keeps this in a pluggable state store. The default in-memory backend is per-process and is fine for a single instance; for multiple replicas use a shared backend (Redis, Postgres, or hybrid).

Warning

Multi-replica deployments that use rate limiting, shared caching, or circuit breaking should configure a shared state backend. With the default in-memory store, those features are scoped to each individual replica.

See State for the backends and how to select one.

  • Gateway configurationworkers and the rest of the gateway block.

  • Helm chartreplicaCount, autoscaling, topologySpreadConstraints, PDB.

  • State — shared state backends for multi-replica deployments.

  • Graceful shutdown — draining cleanly as replicas come and go.