Skip to main content
RunBook Academy

Git, CI/CD & GitOpsXLVII · Pipeline DependenciesTopology

Fan-in and fan-out — parallelism at job boundaries

Intermediate⏱ ~20 mingit

What you'll learn

  • Identify fan-out, fan-in, and diamond shapes in a pipeline DAG
  • Predict the wall-clock cost of each shape
  • Design a DAG that maximises parallelism by minimising unintended fan-in
  • Recognise that the fan-in point is the synchronisation that determines pipeline duration

Prerequisites

Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x

Not yet marked complete on this device.

Three DAG shapes recur in every pipeline: fan-out, fan-in, and diamond. They are the vocabulary for reading and writing DAGs.

Fan-out

Fan-out is one job whose completion enables many successors.

flowchart LR
    B["build"] --> U["unit"]
    B --> I["integration"]
    B --> SC["scan"]

build runs first; the three start as soon as it completes and a runner is free. Cost is max(unit, integration, scan).

Fan-in

Fan-in is many predecessors whose completion enables one successor. The successor starts only when every predecessor has completed.

flowchart LR
    U["unit"] --> PKG["package"]
    I["integration"] --> PKG
    C["contract"] --> PKG

package waits for all three. Wall-clock cost is max(unit, integration, contract).

Diamond

Diamond is fan-out followed by fan-in.

flowchart LR
    B["build"] --> U["unit"]
    B --> I["integration"]
    U --> DP["deploy"]
    I --> DP

Cost is build + max(unit, integration) + deploy.

Parallelism at boundaries

Parallelism is bounded by the DAG, the runners, and concurrency:.

concurrency:
  group: ${ github.workflow }-${ github.ref }
  cancel-in-progress: true

concurrency: for cross-run; DAG for within-run.

Designing DAGs

flowchart LR
    B1["build"] --> T1["test-a"]
    B1 --> T2["test-b"]
    B1 --> T3["test-c"]
    T1 --> D1["deploy"]
    T2 --> D1
    T3 --> D1
  1. Maximise parallelism early.
  2. Synchronise at boundaries.
  3. Serialise mutations with needs:.

Production discipline

  1. Identify fan-in and slowest predecessor.
  2. Optimise slowest predecessor first.
  3. Avoid fan-in to jobs not needing all predecessors.
  4. concurrency: for cross-run; DAG for within-run.

Cross-course references

  • Ansible for Production Sysadmins - Part XXXVII applies fan-out/fan-in to AWX.
  • Linux for Production Sysadmins - Part XXX uses diamond for systemd.

Quiz

Knowledge check · 4 questions

  1. Q1. A diamond has build (2 min), two parallel test jobs (1 min and 8 min), and a deploy (2 min). What is the wall-clock cost?

  2. Q2. A fan-in target's wall-clock start time is bounded by its slowest predecessor, not by the sum of its predecessors.

  3. Q3. Name the three DAG shapes and identify which one is the synchronisation point that bounds the pipeline's wall-clock duration.

  4. Q4. Identify the bottleneck in a diamond and recommend the optimisation.

    Pipeline: build (2), unit (1), integration (8), scan (3), deploy (2). Diamond: build -> (unit, integration, scan) -> deploy. Total: 15 min.

Passing score: 75%. Answers are checked in this browser.