Where to Put Quality Gates in Your Pipeline Matters More Than What You Scan
You push a commit. The pipeline starts. You wait. And wait. After fifteen minutes, the pipeline fails because of a low-severity vulnerability in a library your code doesn't even use. You fix it, push again, and wait another fifteen minutes.
This is the cost of putting every quality gate at the same point in the pipeline. The alternative is just as frustrating: all scans run at the very end, right before production. Your code passes build, unit tests, integration tests, and staging. Then it fails because a hardcoded secret was sitting in a config file since the first commit. You just wasted hours of pipeline time on something that could have been caught in seconds.
The position of each gate determines two things: how fast developers get feedback, and how much time and compute you waste when something fails. Getting this right is not about choosing between speed and security. It is about ordering checks so both work together.
Fast and Light Goes First, Heavy Goes Later
The basic principle is simple: quick, lightweight checks run early in the pipeline. Heavy checks that need more context run later. But this is not about splitting scans into two groups. Each type of scan has a natural place where it gives the most value with the least friction.
The diagram below maps each gate to its recommended pipeline stage:
Secret Scan: Run Before Build
Secrets should be detected before anything gets built. Once a secret is baked into a container image or an artifact, removing it becomes much harder. The image might already be pushed to a registry, pulled by other systems, or deployed to an environment. Even if you delete the image, the secret could be cached or logged somewhere.
Run secret scanning right after code checkout, before any build step. If the pipeline finds a hardcoded API key or database password, the developer gets immediate feedback. They fix the file, push again, and the pipeline restarts without having waited for a build that would have been wasted anyway.
Dependency Scan: Before Artifact Creation
Dependency scanning checks the libraries your project pulls in. It needs the dependency manifest file, which is available right after checkout. The natural place for this scan is after checkout but before the artifact is built.
If a newly added library has a critical vulnerability, the pipeline fails early. The developer does not wait for a build, unit tests, or integration tests. They fix the dependency and push again. This is the essence of early feedback: fail fast on problems that are cheap to fix.
Some dependency scanners are fast enough to run before build. Others are slower. If your scanner takes several minutes, consider running it on every commit for the main branch only, and on pull requests for feature branches. This keeps feedback fast for daily work while still catching issues before they reach production.
Container Image Scan: After Build, Before Registry
Container image scanning is different. You cannot scan an image until it exists. The right place is after the image is built, before it is pushed to a registry or used in any environment.
If the image contains vulnerabilities, the pipeline stops here. The image never reaches staging or production. This is important because once an image is in a registry, other pipelines or teams might pull it. Stopping the pipeline at this point prevents vulnerable images from spreading.
The trade-off is that image scanning takes time. If your team pushes many commits per day, running full image scans on every commit can slow the pipeline significantly. One common approach is to run a quick scan on every commit and a full scan on merges to the main branch. Another is to cache scan results and only rescan when the base image or dependencies change.
IaC Scan and Policy Check: Two Places, Two Purposes
Infrastructure as Code scanning and policy checks can run at two different points, and each serves a different purpose.
First, run them when the infrastructure code is written. This gives developers fast feedback while they are still working on the configuration. They do not need to wait for a full pipeline run to know that a security group rule is too permissive or that a storage bucket is publicly accessible.
Second, run them again before the configuration is applied to an environment. This is the compliance gate. Even if the developer ignored the earlier warning, the pipeline enforces the policy before any infrastructure changes take effect.
The first gate is for developer convenience. The second is for compliance certainty. Both are needed, but they do not need to run the same checks. The early gate can run lighter checks, while the later gate runs the full policy suite.
What to Avoid: One Big Gate at the End
The worst pattern is putting all scans in a single block at the end of the pipeline. This creates a long feedback loop for every type of issue. A missing secret, a vulnerable dependency, a misconfigured IaC file, and a container vulnerability all get reported at the same time, after the developer has waited through build, unit tests, integration tests, and staging.
This pattern also makes the pipeline fragile. One slow scan blocks all others. If a scan fails, the developer has to fix the issue and wait through the entire pipeline again, including all the steps that already passed.
Spread gates across the pipeline so each stage has a clear responsibility. The early stages catch cheap problems fast. The later stages catch expensive problems before they reach production.
Consider the Cost of Scanning
Some scans are expensive. Full dependency database lookups, deep container analysis, and comprehensive policy evaluations can take minutes and consume significant compute resources. Running these on every commit for every branch is wasteful.
The solution is not to skip the scans. It is to place them strategically. Run expensive scans only on the main branch or on pull requests targeting the main branch. For feature branches, run only the fast checks: secret scan, quick dependency scan, and syntax validation. This keeps the pipeline fast for daily work while still enforcing quality before code reaches production.
Practical Checklist
- Secret scan runs before build, right after checkout.
- Dependency scan runs before artifact creation, using the manifest file.
- Container image scan runs after build, before registry push.
- IaC scan runs at two points: during development and before environment apply.
- Expensive scans run on main branch or merge targets only.
- Fast scans run on every commit for all branches.
The Takeaway
A well-placed gate catches problems early, when they are cheap to fix. A poorly placed gate catches problems late, after time and compute have been wasted. The goal is not to scan everything everywhere. It is to put each scan where it gives the fastest feedback for the problems it is designed to catch. When you get the placement right, developers get quick wins, compliance gets its guarantees, and the pipeline stays fast enough that no one wants to bypass it.