Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for GitLab CI/CD By James Joyner IV · · 9 min read

GitLab Dynamic Environments: Spin Up Ephemeral Infra and Tear It Down Cleanly

Use GitLab dynamic environments with on_stop jobs and auto-stop timers to provision per-branch infrastructure that cleans itself up — no more orphaned namespaces.

  • #gitlab
  • #cicd
  • #environments
  • #ephemeral
  • #kubernetes
  • #cleanup

Every team that does per-branch deploys eventually discovers the same surprise: a cloud bill full of infrastructure for branches that were merged and deleted months ago. Orphaned namespaces, dangling load balancers, databases nobody remembers creating. The deploy automation worked great; the teardown automation never existed. GitLab’s dynamic environments solve exactly this — if you wire up the on_stop half that most teams skip.

This is how to provision ephemeral infrastructure that actually cleans itself up.

Static vs. dynamic environments

A static environment is a fixed target — production, staging. A dynamic environment is created on demand, usually one per branch or merge request, with a name derived from a CI variable:

deploy_review:
  stage: deploy
  script:
    - ./deploy.sh "$CI_ENVIRONMENT_SLUG"
  environment:
    name: review/$CI_COMMIT_REF_SLUG
    url: https://$CI_ENVIRONMENT_SLUG.review.example.com

The review/$CI_COMMIT_REF_SLUG naming creates a distinct environment per branch. GitLab tracks each one in the Environments view, with its URL and deployment history. So far this is the easy, well-known half. The hard part — the part that saves your bill — is teardown.

The on_stop job is the part everyone forgets

A dynamic environment should know how to destroy itself. You attach an on_stop job that runs the teardown:

deploy_review:
  stage: deploy
  script:
    - ./deploy.sh "$CI_ENVIRONMENT_SLUG"
  environment:
    name: review/$CI_COMMIT_REF_SLUG
    url: https://$CI_ENVIRONMENT_SLUG.review.example.com
    on_stop: stop_review
    auto_stop_in: 3 days

stop_review:
  stage: deploy
  script:
    - ./teardown.sh "$CI_ENVIRONMENT_SLUG"
  environment:
    name: review/$CI_COMMIT_REF_SLUG
    action: stop
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      when: manual
  variables:
    GIT_STRATEGY: none

Three things here are load-bearing:

  • action: stop marks this as the teardown job. GitLab runs it automatically when the environment is stopped — including when the source branch is deleted (i.e. when the MR merges). That’s the magic: merge the MR, the branch is deleted, the on_stop job fires, the infrastructure is destroyed. No human has to remember.
  • auto_stop_in: 3 days is the backstop. Even if a branch lingers, GitLab auto-stops the environment after the timer, triggering the same teardown. This is what kills the abandoned-branch leak.
  • GIT_STRATEGY: none on the stop job — because the branch may already be deleted by the time teardown runs, so the job can’t check it out. Skip the clone.

Make teardown actually delete everything

The on_stop job is only as good as your teardown.sh. The common failure is tearing down the obvious thing (the Kubernetes deployment) while leaving the expensive thing (a provisioned database, a cloud load balancer, a DNS record). When you provision a dynamic environment, write the teardown in the same change, and make it idempotent so a re-run on already-gone resources doesn’t error:

#!/usr/bin/env bash
set -euo pipefail
SLUG="$1"

# Idempotent teardown — ignore "not found"
kubectl delete namespace "review-$SLUG" --ignore-not-found
aws elbv2 delete-load-balancer --load-balancer-arn "$(lookup_lb "$SLUG")" || true
./cleanup-dns.sh "$SLUG" || true

A discipline that’s saved me real money: provisioning and teardown are a pair. You don’t merge code that creates an environment without the code that destroys it. Treat a missing on_stop like a missing test.

Catch the leaks before the bill does

Even with good hygiene, things slip — a teardown script that silently failed, a resource created outside the namespace. Run a scheduled audit pipeline that lists what’s actually deployed and flags environments with no recent activity:

audit_environments:
  stage: audit
  script:
    - ./list-orphaned-namespaces.sh
  rules:
    - if: '$CI_PIPELINE_SOURCE == "schedule"'

This is a great spot for AI: feed it the list of live namespaces and the list of open merge requests, and ask “which of these environments has no corresponding open MR and should probably be torn down?” The model is good at the diff-the-two-lists reconciliation that’s tedious to script perfectly. Pair that with the dynamic environments and you get cleanup that’s both automatic and audited.

Tie it into review apps and Kubernetes

Dynamic environments are the foundation under review apps — the per-MR live previews. The environment machinery here (naming, on_stop, auto_stop_in) is exactly what a review-app setup uses; we go deeper on the review-app and Kubernetes-agent side in our GitLab CI/CD guides. For the pipeline config itself, our AI Code Review assistant flags the most expensive omission in a deploy diff: an environment that creates resources but has no on_stop to destroy them.

The takeaway

Per-branch infrastructure is fantastic for review velocity and a slow-motion budget disaster if you only automate the create half. Dynamic environments with on_stop give you automatic teardown on merge; auto_stop_in backstops the branches that linger; a scheduled audit catches the leaks that slip through. Provision and teardown as a pair, and your cloud bill stops accumulating ghosts.

Teardown scripts and AI cleanup suggestions are assistive. Verify what’s actually destroyed against your cloud console before trusting automated cleanup with production-adjacent resources.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.