The $450/month one-liner
I put ECR lifecycle policies on 50 ECR repositories across two AWS accounts. I didn’t want to wait for AWS to evaluate them on its own schedule — I wanted to see results now.
The worst offender had 832 images totaling 4.6 TB — old Kubeflow model deployment templates that nobody had pulled in over a year. The lifecycle policy was in place, the rules were correct. I re-applied the same policy with put_lifecycle_policy — identical JSON, same rules, no changes. ECR treated it as a new policy and evaluated immediately. 801 images deleted in about 60 seconds. 4.4 TB reclaimed. The repository went from 832 images / 4.6 TB to 31 images / 192 GB.
ecr.put_lifecycle_policy(
repositoryName='ml-model-templates',
lifecyclePolicyText=json.dumps(existing_policy) # same policy, re-applied
)
The ~$450/month in ECR storage was the Kubeflow pipeline’s accumulation of container images for every model deployment — each one a full inference environment that was used once and never cleaned up. The lifecycle policy was supposed to handle this automatically. It just needed a nudge.
I tried the same trick on two other repositories. It didn’t work — they sat there. So I used the lifecycle policy preview to see what the policy would delete, then batch-deleted those images myself:
# Ask ECR what the policy would expire
ecr.start_lifecycle_policy_preview(repositoryName='ml-inference-api')
# Wait for preview to complete
waiter = ecr.get_waiter('lifecycle_policy_preview_complete')
waiter.wait(repositoryName='ml-inference-api')
# Get the list of images the policy would delete
preview = ecr.get_lifecycle_policy_preview(repositoryName='ml-inference-api')
to_delete = [
{'imageDigest': img['imageDigest']}
for img in preview['previewResults']
if img['action']['type'] == 'EXPIRE'
]
# Delete them now instead of waiting
for batch in [to_delete[i:i+100] for i in range(0, len(to_delete), 100)]:
ecr.batch_delete_image(repositoryName='ml-inference-api', imageIds=batch)
The re-poke isn’t a reliable API behavior, but the preview API always works — it tells you exactly which images match your rules, and you can act on that list immediately.
AWS documents that images expire within 24 hours of meeting the criteria. They don’t say what happens if you re-PUT the same policy — but in my case it triggered immediate evaluation on the biggest repository and saved $450/month. On two others, it didn’t. Costs nothing to try.