Multi-stack deploys

An OwnStack app can deploy to one stack or many. The shape is the same — same Procfile, same buildpack, same release task — but each stack is its own running instance with its own dokku state, scale, logs, and (optionally) its own per-stack config overrides.

Why deploy to multiple stacks

  • Staging + production — cheap stack for pre-merge testing, beefier stack for prod.
  • Primary + failover — same code, different region; flip DNS if the primary goes down.
  • Active-active — multiple regions serving traffic via a global load balancer (the cloud provider's, or your DNS-based one).
  • Multi-tenant isolation — one app codebase, many stacks, each holding a different customer's data.

Add or remove stacks

$ ownstack app stacks <app>
$ ownstack app stacks:add <app> <stack-name>
$ ownstack app stacks:remove <app> <stack-name>

Each new target gets its own dokku app on the new stack on the next deploy. Removing a target stops deploys to that stack but leaves the dokku app and data in place — destroy them via ssh dokku@<stack-ip> apps:destroy if you don't need them.

One deploy, many jobs

A single ownstack deploy enqueues one deployment job per stack. They run in parallel. Each has its own status, log, and SHA tracking:

$ ownstack deploy
Triggering deploy for app 47…
✓ Deploy started on prod-east (job 1024)
✓ Deploy started on prod-west (job 1025)

$ ownstack app info
  Stack:   prod-east — deployed abc1234
  Stack:   prod-west — deployed abc1234

If one job fails, the others keep going. The dashboard Deployments tab shows mixed status. Re-deploy just the failed stack with --stack=<name>.

Per-stack config

App-level config vars apply to every stack. For values that differ per stack — different external API URL in staging, different region indicator — set them at the stack level:

$ ownstack config:set --app=<app> --stack=prod-east  REGION=us-east-1
$ ownstack config:set --app=<app> --stack=prod-west  REGION=us-west-2

Stack-level vars override app-level vars on that stack only.

Per-stack scaling

Scale state is per-stack. Larger region runs more workers; a hot-spare runs zero. See Scaling.

Per-stack databases

By default, each stack gets its own postgres/mysql/redis service. Two ways to share data across stacks:

  • External DB — point DATABASE_URL at a managed RDS / Cloud SQL / etc. instance reachable from all stacks. Set needs_postgres: false on the app so OwnStack stops auto-creating per-stack services.
  • Replicate — use ownstack app replicate to make a sibling app that shares DB and Redis with the source. Useful for blue-green within a stack.

DNS in front of multiple stacks

OwnStack doesn't run a global load balancer. Either:

  • Use the cloud provider's LB (AWS ALB/NLB, GCP HTTP LB, Cloudflare Load Balancing) and target each stack as an origin.
  • Use weighted DNS records (Route 53, DNSimple, Cloudflare) — split traffic by record weight, fail over with health checks.

Each stack independently terminates SSL with its own Let's Encrypt cert.