Chapter 14Lesson 03~165 minutes

Parent-Child Pipelines, Dynamic Child Pipelines, Generated Configuration, and Monorepo Decomposition: Configuration, Design Choices, and Tradeoffs

Child pipelines are an architectural choice, not a default optimization. This lesson compares one pipeline with child pipelines, static with dynamic configuration, team-owned subtrees with central controls, and decoupled trigger completion with status mirroring while keeping source identity, trust, cost, and rollback explicit.

Parent-child pipelinesDynamic configurationMonoreposGenerated YAMLPipeline orchestration

Learning objectives

  • Choose a single pipeline or parent-child architecture based on ownership, graph complexity, observability, limits, and rollback cost.
  • Choose static or dynamic child configuration based on determinism, generation inputs, reviewability, and change frequency.
  • Design variable/input forwarding and status strategy deliberately rather than leaking parent state by convenience.
  • Bound fan-out, nesting, generated job counts, runner demand, and artifact/report assumptions.
  • Use a decision table to justify architecture with tier/offering, trust, maintainability, latency, cost, and evidence.

1. Architecture begins with ownership and dataflow, not YAML length

A 2,000-line pipeline is not automatically a child-pipeline candidate, and a 200-line monorepo pipeline is not automatically simple. Decompose when pipeline boundaries reflect meaningful ownership, independent job graphs, or change scopes that can be reasoned about separately.

Keep work in one pipeline when jobs share dense artifact dependencies, require one simple critical path, or would become harder to observe across pipeline boundaries.

2. Single pipeline versus child pipelines

Dimension Single pipeline Parent-child
Graph One graph; simple global visibility Multiple graphs; clearer subsystem boundaries
Source identity One pipeline SHA Shared SHA across hierarchy, distinct pipeline IDs
Artifacts Straightforward same-pipeline needs/dependencies Cross-boundary transfer is separate and may be tier-sensitive
Ownership Central file/graph can become crowded Child files can map to subtree owners
Failure isolation One pipeline status/graph Child failures can be isolated but status coupling must be explicit
Limits/cost One pipeline with many jobs More pipeline records, API/UI/log/runner fan-out
Rollback Revert one config graph Revert parent trigger logic and/or child config/generator

3. Static versus dynamic child configuration

Question Prefer static when… Prefer dynamic when…
Job set Known from repository structure Legitimately computed from bounded metadata
Review Humans should review exact child YAML in Git Generator + emitted YAML can be reviewed/tested deterministically
Change frequency Child shape changes through normal commits Large sparse target set would make static YAML wasteful
Security Minimal configuration-generation surface desired Generator inputs can be strictly validated and output bounded
Evidence Source SHA/path is enough Need generator job/input/generated artifact/digest evidence

4. Per-directory ownership versus central platform controls

A useful monorepo split gives service teams ownership of service-specific tests while retaining organization-wide controls in reviewed reusable layers. Do not let child pipelines bypass central security, runner, release, or deployment policies merely because they live in separate files.

Define the boundary: platform owners maintain the parent routing contract and shared components; service owners maintain child-specific jobs; security-sensitive runners and deployment identities remain centrally governed.

5. Status mirroring versus decoupled creation

Mode Use when Tradeoff
Default trigger behavior Child work may continue independently and parent need only prove creation Parent can become green before child outcome; consumers must not infer completion
strategy: mirror Parent path must wait for and reflect the child result More accurate gating but increases critical-path coupling and can serialize later stages
Legacy strategy: depend Existing compatibility only Current docs recommend mirror instead for new designs

6. Forward less state than you think you need

Use downstream spec:inputs when the child exposes a configuration interface. For variables, start with inherit:variables: false and add only named non-secret values. Pipeline variables are not forwarded by default; if you explicitly enable them, document the precedence and security consequences.

Do not make a child’s behavior depend invisibly on dozens of parent defaults. Hidden inputs destroy portability and make generated configuration impossible to reason about.

7. Fan-out breadth versus queue pressure

A parent that creates 80 children with 20 jobs each has created 1,600 jobs, not “80 small pipelines.” Measure hierarchy count, child job count, runner queue time, artifact/report volume, API activity, and operator readability.

Bound fan-out with allowlisted target sets and a maximum child count. Prefer one child per meaningful ownership/build boundary, not one child per file. Keep the default hierarchy limit as a guardrail instead of designing to its ceiling.

8. Two child levels are enough for most designs

GitLab permits two levels of child nesting. Treat that as a strong signal to avoid recursive orchestration trees. Deep structures make IDs, status, variables, reports, artifacts, ownership, and failure paths harder to correlate.

If you need deeper business orchestration, consider whether the boundary is really another project, a deployment platform, a workflow engine, or a single DAG rather than another child.

9. Reports and artifacts need an explicit contract

Child reports can surface in merge-request views under current GitLab behavior when the parent waits appropriately, but report types and security features can have their own tier constraints. Raw artifacts do not become magically available to the parent or siblings.

Design each child to produce self-contained evidence with producer pipeline/job/SHA. If another pipeline must consume that output, define the transfer mechanism and tier assumption explicitly rather than depending on UI visibility.

10. Worked decision table: three monorepo teams

Requirement Choice Reason/evidence
Three services, each 5–10 jobs, sparse changes Static child per service Clear ownership, simple rules:changes, no generator needed
Hundreds of generated test targets from a small allowlisted manifest Dynamic child with bounded generator Generation is justified; retain manifest + generator SHA + emitted YAML
Build/package/deploy share one artifact chain tightly Single DAG Avoid cross-pipeline artifact complexity; optimize with needs instead
Parent merge gate must fail when child fails strategy: mirror Status contract matches merge-gating intent
Child only sends asynchronous documentation preview Default trigger may be acceptable Parent need not block; UI/ops must treat child separately

11. Tier, trust, and portability assumptions

Core parent-child pipelines, dynamic child pipelines, and status strategy are Free-compatible. Keep the mandatory architecture on this path. Optional cross-parent/child artifact fetching with needs:pipeline:job is currently Premium/Ultimate. Security report types can also carry higher-tier requirements.

On older Self-Managed instances, verify support for strategy: mirror because it was introduced in GitLab 18.2. If unavailable, document the exact compatibility fallback instead of silently teaching newer behavior.

Knowledge check

When should a dense build/package artifact chain stay in one pipeline?

What is the strongest reason to choose dynamic child configuration?

Why can strategy: mirror increase pipeline latency?

Why is one child per changed file usually a bad design?

What should be written down when pipeline variables are forwarded?

Next lesson

Diagnostics, failure modes, security, and performance

Preserve hierarchy evidence and diagnose generation, rules, status, artifact, forwarding, and fan-out failures causally.

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. Parent/child pipeline syntax, downstream status behavior, report visibility, hierarchy limits, inputs, and variable forwarding are version-sensitive. Re-check the deployed GitLab version before relying on newer syntax such as strategy: mirror.

Current behavior used by this chapter: parent-child pipelines are available on Free/Premium/Ultimate and GitLab.com/Self-Managed/Dedicated. Child pipelines run in the same project, ref, and commit SHA as the parent and report CI_PIPELINE_SOURCE=parent_pipeline. Nested child pipelines are limited to two child levels; the default pipeline hierarchy limit is 1000 downstream pipelines. One child trigger can combine up to three child configuration files. Dynamic child configuration can come from a generated artifact; the artifact path is interpreted by the GitLab server, and CI/CD variables cannot be used in an include section inside the dynamic child configuration. strategy: mirror was introduced in GitLab 18.2 and is the recommended status-coupling strategy; without a strategy the trigger job succeeds once the child is created. YAML-defined trigger variables forward by default, while pipeline variables do not unless trigger:forward:pipeline_variables: true is set. needs:pipeline:job for cross-parent/child artifact download is currently Premium/Ultimate, so mandatory labs do not depend on it.

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.