Timothy D Beach
← Writing

April 29, 2026 · Software engineering

Pipeline vs Harness

Two words that sound similar, get used loosely, and actually mean different things. Short version up top, then the nuance.

TL;DR

  • Pipeline = work moves through stages. The thing being processed flows; the stages are fixed.
  • Harness = the system stays put; the harness wraps it to run/test/drive it. The wrapper is active, the wrapped thing is acted upon.

A pipeline is a conveyor belt. A harness is a jig (or a horse's harness — same root metaphor).

Pipeline

Colloquial sense

A series of stages where the output of one step is the input of the next. Linear, directional, often automated. Borrowed from oil/water pipelines: stuff goes in one end, comes out the other, transformed along the way.

Technical instances we actually use

  • CI/CD pipelinelint → build → test → deploy. GitHub Actions, Jenkins, GitLab CI.
  • Data pipeline / ETLextract → transform → load. Airflow, dbt, Dagster.
  • Unix pipescat foo | grep bar | sort | uniq -c. The original.
  • ML training pipelineingest → featurize → train → evaluate → register.
  • Compiler pipelinelex → parse → typecheck → optimize → codegen.
  • Render pipeline — vertex shader → fragment shader → framebuffer.

Defining traits

  1. Directional flow — work moves forward through ordered stages.
  2. Stage isolation — each stage has a clear input contract and output contract.
  3. Transformation-centric — the thing (data, code, artifacts) is what changes.
  4. Often parallel-fan-out / fan-in — but still graph-shaped, not loopy.
  5. Stateless-ish stages — re-runnable, cacheable, idempotent when done well.

When someone says "the pipeline broke," they mean a stage failed and the artifact didn't make it to the next stage.

Harness

Colloquial sense

A thing that wraps around another thing to control it, hold it in place, or drive it. Horse harness, climbing harness, wiring harness. The harness doesn't become the horse — it constrains and directs the horse.

Technical instances we actually use

  • Test harness — the scaffolding that sets up fixtures, invokes the code under test, captures output, asserts. JUnit, pytest, RSpec. The harness is what makes a function testable in isolation.
  • Agent / LLM harness — the loop and machinery around a language model: prompt assembly, tool dispatch, context management, retries, hooks. Claude Code is a harness around Claude. The model is the engine; the harness is the chassis.
  • Hardware test harness — physical bench rig that powers a board, drives its inputs, measures its outputs.
  • Wiring harness — bundled cables that connect a system together (cars, aircraft).
  • Fuzzing harnessLLVMFuzzerTestOneInput(...) — a thin wrapper that hands fuzzer-generated bytes to the code being fuzzed.
  • Benchmark harness — JMH, criterion.rs. Wraps the code, runs it many times under measured conditions.

Defining traits

  1. Wraps a system under operation — the wrapped thing (function, model, board, binary) is the subject; the harness is the apparatus.
  2. Control loop / driver — usually has its own event loop, timing, or invocation logic.
  3. Instrumentation — captures, observes, asserts, measures.
  4. Lifecycle ownership — sets up, tears down, isolates the system under test/run.
  5. Often stateful — maintains context across invocations of the wrapped thing.

When someone says "the harness is flaky," they mean the wrapper itself (setup, teardown, env) is broken — not the code being exercised.

The overlap zone (where people mix them up)

Term you'll hear Which is it really?
"Test pipeline" A pipeline of stages (lint → unit → integration → e2e). Each stage may use a test harness.
"Test harness" The framework that runs an individual test — fixtures, asserts, mocks.
"Inference pipeline" Data flows: input → preprocess → model → postprocess → output.
"Agent harness" Loop wrapping an LLM with tools and context. Not a pipeline — has cycles, branching, persistent state.
"Build pipeline" Stages: compile → link → package → sign → publish.
"Build harness" Less common; would mean the rig that invokes the build (e.g., a meta-builder driving many sub-builds).

Rule of thumb

  • If you can draw it as a DAG of stages with artifacts moving left-to-right → pipeline.
  • If you can draw it as a box wrapping another box, with a control loop and instrumentation → harness.
  • They compose: a CI pipeline runs a stage that invokes a test harness to exercise the code.

Why the distinction matters for our work

  1. Debugging triage — "the pipeline failed at the test stage" vs "the test harness is hanging" point at very different failure modes. One is an artifact problem (build broken, deps missing), the other is an environmental/wrapper problem (fixture setup, teardown leaking).
  2. Design choices — when building automation, ask: am I moving artifacts through stages (pipeline) or driving a system to observe its behavior (harness)? The shapes are different. Pipelines want orchestrators (Airflow, GHA). Harnesses want runners and drivers (pytest, custom loops).
  3. LLM-era specifically — "agent" work is overwhelmingly harness work. Claude Code, Cursor, the Claude Agent SDK — they are all harnesses around a model. Calling them pipelines obscures that the central thing is a loop with state and tool dispatch, not a feed-forward flow.

One-line mnemonic

A pipeline transforms what flows through it. A harness controls what sits inside it.