Method

2026-10-29

Engineer the Gate: Verification as a Designed System, Not an Accumulation of Checks

Every team's quality gates are an accident of the failures they happened to survive. A gate estate that is engineered instead of accreted is the difference between verification you trust and checks nobody can explain.


Ask an engineering team to draw their quality gates and they will draw a list. Lint. Tests. Validation. Security scan. Maybe a build. The list is ordered by memory, not by design. Every entry arrived on a different day, from a different person, after a different incident.

That is not a gate system. It is a sediment.

A quality gate — a check that decides whether code may land — is a piece of engineering. It has an interface, a cost, a failure mode and a blast radius. Treat it that way and the estate becomes legible: which check protects which invariant, which rung a check belongs on, and what a green line actually promises.

Skip that and you get what most teams have. Several gate styles. Several names for one idea. No way to answer "are we covered?" without reading every build file in every repository.

This is the argument for engineering the gate before building more of them.

Gates Accrete Because Each One Is Locally Rational

No one sits down to design a bad gate estate. Gates accumulate for the best possible reasons.

A release ships a bug a test would have caught: a test is added. A secret reaches a log: a scan is added. A migration breaks a neighbouring system: a verification is added. Each addition is correct in isolation, defended in review, and justified by something that actually happened.

The problem is that the sum is never reviewed. Nobody asks whether the tenth check belongs in the same place as the fourth, whether it runs at the right moment, or whether its name means what the previous nine mean.

What this shows: each gate is defensible on its own. The set never gets reviewed.

The result is measurable. In one estate of twelve repositories, the command that gates a merge — make ci — ran seven checks in two of them, five in one, four in four, two in three, a delegated runner in one, and did not exist in another. Four repositories had no linter of any kind in their gate.

No single decision produced that. Each repository made reasonable local choices. The estate ended up with eight different bodies behind one name.

A Quality Gate Is a Contract, and It Declares Four Things

A companion essay, Quality Is Enforced, Not Hoped For, defines a gate by its three parts: a testable rule, an automated check, and a consequence that stops the flow. That is what a gate is.

This essay asks the next question: what a gate declares to the estate. The three parts can all be present and the gate still confuse everyone who reads its name.

The unit of design is not "the check". It is the gate: the command a person or a machine runs to get a verdict. Every gate declares four things, whether or not anyone wrote them down.

DeclaresThe question it answersWhat goes wrong when it stays implicit
Invariantwhat must be true when this passes?the gate outlives the reason it existed and nobody dares delete it
Scopewhich checks run, and which do not?a green result is read as wider than it is
Verdictpass or fail, on what evidence?a failure cannot be reproduced, or a pass cannot be trusted
Costhow long, and where may it run?a slow gate gets bypassed, and the bypass becomes the standard

What this shows: the contract. A gate that cannot answer one of these is not yet designed.

Write those four down and most gate arguments dissolve. Should this check exist? becomes which invariant does it protect? Where should it run? becomes what does it cost? And the question that opens most gate post-mortems — "why did the deploy fail when everything passed?" — becomes which scope did that green result actually cover?

Scope is where the argument usually lands. It is also where a design decision has to be made next.

The Five Rungs, and What Belongs on Each

A gate estate has rungs, and each rung has a different job. The most common design error is not a missing check. It is a check on the wrong rung, where it is either too slow to run or too late to matter.

What this shows: the five rungs a change passes through, and the budget each one gets.

RungIts jobBudgetFitsDoes not fit
Atomicone concern, checked the moment you want itms–slint, types, formatting, a staged secret scananything needing a database
Commitcatch what the author can still fix cheaplysecondslint on changed files, unit testsfull builds, integration suites
Fullthe shared verdict on a change — what CI runsminutesthe whole gate, integration testsexhaustive matrices, soak tests
Scheduledthe checks too slow for a person's patiencehoursdependency audits, full rebuilds, device matricesanything that must block a merge
Releaseaccountability for what leaves the buildingdeliberatesign-off, staged rollout checksrepetitive mechanical checks

Two design rules follow.

A check lives on exactly one rung. If the same check exists on two, one will drift and nobody will know which is authoritative. If it exists on none, the invariant is unprotected while the team believes otherwise.

The rung's budget is part of the design, not an implementation detail. A ten-minute check on the commit rung teaches people to commit with --no-verify, and that bypass becomes permanent. That is a placement problem, not a discipline problem. The fix is to move the check to the full rung, not to ask for more willpower.

A Worked Example: A Four-Engineer Team, Designed From Nothing

The abstraction is easier to trust with a concrete design. Take a small team shipping a web application with a background worker and a public API — four engineers, one repository, no gate estate yet.

1. Name the invariants first. Before choosing tools, write the five or six sentences the business actually cares about: the API never returns another tenant's data · a migration never breaks the previous release · no credential is committed · every endpoint has a test · the build reproduces from a clean checkout.

2. Place each check on a rung.

InvariantCheckRung
no credential committedsecret scan on staged filesatomic / commit
code style and typeslint and type checkcommit
every endpoint has a testunit and contract testscommit → full
the API never leaks across tenantsauthorisation tests against a seeded databasefull
a migration never breaks the previous releaseapply migrations, then run the previous release's testsfull, then scheduled
the build reproducesclean-checkout buildscheduled

3. Compose one name at the most expensive rung. The full rung gets exactly one entry point — call it ci — and it runs the union of everything placed there. The commit rung gets a different name, and it prints its scope: "lint and unit tests only; ci runs the full gate."

4. Prove each gate can fail. For every check, write down the case that would fail it. A migration check is trusted only after someone has broken a migration on purpose and watched the gate catch it. A gate that has never failed is a hypothesis, not a check.

5. Re-audit at the first sign of drift. The first time someone asks "which command runs everything?", the answer must be one word — not a diagram.

Nothing in that sequence needed a new tool. It needed a decision, made in order: invariant → rung → name → proof.

Seven Rules for Composing a Gate Estate

That sequence designs one estate. These rules keep it one estate as it grows. Each is cheap to check and expensive to omit.

1. One name, one meaning. If a command is called ci, it runs the whole gate — in every repository that has one. A subset gets its own name. A word that means two things is not a word; it is a guess.

2. A slice announces what it skips. Fast commands are worth keeping. They are dangerous exactly to the degree they stay quiet. Before printing a result, a slice states its scope and names the command that covers the rest.

3. The same command locally and in CI. If the local command runs less than the pipeline's, "it passed here" predicts nothing. Saving seconds locally buys a class of failures that only appear after a push, on someone else's clock.

4. A gate proves it ran. A verdict with no count and no evidence cannot be audited. "12 checks passed" can be caught being wrong about twelve. "Passed" can be caught being wrong about nothing.

5. Gates compose by inclusion, defined once. The whole gate is the union of its parts, expressed in one place. When the pipeline and the developer spell out that union separately, they diverge — usually the first time someone is in a hurry.

What this shows: one composition point against six overlapping entry points that all claim to run "the checks".

6. A failure names the fix. A gate that says failed sends its reader to a log. A gate that says this file, this line, this is what to change, here is the document is an instrument. The second kind gets fixed. The first kind gets skipped.

7. Debt is declared, printed and expiring. Some checks cannot exist yet. That is fine. Silence is not: an exemption registry the gate prints on every run keeps a gap from becoming a belief.

Four Anti-Patterns the Design Prevents

A designed estate is easiest to describe by the failures it makes impossible. Each of these is a design defect, not a careless moment.

Anti-patternSymptomDesign fix
Pyramid of entry pointssix commands seem to run "the checks"; people pick the cheapestone name and one rung per check, composition stated once
Gate that reads its own outputreports defects in generated or vendored files that no change can fixdraw the input boundary; ignore built artefacts
Context-sensitive gatedoes more in CI than locallyone behaviour; scope as an explicit argument, never inferred
Copy-paste gatethe same gate in a dozen repositories as a dozen different bodiesone standard, and a conformance check that compares them

Two further classes belong to the companion essay: the gate that cannot fail, and the orphan gate. The orphan is worth restating here, because it belongs to composition as much as to enforcement, and because it is the only one invisible in code review.

A check can exist, be documented, be reviewed — and be invoked by nothing. In the estate measured above, two continuous-integration workflows never called the full gate at all, and one repository had no workflow that ran it. Every one of those gates was real. Every one protected nothing.

Before You Add the Next Check: A Design Review

The next check is always proposed in a hurry, in the middle of an incident. Eight questions, answered in two minutes, keep the estate from absorbing that hurry permanently.

#QuestionA bad answer sounds like
1Invariant — what must be true when this passes?"it catches the bug we just had"
2Rung — which rung, and does its cost fit the budget?"put it in CI, it takes eight minutes"
3Failure case — what change makes this gate fail?"it should never fail, hopefully"
4Evidence — how will we know it ran?"it prints OK"
5Name — does the name mean what the estate already means?"call it check2"
6Home — which repository and file owns it?"copy it into every repo"
7Owner — who fixes it when it fails at 2am?"whoever is on call"
8Retirement — what would make us delete it?"we never delete gates"

Question 8 is the one nobody asks. It is also the reason estates grow monotonically. A gate with no retirement condition is a gate nobody can justify years later, so it stays — and its noise teaches people to ignore the rung it lives on.

Auditing a Gate Estate Takes an Hour

With the design in hand, the audit is mechanical. Five questions, all answerable from the repository, none needing a meeting.

  1. Inventory — what gate commands exist, and what does each contain? One table, one line per repository.
  2. Rungs — for each check, which rung is it on, and does its cost fit that rung's budget?
  3. Names — does every name mean one thing across the estate? Where does a name promise more than its body runs?
  4. Wiring — does CI invoke the whole gate, and only the whole gate?
  5. Liveness — for each gate, name the case that would fail it. If nobody can, the gate is decoration.

The answers are unflattering almost every time. They are also the cheapest engineering work available: a naming rule, a placement decision, and a count.

What a Designed Gate Buys — and What It Costs

It costs time. The design is what keeps that cost bounded: a budget per rung, checks on the rung that suits them, and a fast slice that is honest about being a slice.

An undesigned estate also costs time. It just spends it in the worst place: at the end, on a deploy nobody can explain.

Three things compound once the estate is designed.

Maintainability. When one gate is the union of named parts, changing a check is a local edit rather than archaeology across a dozen build files.

Onboarding. A new engineer — or an AI agent working in the repository — answers "what is verified here?" by reading one table, not by inferring it from a history of incidents.

Trust. A green line means what it says, the same way, every time. That is the only property that makes delegating to automation worth doing, and it is an engineering property, not a cultural one.

The Orchestrator's Takeaway

  • Quality gates are architecture. They have interfaces, costs and failure modes, and they are worth designing on purpose.
  • Decide the invariant, then the rung, then the name, then the proof — in that order.
  • Make fast slices announce what they skip, and run the same command the pipeline runs.
  • Audit the estate with five questions before adding the next check. The tenth check is where incoherence becomes expensive.

The teams that stay fast are not the ones with the most checks. They are the ones whose checks mean the same thing to everyone — including the machine that runs them.

Read next
The engagement

Engineering Strategy & Accelerated Delivery

We help teams leverage modern tooling safely, grounded in strict engineering practice, to reduce time-to-market without accumulating technical debt — and the practice edition of the guide covers the method in full.

See how we work on this

AI
Software Engineering
Quality & Governance
Platform Engineering