Stages, needs DAGs, Dependency Graphs, Early Execution, and Pipeline Critical-Path Design: Configuration, Design Choices, and Tradeoffs
A DAG is an operational design, not just faster YAML. This lesson compares stages with needs, early feedback with runner pressure, narrow dependency edges with auditability, optional needs with rule-driven job absence, and same-pipeline DAGs with cross-pipeline artifact-transfer features.
Learning objectives
- Choose simple stages or a DAG according to dependency shape, reviewability, runner capacity, and feedback needs.
- Use needs:optional only when a missing producer is genuinely optional to correctness.
- Balance fan-out breadth against queue pressure, concurrency cost, and evidence complexity.
- Distinguish same-pipeline needs from needs:project and needs:pipeline:job artifact-transfer semantics.
- Document current limits, tier/offering assumptions, and observable evidence for each graph design choice.
1. DAG design is a tradeoff, not a maturity badge
A stage-only pipeline is not “primitive.” It is often the most maintainable representation when every test genuinely depends on every build, when the pipeline is short, or when runner capacity is limited. A DAG earns its complexity when it encodes real independence that materially improves feedback or delivery latency.
2. Simple stages versus explicit DAG edges
| Choice | Strength | Cost/risk | Good fit |
|---|---|---|---|
| Stage barriers | Easy mental model; implicit ordering; broad prior-stage artifacts | Unrelated jobs can block each other | Small pipelines or true stage-wide gates |
| needs DAG | Early execution; explicit dependency shape; same-stage edges possible | More graph review; artifact transfer becomes narrower | Independent build/test paths, monorepos, long stage skew |
| Hybrid | Keep high-level stages while accelerating selected paths | Two ordering concepts coexist | Most production migrations |
The hybrid model is often best: preserve stage names for human
grouping and status meaning while adding needs only
where a measurable barrier is unnecessary.
3. Early feedback versus resource contention
Moving a source-only linter to needs: [] can produce
feedback earlier. Moving twenty CPU-heavy jobs to the runnable
frontier may instead create a queue, evict useful cache, saturate
network storage, or slow every job. Pipeline latency is a system
property:
effective_completion ≈ graph_dependency_time
+ runner_queue_delay
+ execution_time
+ artifact_transfer
+ external_wait
Measure these components before concluding that “more parallel” is faster. If queue time dominates, a wider DAG can make the interface look parallel while the execution substrate remains serialized.
4. Fan-out breadth and fan-in pressure
Fan-out lets independent work proceed. Fan-in waits for multiple
predecessors. Current GitLab limits a single normal
needs array to 50 jobs on GitLab.com (50 by default on
Self-Managed/Dedicated). Do not design toward the maximum casually.
A 40-edge fan-in may indicate that a smaller verification aggregate,
matrix structure, or component boundary would be easier to reason
about.
| Question | Why it matters |
|---|---|
| Does the consumer need every predecessor for correctness? | Remove decorative or historical edges that serialize without purpose. |
| Do all predecessors produce unique artifact names? | Parallel producers can overwrite same-named artifacts when downloaded together. |
| Will the fan-out exceed runner capacity? | Runnable jobs become pending and queue delay masks graph gains. |
| Can failure evidence identify one failed shard? | Preserve per-job/shard identity rather than collapsing evidence. |
5. Required versus optional needs
needs:optional exists because job membership can be
conditional. If a needed job is absent and the need is required,
pipeline creation can fail. If the edge is optional and the job is
absent, GitLab can proceed after the remaining needs are satisfied;
if the optional need is the only need and it is absent, the consumer
can start immediately.
docs_quality:
stage: test
rules:
- changes:
paths: [docs/**/*]
script: ./ci/check-docs.sh
summary:
stage: package
needs:
- job: docs_quality
optional: true
script: ./ci/write-summary.sh
6. needs is also a dataflow decision
With ordinary stages, artifact download can be broad. With
needs, only listed producers are eligible artifact
sources. artifacts: true is the default on a normal
needs edge; use false when the edge is control-only.
publish_preview:
stage: package
needs:
- job: unit_test
artifacts: false
- job: build_preview
artifacts: true
script:
- test -s dist/preview.tar
This is easier to audit than relying on “whatever artifacts existed in earlier stages.” Chapter 10 will deepen retention, reports, dependencies, and cross-job dataflow; here the design rule is simply that graph correctness and data correctness must agree.
7. Do not confuse same-pipeline dependencies with cross-pipeline artifact features
The word needs appears in several features with
different semantics:
| Feature | Primary purpose | Wait semantics / tier |
|---|---|---|
needs |
Order jobs in the same pipeline and optionally transfer artifacts | Free; consumer waits for listed same-pipeline jobs |
needs:project |
Fetch artifacts from another project/ref | Premium/Ultimate; up to five jobs; fetches latest successful specified job and does not wait for a concurrently running pipeline on that ref |
needs:pipeline:job |
Fetch artifacts within a parent-child pipeline hierarchy | Artifact transfer across parent/child hierarchy; producer must have completed successfully |
needs:pipeline |
Mirror upstream pipeline status | Status mirroring, not the same as a normal job dependency edge |
needs. Cross-project/child variants are architecture
context and later orchestration chapters revisit them.
8. Security and trust remain attached to jobs and artifacts
A DAG edge does not authorize anything by itself. Runner trust, protected variables, CI_JOB_TOKEN permissions, external credentials, and artifact sensitivity remain separate state. Earlier execution can increase exposure if a privileged job is made runnable before the checks that were implicitly protecting it through stage order.
When refactoring, identify whether an earlier stage was acting as a policy gate, not merely a technical dependency. If a deployment must not become runnable until review/security checks finish, encode those checks as required needs or preserve an appropriate barrier.
9. Worked decision table
| Scenario | Recommended model | Reason / observable proof |
|---|---|---|
| Five jobs, each test consumes all build outputs | Stages | Barrier matches true dependency; low graph complexity |
| App test waits for unrelated 20-minute docs build | Hybrid needs | Add edge app-test→app-build; prove earlier start + correct artifact SHA |
| Source linter consumes repository only | needs: [] candidate |
Prove no job-produced inputs or policy gate is required |
| Conditional docs job may not exist; summary does not require it | Optional need | Pipeline remains valid in both job-membership cases |
| Conditional producer generates mandatory release metadata | Align rules; required need | Missing producer must prevent consumer, so optional would be incorrect |
| Cross-project artifact fetch needed |
needs:project only after tier/auth/current-data
semantics review
|
Not a same-pipeline scheduling edge; pin ref/identity and understand latest-success behavior |
10. Current-version assumptions to record
- Primary docs verified 2026-09-11.
-
Normal
needs: maximum 50 listed jobs on GitLab.com; Self-Managed/Dedicated default 50 and administrator-configurable. - Same-stage
needsare supported. -
needs: []enters the runnable frontier immediately when the pipeline is created. -
Normal needs artifact transfer is restricted to listed producers;
artifacts: trueis the default. -
Do not combine
needsanddependenciesin the same job. -
needs:projectis Premium/Ultimate and has different wait semantics.
Knowledge check
When are stages preferable to a DAG?
When stage barriers match the real dependencies/policy gates or the latency gain would not justify extra graph complexity.
Why can wider fan-out make a pipeline slower?
It can exceed runner or shared resource capacity, increasing queue time and contention.
What question decides whether optional: true is correct?
Whether the consumer remains semantically correct and has all required inputs when the producer is absent.
Does needs:project wait for another project’s currently running pipeline to finish?
No. Current docs say it downloads from the latest successful specified job for the ref rather than waiting for a concurrent pipeline.
Why should a security check sometimes remain a required dependency even if the deployment artifact already exists?
Because authorization/policy correctness is part of the required state, not just file availability.
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-11. GitLab CI/CD DAG and artifact-transfer semantics are version-sensitive; verify the deployed GitLab version for Self-Managed/Dedicated installations.
-
Make jobs start earlier with
needs— stage barriers, DAG execution, immediate jobs, and practical examples. -
CI/CD YAML syntax reference
— authoritative
stages,needs,needs:artifacts,needs:optional,needs:project, andneeds:pipeline:jobsemantics and limits. -
Pipeline editor
— visualization of jobs, stages, and
needsrelationships plus full configuration inspection. -
CI Lint
— syntax/logic validation and pipeline simulation that can expose
invalid
needsrelationships before execution. -
Job artifacts
— default previous-stage artifact fetching and how
needs:artifactschanges data transfer. - Troubleshooting job artifacts — missing/expired/inaccessible artifact failures.
-
Jobs API
— job IDs, stage/status,
created_at,started_at,finished_at, duration, queued duration, and runner metadata for timing evidence.
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.