Skip to content
All posts
March 18, 20265 min read

Quality Gates in the Release Process: What to Check Before Shipping

A quality gate is a checkpoint that a release must pass before moving to the next stage. Defining clear gates eliminates the 'looks good to me' releases that become production incidents. Here's how to structure them.

TestingReleaseCI/CD
Share:

Most release processes have one gate: "does the developer think it's ready?" That's not a gate. That's optimism.

Quality gates are explicit, measurable criteria that a release must pass before moving forward. They transform releases from subjective calls into objective processes.


What a Quality Gate Is

A quality gate is a defined set of criteria that must be met before a release advances. If any criterion fails, the release stops — automatically or manually.

Examples:

  • All automated tests pass (CI gate — automated)
  • Zero critical bugs open (QA gate — human judgment)
  • Performance metrics within baseline thresholds (metrics gate — automated)
  • Product owner has approved the feature (acceptance gate — human sign-off)

Good gates are:

  • Objective — pass/fail, not "probably fine"
  • Enforced — blocked releases, not optional guidelines
  • Proportionate — don't gate every commit like a major release

Gate 1: The Commit Gate (CI)

Every commit to the main branch passes through automated CI:

  • All unit tests pass
  • All integration tests pass
  • Lint checks pass (no errors)
  • Build succeeds
  • Code coverage doesn't drop below threshold (if configured)

This gate is fully automated. No human involvement. A failing CI blocks the merge.


Gate 2: The QA Gate (Pre-Release)

Before a release candidate is promoted:

  • All stories in the release have been tested
  • Zero open P1 (critical) bugs
  • Zero open P2 (major) bugs (or explicit sign-off to carry over known issues)
  • Regression suite passed
  • New features have been demo'd to product owner

This gate requires human judgment. QA signs off. The sign-off is recorded in the release ticket.

[!NOTE] "Zero P2 bugs" sounds strict. In practice, define what "P2" means precisely. A P2 bug in a corner case feature is different from a P2 bug in the checkout flow. The gate should specify: "zero P2 bugs in the core user journeys."


Gate 3: The Performance Gate

Before each release, performance metrics must be within defined thresholds of the baseline:

MetricBaselineThresholdAction if exceeded
Cold start847ms+15% (< 974ms)Block release
List scroll (P95)14ms/frame+20% (< 17ms)Investigate
Memory at 10 min85MB+10% (< 93MB)Investigate
Crash rate0.3%> 0.5%Block release

Automate the measurement where possible (Android Vitals, Macrobenchmark). Review manually where automation isn't feasible.


Gate 4: The Security Gate

For major releases or releases touching auth/payments:

  • MobSF scan shows no new critical findings
  • No sensitive data in logs (grep check in CI)
  • All network traffic over HTTPS (automated lint check)
  • New permissions are documented and justified

This gate can be partially automated (CI checks for obvious issues) and supplemented with manual review for major releases.


Gate 5: The Staged Rollout Gate

For Play Store releases:

  1. Deploy to internal track → QA team validates on real devices
  2. Promote to closed testing (1-5% of users) → Monitor crash rate for 24 hours
  3. Promote to open testing (10-20%) → Monitor for 48 hours
  4. Promote to production (100%)

Each promotion is a gate:

  • Crash rate < 0.5%
  • ANR rate < 0.1%
  • Rating hasn't dropped (if monitoring)
  • No spike in user-reported issues

Android Vitals provides these metrics automatically.


Automating Gate Checks in CI

yaml
# .github/workflows/ci.yml
- name: Check coverage threshold
  run: |
    COVERAGE=$(./gradlew testDebugUnitTestCoverage | grep "Total coverage" | awk '{print $3}')
    if (( $(echo "$COVERAGE < 70" | bc -l) )); then
      echo "Coverage $COVERAGE% is below 70% threshold"
      exit 1
    fi

- name: Check for debug logs in release code
  run: |
    if grep -r "Log\.d\|Log\.v" app/src/main/ --include="*.kt" | grep -v "//"; then
      echo "Debug logs found in production code"
      exit 1
    fi

When to Skip a Gate

Gates should be skippable for emergencies — but skipping must be:

  1. Explicit (a named person approves the skip)
  2. Documented (recorded in the release ticket)
  3. Followed up (the skipped check runs before the next release)

"Skip it and forget" is how deferred technical debt becomes incidents.


The Gate Summary Document

For each release, create a sign-off document:

markdown
## Release 2.4.1 Sign-Off

**CI Gate:** ✅ All tests passed (build #1234)
**QA Gate:** ✅ Signed off by [QA name] on 2026-03-18
**Performance Gate:** ✅ Cold start 891ms (+5% vs baseline) — within threshold
**Security Gate:** ⚠️ Skipped — approved by [manager] for hotfix
  - Follow-up: Run MobSF scan before 2.5.0
**Rollout Plan:** Internal → 5% → 20% → 100% over 72 hours

This document is the audit trail. If something goes wrong post-release, you know exactly what was checked and what wasn't.


Takeaways

  • Quality gates convert subjective releases into objective, auditable processes
  • Automate what can be automated (CI checks) — reserve human review for judgment calls
  • Every gate has a defined owner and explicit pass/fail criteria
  • Gate skips are allowed but must be documented and followed up
  • Staged rollout is its own gate — never go from 0% to 100% without monitoring intermediary steps
Share:
S

Sudarshan Chaudhari

AI Systems Builder / Product Engineer

Bangkok, Thailand

Solo Android developer with 13+ years in QA, building Android apps, AI automation systems, and developer tools at SudarshanTechLabs.

Stay updated

Get new posts on Android, Kotlin, and solo dev straight to your inbox.

Newsletter preferences

Building something? Available for Android dev and QA consulting.

Work with me

Comments — powered by Giscus