A reliable CI/CD pipeline does more than move code from a repository to production. It creates a sequence of evidence-based decisions that helps a team identify defects, security risks, configuration errors, and operational hazards before they affect users. This guide explains how to design practical CI/CD quality gates for small and growing engineering teams, including where to place automated tests, infrastructure validation, approvals, progressive delivery, and rollback controls.
Overview
A quality gate is a defined condition that a change must satisfy before the pipeline can continue. Some gates are automated, such as a failed unit test or a critical vulnerability finding. Others involve human judgment, such as approving a production deployment during a high-risk release window.
The goal is not to make every pipeline slow or difficult to pass. The goal is to put the right check at the right point in the delivery process. Fast, deterministic checks should run early. Expensive or environment-dependent checks should run after the change has passed basic validation. Production gates should focus on deployment safety, observability, and the ability to recover.
A useful pipeline usually separates these concerns:
- Change validation: Does the code compile, format correctly, and pass its automated tests?
- Security validation: Does the change introduce known dependency, secret, code, or image risks?
- Integration validation: Does the application work with its required services and interfaces?
- Infrastructure validation: Can the proposed infrastructure or configuration change be safely applied?
- Release validation: Is the target environment ready, and is the change suitable for promotion?
- Operational validation: Does the deployment behave normally after release, and is rollback available?
Teams should also define what happens when a gate fails. A failed check should identify the reason, preserve useful logs or reports, and provide a clear path to correction. A gate that is routinely bypassed is usually a sign that its threshold, ownership, or position in the pipeline needs review.
Step-by-step workflow
1. Establish a fast commit gate
Begin with checks that provide quick feedback on every pull request or change proposal. Typical checks include formatting, linting, type checking, compilation, unit tests, and basic policy validation. These checks should be repeatable and should not depend on a shared environment that can become unavailable.
Keep this stage focused. If a test requires a database, external API, or lengthy build process, it may belong in a later stage. The first gate should answer a simple question: is this change structurally sound enough to examine further?
2. Add security checks before artifact promotion
Security scanning should be integrated into the normal delivery path rather than treated as a final inspection. Depending on the application, this can include dependency checks, secret detection, static analysis, container image scanning, and checks for unsafe configuration.
Define an explicit response for findings. For example, a pipeline may block a release for a confirmed critical issue while recording lower-severity findings for review. The exact threshold depends on the system and its risk profile, but the decision should be documented and consistent. For a deeper treatment of application and environment checks, see Preprod Security Scanning: SAST, DAST, and Dependency Checks That Matter.
3. Build a versioned, traceable artifact
After the change passes early validation, build the deployable artifact once and promote that same artifact through later environments. This might be a container image, package, binary, or static bundle. Rebuilding separately for staging and production can create differences that the earlier checks did not cover.
Attach useful metadata to the artifact, such as the source revision, build result, dependency information, and configuration version. This makes it easier to answer which code is running, which checks it passed, and which release should be restored if a problem appears.
4. Run integration and contract tests
Integration tests verify that components work together. Contract tests can check whether an API provider and consumer agree on request and response behavior. Database migration tests, queue processing tests, and authentication flows may also belong here.
Use test environments that resemble the intended deployment closely enough to expose meaningful failures. The environment does not need to duplicate production in every detail, but differences in service versions, permissions, network rules, or data shape should be understood rather than accidental.
5. Validate infrastructure and deployment configuration
Infrastructure as code should pass formatting, syntax, validation, policy, and plan checks before an apply operation is allowed. Review the proposed change for unexpected resource replacement, permission expansion, networking changes, and data-loss risk.
For teams using Terraform or a similar tool, keep the plan available as a review artifact and separate planning from applying where that improves control. The Infrastructure as Code with Terraform guide provides a useful companion workflow for project structure and troubleshooting.
6. Promote through controlled environments
Deploy the approved artifact to an appropriate non-production environment and run smoke tests, integration checks, and environment-specific validation. Keep promotion rules clear when moving from staging or pre-production toward production. The distinctions between these environments should be intentional, including their data, access controls, dependencies, and operational purpose. See Staging vs Preproduction vs Production for a promotion checklist.
A manual approval can be appropriate before production when the release has elevated risk, changes customer-facing behavior, or requires coordination with operations. Approval should confirm evidence, not replace it. The reviewer should be able to see the test results, security findings, deployment plan, expected impact, monitoring plan, and rollback procedure.
7. Use progressive delivery and automatic rollback where practical
For systems that support it, release to a limited audience or traffic slice before completing the rollout. Monitor error rates, latency, availability, resource consumption, and important business or workflow signals. Define a measurement window and thresholds before deployment begins so the team is less likely to rationalize a poor result after the fact.
Rollback should be treated as a tested workflow rather than an emergency theory. Depending on the system, rollback may mean restoring a previous artifact, shifting traffic, disabling a feature flag, or applying a forward fix. Database changes require particular care because an application rollback may not reverse an incompatible schema change. Teams can rehearse this process using the guidance in Preprod Incident Response.
Tools and handoffs
The specific CI/CD platform matters less than the clarity of the workflow. GitHub Actions, GitLab CI, hosted build systems, and self-managed runners can all support the same underlying pattern: events trigger jobs, jobs produce evidence, and promotion rules use that evidence.
Keep ownership visible at each handoff:
- Developers own code quality, unit tests, and the initial description of risk.
- Security or platform specialists maintain scanning rules, baseline policies, and exception processes.
- Infrastructure owners review resource, permission, networking, and data changes.
- Release or service owners decide whether the evidence supports promotion and confirm the rollback plan.
- Operations and SRE teams define post-deployment signals and help investigate abnormal behavior.
Pipeline outputs should be easy to find. Store test reports, scan results, deployment plans, artifact identifiers, approval records, and post-deployment observations with the relevant change or release. Avoid requiring someone to search across unrelated systems to reconstruct why a deployment was approved.
Quality checks
Use the following questions when reviewing a CI/CD pipeline:
- Do fast checks run before slower environment-dependent checks?
- Does the pipeline build once and promote an identifiable artifact?
- Are critical security findings and exposed secrets handled automatically?
- Are integration tests representative of the dependencies that matter?
- Can infrastructure changes be reviewed before they are applied?
- Are production approvals based on visible evidence rather than habit?
- Are deployment health signals defined before progressive delivery begins?
- Can the team disable, roll back, or correct a release without guessing?
- Are exceptions time-bound, owned, and recorded?
Measure the pipeline as a delivery system. A gate that catches defects is valuable, but a gate that produces constant false positives can encourage bypasses. Review failure patterns, queue time, execution time, flaky tests, manual wait states, and rollback frequency. Improve the weakest part of the workflow instead of adding checks indiscriminately.
When to revisit
Review the pipeline whenever the application architecture, deployment platform, compliance needs, or team ownership changes. A new database, external integration, container base image, Kubernetes deployment model, or infrastructure provider can create risks that the existing gates do not cover.
Also revisit the workflow after a failed release, production incident, security finding, repeated flaky test, or emergency bypass. Ask which signal was missing, which gate appeared too late, and whether the response was clear enough under pressure. Update thresholds, documentation, ownership, and rollback procedures together.
A practical next step is to map the current pipeline on one page. List every stage, its purpose, its owner, its pass condition, its evidence, and its failure response. Then identify one high-value improvement, such as adding infrastructure plan review, promoting a single immutable artifact, or defining automated rollback thresholds. Small, deliberate changes make a CI/CD pipeline safer without turning delivery into an obstacle course.