Chapter 09Lesson 03~150 minutes

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.

Design tradeoffsneeds:optionalFan-outCross-pipelineAuditability

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.

Prefer the simplest graph that is both correct and observable. A reviewer should be able to answer “why can this job start now?” without reconstructing hidden dataflow from scripts.

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
Correctness test: ask “If docs_quality is absent, is summary still semantically valid?” If the answer is no, fix rule alignment instead of setting optional true.

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
The mandatory Chapter 09 lab uses only ordinary same-pipeline 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.

Never optimize around a security gate by making a privileged/deployment job depend only on its build artifact. Required authorization and quality/security gates are dependencies too.

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 needs are supported.
  • needs: [] enters the runnable frontier immediately when the pipeline is created.
  • Normal needs artifact transfer is restricted to listed producers; artifacts: true is the default.
  • Do not combine needs and dependencies in the same job.
  • needs:project is Premium/Ultimate and has different wait semantics.

Knowledge check

When are stages preferable to a DAG?

Why can wider fan-out make a pipeline slower?

What question decides whether optional: true is correct?

Does needs:project wait for another project’s currently running pipeline to finish?

Why should a security check sometimes remain a required dependency even if the deployment artifact already exists?

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, and needs:pipeline:job semantics and limits.
  • Pipeline editor — visualization of jobs, stages, and needs relationships plus full configuration inspection.
  • CI Lint — syntax/logic validation and pipeline simulation that can expose invalid needs relationships before execution.
  • Job artifacts — default previous-stage artifact fetching and how needs:artifacts changes 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.
Next lesson

Stages, needs DAGs, Dependency Graphs, Early Execution, and Pipeline Critical-Path Design: Diagnostics, Failure Modes, Security, and Performance

Diagnose graph failures from preserved evidence: premature consumers, accidental serialization, invalid edges, missing producers, and queue pressure.

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.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.