Environments, Deployments, Environment Tiers, URLs, Deployment History, and Operational Traceability: Configuration, Design Choices, and Tradeoffs
Choose environment naming, tiers, actions, URL semantics, environment-scoped variables, artifact promotion, retention, and rollback strategy from operational evidence requirements.
Learning objectives
- Choose static versus dynamic environment naming and one-environment-per-tier versus service-specific environments.
- Treat GitLab environment URL/history as metadata and prove real target health independently.
- Choose build-once artifact promotion over rebuild-at-deploy when byte identity and rollback reproducibility matter.
- Use environment-scoped variables narrowly while avoiding them as pipeline-compilation inputs in rules/includes.
- Choose start/prepare/verify/access/stop actions and auto-stop behavior according to deployment-record and lifecycle intent.
1. Design starts with the target identity and evidence contract
Once a team can create an environment, the hard questions are
architectural: should production be one environment or
one per service? Should feature branches create dynamic
environments? Should a verification job create deployment history?
Where should an artifact live so rollback does not rebuild it? Which
variables should be scoped to which environment?
The answer should follow the operational object you need to control and audit, not a preference for shorter YAML.
2. Static versus dynamic environments
| Choice | Strengths | Risks / evidence cost | Typical fit |
|---|---|---|---|
Static: staging, production |
Stable history, predictable scoping, simple URLs | Can be too coarse for multiple independent services | Long-lived shared targets |
Dynamic: review/$CI_COMMIT_REF_SLUG |
Per-change isolation, reviewability | Cardinality, cleanup, URL/slug collisions, cost | Ephemeral review/test stacks |
Chapter 20 is dedicated to dynamic review environments. Chapter 19 keeps the mandatory path static so environment history is easy to reason about.
3. One environment per tier versus per service
Environment granularity should match rollback and authorization
granularity. If five services deploy independently, one
production environment can blur which service changed
and complicate protected-environment permissions. Names such as
production/payments and
production/catalog can preserve separate history while
both use deployment_tier: production.
| Question | Single tier environment | Service-specific environment |
|---|---|---|
| Deployment history | All changes mixed | Per-service history |
| Rollback target | Potentially ambiguous | Clearer per service |
| Environment-scoped variables | Coarser scope | Narrower scope |
| Operational dashboard | Simple count | More objects to govern |
4. Name and deployment tier solve different problems
The name is the environment identity; the tier classifies its
operational role. GitLab can guess tiers from common names, but
explicit deployment_tier is safer for unconventional
names.
deploy:portal:
environment:
name: customer-portal
deployment_tier: production
url: https://portal.example.com
Current GitLab supports CI/CD variables in
deployment_tier starting with GitLab 18.5, but use a
small, validated set of tier values; do not turn tier classification
into arbitrary user input.
5. Use actions to preserve semantic deployment history
| Intent | Action | Creates deployment? | Auto-stop effect to consider |
|---|---|---|---|
| Apply a new version | start |
Yes | Deploying can reset lifetime when configured. |
| Prepare target | prepare |
No ordinary deployment | Can reset scheduled stop based on latest successful deployment. |
| Read/verify health | verify |
No ordinary deployment | Does not reset scheduled stop in the same way as access/prepare. |
| Access target context | access |
No ordinary deployment | Can reset scheduled stop. |
| Teardown | stop |
Stops environment | No auto_stop_in on stop action. |
Using start for a health check pollutes history with
“deployments” that did not deploy anything. Using
verify preserves the meaning of the deployment
timeline.
6. auto_stop_in is lifecycle scheduling, not deletion proof
auto_stop_in accepts natural-language durations such as
1 day or never. GitLab’s background worker
detects expired environments periodically, so the stop is not an
exact real-time SLA.
A stop action can run teardown logic, but the environment becoming
stopped still does not prove that a cloud resource, DNS
record, namespace, or database was deleted. Chapter 20 will require
explicit cleanup proof for ephemeral stacks.
7. GitLab URL/record versus actual service health
Choose URL semantics that help humans navigate, but define a separate health contract: expected artifact/image digest, version endpoint, provider resource ID, minimum dependency health, or another read-back appropriate to the target.
| Signal | What it proves | What it does not prove |
|---|---|---|
| Deployment job success | Script exited successfully | Target serves intended version |
| GitLab deployment success | GitLab recorded a successful deployable | Provider accepted/settled all external changes |
| Environment URL | Navigation destination | Reachability or version identity |
| Target health/read-back | Observed external state | How GitLab configuration was compiled |
| Artifact digest match | Byte identity | Runtime dependency health |
8. Rebuild versus artifact promotion
For high-assurance delivery, treat build output as a versioned input to deployment. Rebuilding in each environment breaks the chain from test evidence to production bytes.
Preferred lineage:
source SHA -> build job -> artifact/image digest -> test evidence -> staging deployment -> production deployment -> rollback reference
Risky lineage:
source SHA -> test build A -> rebuild for staging B -> rebuild for production C
When artifact retention in job storage is too short for release/rollback requirements, promote the artifact into an appropriate package/container registry with an immutable version/digest policy. Do not misuse cache as deployment evidence.
9. Environment-scoped variables narrow exposure, but are not rule inputs
Project variables can be scoped to a specific environment or wildcard. This is useful for narrowing deployment configuration or credentials. It does not replace a secrets manager, protected refs, or deployment authorization.
GitLab explicitly warns against using environment-scoped variables
with rules or include: those decisions can
be evaluated before the environment scope is known. Keep pipeline
creation decisions based on pre-pipeline/pipeline data, then use the
scoped value only inside the eligible environment job.
10. Rollback design: preserve deployable identity before you need it
GitLab rollback creates a new deployment pointing at the older commit and reruns deployment logic. Design the deployment job so it can retrieve or consume the exact historical payload by digest/version. If the job needs expired artifacts or performs a fresh build, the rollback contract is weak.
Record at least: original source SHA, artifact/image digest, deployment ID, environment ID/name, provider target ID, health evidence, and retention/location of the rollback payload.
11. Worked decision table
| Scenario | Recommended design | Prerequisite/tier | Observable proof |
|---|---|---|---|
| Long-lived staging and production | Stable names + explicit tiers + build-once artifact promotion | Free core features | Single coherent history per target and digest continuity |
| Health polling after deploy | Same environment + action: verify |
Free | No extra ordinary deployment record; health evidence tied to deployment |
| Feature preview | Dynamic review/* + stop/auto-stop |
Free core pattern; infra cost varies | Environment slug/URL/resource IDs + cleanup proof |
| Sensitive production approval | Protected environment / approvals as available | Tier/role dependent | Authorization/approval evidence plus deployment record |
| Rollback months later | Registry/package retention by immutable digest | Registry/storage policy dependent | Old digest is still retrievable and matches prior record |
12. Design checklist
- Name the operational target consistently.
- Set the deployment tier explicitly when the name is nonstandard.
- Use
startonly for actual deployment changes. - Keep URL metadata separate from health evidence.
- Build once and promote exact bytes/digests.
-
Scope variables to the environment only when appropriate; do not
rely on them for
rules/include. - Design rollback retention before production needs it.
-
Record
CI_PIPELINE_SOURCE,CI_COMMIT_SHA, job/deployment IDs, digest, and target read-back.
Knowledge check
Why can customer-portal still have deployment_tier: production?
Environment name is identity while deployment tier is an explicit classification; they do not need the same string.
Why use action: verify for a health-check job?
It accesses/verifies environment state without creating a misleading ordinary deployment record.
What is the main rollback advantage of build-once promotion?
The exact bytes tested and previously deployed can be identified and redeployed by digest/version instead of rebuilt.
Why should environment-scoped variables not drive rules/includes?
Pipeline configuration can be validated before the environment scope/value is available, making such decisions unreliable.
Does auto_stop_in prove cloud resources were deleted?
No. It schedules GitLab environment stopping; external cleanup needs separate teardown and verification evidence.
Version and compatibility note
GitLab and GitLab Runner evolve continuously. Treat version-sensitive YAML, runner/executor behavior, APIs, security features, policy controls, tiers, and deprecations as assumptions to verify against the current official GitLab documentation before production use. Preserve the exact project/ref/SHA, compiled configuration, pipeline/job IDs, runner/tool versions, and external target evidence used for any reproducible lab or incident record.
Official references and version notes
Documentation verification date: 2026-09-12. Environment/deployment keywords, environment actions, deployment-tier variable support, auto-stop behavior, rollback UI behavior, environment-scoped variables, and deployment safety are version-sensitive. Re-check the GitLab and Runner versions used by production delivery before applying the exact examples.
- Environments — environment identity/state, tiers, URLs, stop/auto-stop behavior, environment-scoped variables, and operational views.
- Deployments — deployment history, deployment refs, retry/rollback behavior, and auditability.
- Deployment safety — deployment serialization, outdated-job prevention, protected environments, and rollback considerations.
-
CI/CD YAML syntax reference
—
environment,environment:name,url,action,auto_stop_in,deployment_tier, and related job semantics. - Deployments API — deployment IDs, statuses, SHA/ref, user, environment, and history queries.
- Environments API — environment metadata/state/tier management when API access is appropriate.
- CI/CD variables — environment scope behavior and precedence boundaries.
Current assumptions used in this chapter:
environments and deployment history are available on Free, Premium,
and Ultimate across GitLab.com, Self-Managed, and Dedicated.
Environment states include available,
stopping, and stopped.
environment:action currently supports
start (default, creates a deployment after job start),
prepare, verify, access, and
stop; the latter four model lifecycle/access work
rather than ordinary deployment creation. Deployment tiers are
production, staging, testing,
development, and other; CI/CD-variable
support for deployment_tier was added in GitLab 18.5.
auto_stop_in uses natural-language durations; stop
processing is background work and is not an exact real-time timer.
The mandatory labs use synthetic artifacts, a stable
training/ch19 environment, alpine:3.22, a
reserved .invalid URL, and filesystem/artifact
snapshots as a faithful target simulation—no cloud account,
protected production environment, or real credential is required.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.