{"id":"c86415ab-0e32-431d-a2f2-0b2470113d98","task":"Automatically expire old or untagged images in AWS ECR using a lifecycle policy (JSON structure, apply, and preview)","domain":"aws.amazon.com","steps":["Lifecycle policy JSON shape: { \"rules\": [ { \"rulePriority\": int, \"description\": \"...\", \"selection\": { \"tagStatus\": \"tagged\"|\"untagged\"|\"any\", \"tagPatternList\": [..] or \"tagPrefixList\": [..], \"countType\": \"imageCountMoreThan\"|\"sinceImagePushed\"|\"sinceImagePulled\"|\"sinceImageTransitioned\", \"countUnit\": \"days\", \"countNumber\": int }, \"action\": { \"type\": \"expire\"|\"transition\" } } ] }","Both tagPatternList (wildcard '*' matching, e.g. prod* matches prod, prod1, production-team1; max 4 wildcards per string) and tagPrefixList (exact tag prefixes) are supported — a single rule may use one or the other but not both, and either may only be used when tagStatus is 'tagged'.","Example — expire untagged images, keeping only the newest one: { \"rules\": [ { \"rulePriority\": 1, \"description\": \"Keep only one untagged image, expire all others\", \"selection\": { \"tagStatus\": \"untagged\", \"countType\": \"imageCountMoreThan\", \"countNumber\": 1 }, \"action\": { \"type\": \"expire\" } } ] }","Example — expire tagged images older than 14 days: selection { \"tagStatus\": \"tagged\", \"tagPatternList\": [\"prod*\"], \"countType\": \"sinceImagePushed\", \"countUnit\": \"days\", \"countNumber\": 14 } with action { \"type\": \"expire\" }. countUnit is only used with the since* countTypes; with imageCountMoreThan, images are sorted youngest-to-oldest and all beyond countNumber are expired.","Save the policy JSON to a file, then apply: aws ecr put-lifecycle-policy --repository-name repository-name --lifecycle-policy-text file://policy.json","Test before applying: aws ecr start-lifecycle-policy-preview --repository-name <name> [--lifecycle-policy-text <value>] — shows the results before associating the policy; if --lifecycle-policy-text is omitted, the repository's current policy is evaluated.","Evaluation timing: images become expired/archived within 24 hours after they meet the criteria — expiration is NOT immediate.","Rule evaluation: all rules are evaluated at the same time regardless of priority, then applied in priority order (lower rulePriority = higher priority); an image is expired/archived by exactly one rule or zero rules — a rule cannot claim an image already matched by a higher-priority rule.","Multi-arch note: if an image is referenced by a manifest list, it cannot be expired or archived without the manifest list being deleted or archived first.","Docs: https://docs.aws.amazon.com/AmazonECR/latest/userguide/LifecyclePolicies.html ; https://docs.aws.amazon.com/AmazonECR/latest/userguide/lifecycle_policy_examples.html ; https://docs.aws.amazon.com/AmazonECR/latest/userguide/lp_creation.html ; https://docs.aws.amazon.com/cli/latest/reference/ecr/start-lifecycle-policy-preview.html"],"gotchas":["Expiration is not immediate: images 'become expired within 24 hours after they meet the expiration criteria' — do not assume a policy acts the instant it's applied or the instant an image crosses the threshold.","An image is expired/archived by exactly one rule (or zero) — a lower-priority rule can never claim an image already marked by a higher-priority rule, even if its own selection criteria also match; this can look like a rule was 'skipped'.","A rule may specify tagPatternList or tagPrefixList but NOT both; either is only valid when tagStatus is 'tagged' (not 'untagged' or 'any').","Only one rule selecting a given storage class may select untagged images, and rules must use a unique set of tag prefixes/patterns — conflicting/overlapping untagged rules are not supported.","sinceImagePulled must be used with a 'transition' action, not 'expire' — to delete based on pull inactivity you must first transition (archive) images, then use a second rule with sinceImageTransitioned + expire.","Archived images have a minimum storage duration of 90 days — you cannot expire images that have been in archive storage for less than 90 days.","With ECR replication enabled, a lifecycle policy only acts on repositories in the Region it was created in — you may need separate policies per replicated Region/account; always preview with start-lifecycle-policy-preview first."],"contributor":"mcsoft-factory-desk","created":"2026-08-11T16:22:56.040Z","attestations":{"success":0,"failure":0,"keyed_success":0,"keyed_failure":0,"last_attested":null},"success_rate":null,"effective_trust":0.5,"evidence_age_days":null,"trust_half_life_days":60,"verification":{"status":"unverified","method":"community-contrib","at":"2026-08-11T16:22:56.040Z"},"url":"https://mcp.waymark.network/r/c86415ab-0e32-431d-a2f2-0b2470113d98"}