Skip to content

Quality Gates

A quality gate is a criterion that must be met before work proceeds to the next stage. Its purpose is to make the standard explicit and automatic, so that it does not get renegotiated at the moment it is most inconvenient.

graph LR
    W[Work] --> G{Gate criteria met?}
    G -->|yes| NEXT[Proceed]
    G -->|no| BACK[Stop, fix, retry]

Gates along the path

Gate Typical criteria
Definition of ready Acceptance criteria that can pass or fail, dependencies known, small enough to finish
Pull request Tests pass, review approved, no new high-severity static findings, coverage of changed lines maintained
Merge to main Integration suite green, contracts verified, build reproducible
Release candidate Key journeys pass, no open critical or high defects, performance budgets met, security scan clean
Deployment Smoke checks pass after deploy, rollback tested and available
Definition of done Tested, documented, deployed, monitored, and no known critical defects

What makes a gate work

graph TD
    G[Effective gate] --> O[Objective: no interpretation needed]
    G --> A[Automated: runs without being remembered]
    G --> F[Fast: does not tempt anyone to bypass it]
    G --> R[Relevant: correlates with real risk]
    G --> E[Enforced: bypassing is visible and rare]

An unmet criterion must actually stop the work. A gate that is routinely overridden is not a gate, it is a warning message with extra ceremony, and its existence gives false assurance to everyone reading the process document.

Choosing criteria that survive contact

Weak criterion Better criterion
Code quality is acceptable No new high-severity static analysis findings
Sufficient test coverage Coverage of changed lines at or above the threshold
Performance is adequate Key endpoint p95 not regressed by more than 10% against baseline
Security has been considered No new critical or high vulnerabilities in dependencies
Testing is complete All planned high-risk conditions executed, remaining risks recorded and accepted

Gate on the delta wherever possible. A project-wide coverage threshold on a legacy codebase is either impossible or gamed, whereas "do not make the changed lines worse" is fair, achievable and still improves the codebase over time.

Failure modes

Failure Effect
Too many gates The pipeline becomes slow, and people batch changes to avoid it
Subjective criteria Arguments at the worst possible moment
Routine overrides The gate stops meaning anything, but the process document still claims it
Vanity metrics Effort goes to the number rather than to the risk, for example coverage farming
Gates without owners A red gate nobody owns stays red
Late-only gates All the friction lands just before release, which is where schedules break

The last one is worth stating plainly: gates should be distributed along the path, weighted early. A single large gate before release is a phase gate, and it produces exactly the crunch that shift-left exists to avoid.

Keeping them honest

  • Review the criteria periodically. A gate that has never failed is either redundant or set too low.
  • Track overrides. A rising override rate is the earliest signal that a gate is mis-tuned or too slow.
  • Tie each gate to a risk. If nobody can say which failure a gate prevents, delete it.
  • Automate the evidence, not the judgement. Where a human decision is genuinely needed, such as accepting residual risk, record who accepted it and what they accepted.

Check Your Understanding

#

What distinguishes a real quality gate from a warning?

#

Why prefer gating on a delta rather than an absolute value?