Free — no signup required

AMI Management Strategy

3 min read

The AMI Lifecycle Problem

Once you automate image creation, you will accumulate AMIs rapidly. A team rebuilding images nightly across five application types generates 150 AMIs per month. Without a management strategy, you face three problems: engineers use stale, unpatched images; storage costs grow unbounded; and no one knows which image is the "right" one to use.

A production AMI management strategy addresses four concerns: versioning, discovery, sharing, and deprecation.

Versioning and Tagging

Never rely on AMI names alone for discovery — names are not queryable efficiently. Instead, tag every AMI with structured metadata at build time: a version, the git commit it was built from, a build timestamp, its deployment stage (production/staging/dev), and the image family it belongs to. These tags become the query interface. Terraform, AWS CLI, and your deployment tooling can all find the right image by filtering on tags rather than hardcoding AMI IDs.

Discovery: Never Hardcode AMI IDs

Hardcoding an AMI ID (ami-0a1b2c3d...) in Terraform is a common anti-pattern. AMI IDs are region-specific, change every time you rebuild, and give no indication of what is in the image. The correct pattern is a data source lookup: a data source that finds the most recent self-owned AMI matching the right name, stage, and management tags, in an available state — and a resource that references that data source's ID rather than a literal string. When Packer builds a new image and tags it Stage=production, the next Terraform apply automatically picks it up. No manual ID updates required.

GCP has a native equivalent called Image Families. When you publish an image to a family (e.g., web-servers-prod), pointing to family/web-servers-prod always resolves to the most recently published non-deprecated image in that family.

Sharing Across AWS Accounts

In a multi-account AWS organization (the recommended security model), you typically have dedicated accounts for different purposes:

Build Account  →  shares AMIs  →  Dev Account
                              →  Staging Account
                              →  Production Account

The Build Account runs Packer and owns all AMIs. Sharing is done either by modifying the AMI's launch permissions (for simple cases) or by using AWS Resource Access Manager (RAM) (for organization-wide sharing). The Packer template itself can automate this by listing the specific account IDs the resulting AMI should be shared with as part of the source block, so every new build is shared automatically without a manual step.

Deprecation and Cleanup

Old AMIs must be deregistered to prevent use of unpatched images and to control storage costs (AMIs consist of EBS snapshots, which are billed by GB-month). A practical policy:

  • Keep the last N versions (e.g., 5) of each image family in production.
  • Automatically deregister images older than X days (e.g., 90) that are not in active use.
  • Before deregistering, check that no running instances use the AMI (via aws ec2 describe-instances --filters "Name=image-id,Values=ami-...") .

This cleanup is typically implemented as a scheduled Lambda function or a CI/CD pipeline step that runs after each successful build.

Key Point: AMI management is where immutable infrastructure either succeeds or collapses operationally. Teams that automate the full lifecycle — build, tag, share, discover, deprecate — get the full benefit of immutability. Teams that automate only the build step but manage the rest manually end up with hundreds of mystery AMIs, engineers who hardcode IDs because they cannot figure out which image is current, and the same drift problems they were trying to escape — just moved from servers to images.

This is one of 18 chapters

Every chapter is free — Kubernetes, Terraform, SRE, distributed systems, and more — with fast daily review built in.

Sign up free