From git push to production: what actually happens when ModStack deploys your backend

A deploy is the easiest thing in the world to trigger and one of the hardest things to do well. Between "push accepted" and "traffic served" there's a container build, a rollout across instances, and a routing change — and each one is an opportunity for a bad push to become a bad day.

This post walks the full journey of a ModStack deploy, and the guardrails at each step. If you've ever wondered what the platform is doing while the task spinner turns, this is that story.

Step 1: Build — from Dockerfile to image

Every deploy starts from your repo. ModStack clones the branch you configured, finds your Dockerfile, and runs the build on managed build infrastructure — no runners for you to maintain, and layer caching means unchanged dependencies don't rebuild.

console
# what the build tasklet is doing on your behalf
$ git clone --depth 1 --branch main your-repo
$ docker build --cache-from registry/api:latest -t registry/api:0.4.2 .
  => CACHED [2/6] RUN npm ci
  => [5/6] RUN npm run build
$ docker push registry/api:0.4.2

The resulting image is scanned for CVEs before it's allowed anywhere near a cluster, and the ports your EXPOSE directives declare are picked up so the gateway step can pre-fill your port mappings.

Step 2: Deploy — rolling out with probes

A build that succeeds is not a service that works. The rollout replaces instances one at a time, and each new instance has to prove itself before the next old one is retired. That proof comes from the health probes you configure:

  • Startup probe — how long the app gets to boot before we call it stuck.
  • Readiness probe — "can this instance take traffic right now?"
  • Liveness probe — "has this instance wedged itself and needs a restart?"
yaml
readinessProbe:
  httpGet:
    path: /healthz
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 10
Probes are how a rolling upgrade detects a bad rollout. Shipping a production service without them is almost always a mistake — which is why the wizard asks you to confirm before letting one through.

Step 3: Route — gateway, ILB, and your container

With healthy instances running, traffic has to find them. Requests enter through the environment's gateway on ports 80/443, where SSL terminates. Gateway rules forward each path to an internal load balancer (ILB) port inside the environment's private network, and the ILB spreads the traffic across every instance's container port.

Because the rules are declarative, the platform can catch routing mistakes before they ship — like two services claiming the same path on the same gateway port, which would otherwise be an ambiguous route that works only by accident.

What about rollbacks?

Every deploy is a versioned template. Rolling back is re-deploying a version that already proved it works — same pipeline, known-good input. And because the rollout is gated by the same probes, a rollback can't take the service down either.

The failed version's build logs and task history stick around, so you can diagnose at leisure while the previous version serves traffic.

Try it yourself

The fastest way to internalize all of this is to push something. Create a free environment, point ModStack at a repo with a Dockerfile, and watch the task view narrate every step you just read about.

Ready to press the easy button?

Deploy your first service in minutes — any language, any framework, your cloud or ours.

Get Started