How do parent-child pipelines work in GitLab and when should you use them instead of regular multi-stage pipelines?
Quick Answer
Parent-child pipelines use the trigger keyword with include to dynamically generate and run downstream pipelines as child pipelines of the current pipeline. The parent pipeline creates child pipelines that appear nested in the UI, share the same project context, and can pass variables and artifacts between them. They are ideal for monorepos and dynamically generated pipeline configurations.
Detailed Answer
Think of parent-child pipelines like a general contractor managing a home renovation. The general contractor (parent pipeline) does not personally install the plumbing, electrical, and cabinetry. Instead, they hire specialized subcontractors (child pipelines) for each trade, hand them the blueprints (variables and artifacts), and coordinate the overall project. Each subcontractor works independently, has their own team and schedule, but reports back to the general contractor who decides whether the renovation is complete. If the plumber finds a problem, the general contractor can halt the electrician before they start work.
Parent-child pipelines are created when a job in the parent pipeline uses the trigger keyword with include to reference a YAML file that defines the child pipeline's configuration. The child pipeline runs within the same project but as a separate pipeline instance with its own jobs, stages, and status. The parent job that triggered the child pipeline reflects the child's status: if the child pipeline fails, the parent trigger job also fails (unless strategy: depend is not set, in which case the parent job succeeds immediately after triggering). You can have up to two levels of nesting (a child can trigger a grandchild), and a parent can trigger multiple children. Child pipeline configurations can be dynamically generated by a preceding job, where a script creates a YAML file and the trigger job uses artifact to reference it. This dynamic generation is the killer feature that enables truly flexible CI/CD architectures.
Internally, when GitLab encounters a trigger job with include, it reads the referenced YAML file, parses it as a complete pipeline configuration, creates a new pipeline record linked to the parent pipeline as a child, and begins executing its jobs independently. The child pipeline has its own pipeline ID, its own set of stages, and its own Runner assignments. The parent pipeline's trigger job enters a waiting state (if strategy: depend is set) and monitors the child's status. Variables can be passed from parent to child using the variables keyword in the trigger block, and artifacts from the parent pipeline's jobs can be consumed by the child if the trigger job specifies needs or the artifacts are from previous stages. The child pipeline appears nested under the parent in the GitLab UI's pipeline view, providing a clear visual hierarchy. Pipeline status propagation ensures that the overall parent pipeline reflects the worst status of any child.
In production, parent-child pipelines shine in monorepo architectures. Consider a company with a commerce-platform repository containing frontend/, api/, worker/, and infrastructure/ directories. The parent pipeline has a detect-changes job that runs a script to determine which directories have modified files. It then generates child pipeline YAML dynamically based on the changes. If only frontend/ files changed, only the frontend child pipeline runs, skipping api/, worker/, and infrastructure/ entirely. This can reduce a 45-minute full-pipeline run to a 10-minute targeted run. A real implementation at a company like Shopify or GitLab itself uses this pattern to handle hundreds of components in a single repository, where running all possible jobs on every commit would consume enormous Runner capacity and developer time. The parent pipeline serves as the orchestrator, and each child pipeline is a self-contained build-test-deploy sequence for its component.
A critical gotcha is the artifact passing behavior between parent and child pipelines. By default, child pipelines do not automatically receive artifacts from the parent. You must explicitly pass variables and ensure the child pipeline's jobs reference the parent job's artifacts via needs:pipeline. Another common mistake is not setting strategy: depend on the trigger job, which causes the parent to show success even if the child fails, breaking the pipeline status chain. Also, be aware of the depth limit: GitLab allows a maximum of two levels of pipeline nesting (parent -> child -> grandchild). Attempting to trigger a pipeline from a grandchild will fail. For complex orchestration beyond two levels, use multi-project pipelines instead.