Explanation
Why the waste happens and who it affects.
ECR keeps every image in a private repository until it is deleted, so without a lifecycle policy repositories accumulate thousands of old build images and untagged images that no deployment will ever pull again. Storage for all of them is billed every month.
The growth is gradual and spread across many repositories, so it is rarely noticed until registry storage becomes a visible line item. It compounds with replication: images replicated to other Regions or accounts are stored again in each destination, registry replication never deletes or archives anything, and lifecycle policies are not replicated, so destination repositories keep every copy unless they have their own policies. AWS Trusted Advisor flags this with its check for ECR repositories without a lifecycle policy.
Billing model
The pricing dimensions that drive this cost.
- Private repository storage
- Billed per GB-month for all images stored in private repositories, whether or not they are ever pulled
- Replicated copies
- Each replicated image is stored, and billed, in every destination Region or account in addition to the source
- Cross-Region data transfer
- Replicating or pulling images across Regions incurs data transfer charges
How to detect
4 checks to find it in your estate.
- Review the Trusted Advisor cost optimization check Amazon ECR Repository without lifecycle policy configured (check ID c18d2gz128), which is yellow for any private repository with no lifecycle policy
- For each repository, call DescribeImages and summarize image count, total imageSizeInBytes, the number of untagged images, and images whose lastRecordedPullTime (or imagePushedAt if never pulled) is older than your deployment and rollback window
- Check replication destinations separately: list repositories in each destination Region or account and confirm they have their own lifecycle policies, since source policies are not replicated
- Use Cost Explorer or the Cost and Usage Report to track ECR storage by account and Region and spot repositories or registries with steady growth
How to fix
5 ways to remove the waste.
- Add a lifecycle rule with tagStatus untagged and countType sinceImagePushed that expires untagged images after a short period, such as a few days
- Add rules that keep only the most recent N images for build or branch tag patterns (countType imageCountMoreThan with a tagPatternList), and exclude release or production tag patterns that must be retained
- Use the lifecycle policy preview before applying a policy to confirm exactly which images will be expired; images are expired within 24 hours of meeting the criteria and each action is logged in CloudTrail
- Apply lifecycle policies in replication destinations too, or use repository creation templates so repositories created by replication or create-on-push get a lifecycle policy automatically
- Prefer expiring images that are no longer needed over transitioning them to the Archive storage class: archived images still incur storage charges, cannot be pulled until restored, and have a 90-day minimum storage duration, so archiving is not a substitute for deleting images that will never be used again
Documentation
Vendor references for pricing and configuration.