Using GitLab CI needs to Build DAG‑Style Pipelines
Learn how the `needs` keyword lets jobs start as soon as their prerequisites finish, enabling parallel execution and shorter pipeline runs.
23 Dec 2025, 02:37 UTC

Problem: Waiting for whole stages slows down pipelines
In a typical .gitlab-ci.yml file, jobs are grouped into stages. Even if a downstream job only needs the output of one upstream job, GitLab will hold it back until every job in the preceding stage finishes. This can leave idle runners and increase total pipeline time, especially when you have independent tasks like linting, unit tests, and builds.
Thesis: The needs keyword creates a directed acyclic graph (DAG) that lets jobs run as soon as their declared dependencies finish, cutting idle time.
How needs works
- Add
needs: [job-name]to a job to declare that it depends on the completion ofjob-name. - The job becomes eligible to start immediately after
job-namefinishes, regardless of the stage boundary. - By default, GitLab downloads all artifacts from each needed job before the dependent job starts. Setting
artifacts: falseskips this download when you only need the execution order. - The pipeline graph in the Merge Request or Pipelines UI shows an edge for each
needsrelationship, making the dependency flow visible.
Worked example: Parallel lint, test, and build
Suppose you have three independent jobs that should run before a final deploy job:
stages:
- lint
- test
- build
- deploy
lint:
stage: lint
script: echo "Running linter"
artifacts:
paths:
- lint-report.txt
unit-test:
stage: test
script: echo "Running unit tests"
artifacts:
paths:
- test-report.xml
build:
stage: build
script: echo "Building application"
artifacts:
paths:
- dist/
# Deploy waits for all three to finish, but each can start as soon as its predecessor ends
deploy:
stage: deploy
needs:
- job: lint
artifacts: true # we want the lint report
- job: unit-test
artifacts: false # we only need the test to run, not its artifacts
- job: build
artifacts: true
script: echo "Deploying..."
In this configuration:
lint,unit-test, andbuildare in different stages, butdeploydoes not wait for the entireteststage to finish; it starts right afterunit-testends.- The
unit-testneed specifiesartifacts: false, so GitLab skips downloading the test report, reducing job start‑up time. - When you view the pipeline graph, you will see three edges pointing into
deploy—one from each needed job—clearly illustrating the DAG.
Verification steps
- Add the
needsblock to your.gitlab-ci.ymland commit the change to a branch. - Trigger a pipeline (e.g., by pushing the branch or running a manual pipeline).
- Open the pipeline details page and select the Graph tab. Verify that edges match the
needsdeclarations you wrote. - Check the job logs for
deploy. If you setartifacts: falseon a need, you should see no message about downloading artifacts from that upstream job. - Compare total pipeline duration with a version that omits
needs(i.e., relies only on stage ordering). You should observe a shorter wall‑clock time when the DAG is used.
Trade‑offs and limitations
- Stage membership remains: Jobs still belong to a stage for visual grouping;
needsonly influences start time, not stage assignment. - Complexity growth: Adding many
needslinks can make the pipeline graph harder to follow, especially when failures propagate across non‑sequential edges. - Artifact transfer overhead: Even when you need only the execution order, the default behavior downloads artifacts. Forgetting to set
artifacts: falsecan add noticeable start‑up latency, particularly for large build outputs. - Cross‑project needs (not shown here) require CI job tokens or project access, introducing external dependencies that affect pipeline portability.
Actionable closing
Start by identifying jobs in your pipeline that only need a single upstream output. Add a needs clause with artifacts: false if you don’t require the artifacts, then verify the pipeline graph and job logs as described. This incremental move toward a DAG‑style layout often reduces idle runner time without major refactoring, and you can expand the graph gradually as you become comfortable with the dependency tracking.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.