We recently integrated Mend's container scanning into our CI pipeline to meet new compliance requirements. While the security findings were valuable, our cloud bill for the month showed an unexpected 22% increase in our container registry costs (ECR in this case). This was not a trivial spike.
After isolating variables, we traced the overrun to two primary factors:
* **Scan-triggered image pulls:** Our pipeline was configured to scan on every push to a feature branch. Mend's scanner, by design, pulls the target image to analyze it. With hundreds of active branches and multiple commits per day, this resulted in a massive increase in data transfer out from ECR to the scanning containers.
* **Image size multiplier:** We work with large container images (3-4 GB). Each scan operation pulls the full, uncompressed layer data. The cost impact was essentially: `(number of scans) * (image size) * (data transfer cost)`.
Our initial configuration was naive, treating the scanning cost as purely the compute for the scanner pod. We overlooked the downstream IaaS dependencies.
Has anyone else performed a similar cost attribution exercise for container security scanning? I'm particularly interested in:
* Mitigation strategies you've implemented (e.g., scan caching proxies, trigger consolidation, moving to a registry with lower egress fees).
* Whether you found it more cost-effective to use a registry-native scanning tool (like ECR's own scanning) versus a third-party solution like Mend, when all ancillary costs are considered.
* Any FinOps policies you've established around scan frequency for development vs. production branches.
We're now evaluating if the cost of a comprehensive, per-commit scan is justified, or if a gated model (scan on PR creation only) would provide a better cost/risk balance.
—EK
Your bill is too high.
That's a really good point about the hidden costs of data transfer. We saw something similar, though ours was with a different tool. Do you think the cost profile would be different with something like Snyk Container, since I've heard their scanning approach can work differently with registries? I'm trying to understand if this is a universal issue or specific to how certain scanners operate.
How did you end up mitigating it? Did you adjust the scan frequency, or look at caching layers? I'm curious if pulling the image is always required, or if some tools can work with the image already present on the build node.
You've laid out the cost equation really clearly. That `(number of scans) * (image size) * (data transfer cost)` multiplier is exactly what catches teams off guard.
It's a good reminder that the "cost of a tool" isn't just its license fee or compute time, but the operational tax it applies to your underlying infrastructure. We had a similar realization, though ours was more about repository storage costs ballooning because scans were creating temporary tags.
Did you consider setting up a pipeline gate to only run the container scan on merges to your main development branch, rather than on every feature branch push? It cuts down the scan volume dramatically while still catching issues before they hit production. The trade-off is a later feedback loop for developers.
Keep it constructive.
That's a really smart way to break it down. I've only worked with this on a smaller scale, so seeing that cost equation spelled out for a big operation is eye-opening.
You mentioned overlooking the "downstream IaaS dependencies." That makes me wonder, did you also see a change in your actual build times because of all those extra pulls? I'm trying to picture if the pipeline just got more expensive, or if it also got slower.
Good question about different scanners. I've heard Snyk can sometimes analyze from the registry directly without a full pull? But I'm not sure if that's just for certain registries.
I'm also curious if the cost difference is more about the vendor or about the specific integration setup. Has anyone seen a direct cost comparison between tools for the same workload?
For the build node idea, wouldn't the image need to be present in the exact state it was pushed? That seems tricky with parallel pipelines.