Speed Up GitLab CI/CD with DAG Pipelines Using the needs Keyword
Learn how GitLab's needs keyword creates DAG pipelines that let jobs run as soon as their prerequisites finish, reducing idle time and speeding up delivery.
05 Oct 2026, 00:45 UTC

The problem: linear stages waste time
In a typical GitLab CI/CD configuration, jobs are grouped into stages (e.g., build, test, deploy). All jobs in a stage must finish before any job in the next stage can start, even if a later job only depends on a single earlier artifact. When one test job is slow, the entire pipeline waits, leaving runners idle and increasing wall‑clock time.
Thesis: the needs keyword creates a DAG that lets independent jobs run as soon as their prerequisites are satisfied
GitLab’s needs keyword overrides stage ordering for execution timing. A job listed in needs can start when the referenced jobs have completed, regardless of their stage. This produces a Directed Acyclic Graph (DAG) where fast‑tracked jobs (like a deploy) can begin immediately after the build, while slower tests continue in parallel.
Worked example: deploying after build, ignoring a slow test
Consider a repository with three stages: build, test, and deploy. The test stage contains a fast unit‑test job and a slow integration‑test job. We want the deploy job to run as soon as the build finishes, without waiting for the slow integration test.
# .gitlab-ci.yml
stages:
- build
- test
- deploy
build_job:
stage: build
script:
- echo "Building application"
- make build
artifacts:
paths:
- dist/
fast_test:
stage: test
script:
- echo "Running unit tests"
- make test-unit
slow_test:
stage: test
script:
- echo "Running integration tests (takes ~10 min)"
- make test-integr
deploy_job:
stage: deploy
script:
- echo "Deploying to staging"
- make deploy
needs:
- job: build_job
artifacts: true
In this configuration:
build_jobruns first.- As soon as
build_jobfinishes,deploy_jobstarts, pulling thedist/artifact. fast_testandslow_testrun in parallel with the deploy, because they are in theteststage but are not required bydeploy_job.
When you view the pipeline graph in GitLab’s UI, you will see deploy_job positioned after build_job but before the completion of slow_test, illustrating the DAG behavior.
Trade‑offs and limitations
While needs can cut idle time, it introduces complexity:
- Dependency visualization: A web of
needslinks can be hard to follow without regularly checking the pipeline graph. - Stage membership remains: Jobs still belong to a stage for purposes like resource groups or stage‑level
allow_failure; the stage label does not disappear. - Race‑condition risk: If a job expects an artifact that is uploaded asynchronously, ensure the artifact is defined in the
needsentry (artifacts: true) so GitLab waits for the upload before starting the dependent job.
Start with a small, well‑defined dependency (as in the example) and expand only after you verify the graph looks as expected.
Actionable closing
To adopt DAG pipelines in your project:
- Identify jobs that could start earlier than their stage allows (e.g., deploy, packaging, or notification jobs).
- Add a
needsclause referencing the prerequisite job(s) and setartifacts: trueif you need their outputs. - Commit the
.gitlab-ci.ymland watch the pipeline graph; verify that the dependent job appears as soon as its prerequisites finish. - Monitor pipeline duration over several runs to confirm the expected reduction in wall‑clock time.
By gradually applying needs where dependencies are clear, you can keep pipelines fast without sacrificing readability or introducing hidden race conditions.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.