# ECR Repository Never Pulled

> RepositoryPullCount is the one pull signal AWS publishes as a metric, and ZopNight requires the series to actually span 90 days of zeros, plus a repository at least 90 days old holding at least 1 image, before recommending deletion of storage that is provably dead in its entirety.

Source: https://zop.dev/integrations/aws/recommendations/ecr-repository-never-pulled
Updated: 2026-08-19

---

## Whole-repository death, not cold images

A related rule asks which images inside a live repository have gone cold. This one asks a
blunter question: did *anything* pull from this repository at all. AWS aggregates [its pull metric at the repository level](https://docs.aws.amazon.com/AmazonECR/latest/userguide/monitoring-usage.html) by design (no image or tag dimension exists), so the metric
can prove a repository untouched but can never name a stale image inside a busy one. When it
reads zero across the window, every image in the repository is dead weight together, and the
recommendation prices the repository's entire [storage bill](https://aws.amazon.com/ecr/pricing/) as recoverable.

## Each gate removes a way to be confidently wrong

The abstentions are the design. A missing metric means the fetch failed (throttle, grant,
regional gap) and is never read as zero; the producer emits explicit zeros on successful
empty queries precisely so failure and silence stay distinguishable. The series must
actually reach back 90 days, because a fortnight of data supports only a fortnight-sized
claim. The repository must be at least 90 days old, or silence means "new", not "dead". An
empty repository abstains: deleting zero bytes saves zero dollars. And an unpriced
repository abstains, since a cost recommendation without a cost is noise.

## A self-inflicted measurement wound, disclosed

ZopNight's own image scanning once overwrote per-image last-pull timestamps fleet-wide,
which is partly why this rule leans on the pull *counter* instead: scanning only ever added
to it, so a zero reading is genuinely untouched. The residual error runs in the safe
direction. A dead repository might be hidden by our own past pulls for a while, but a live
one can never be invented.

## Run the measurement

```bash
aws cloudwatch get-metric-statistics \
  --namespace AWS/ECR --metric-name RepositoryPullCount \
  --dimensions Name=RepositoryName,Value=my-repo \
  --start-time "$(date -u -v-90d +%Y-%m-%dT%H:%M:%SZ)" \
  --end-time "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
  --period 86400 --statistics Sum
```

## Deletion is permanent, so check the slow cycles first

Rollback images, DR golden images, and compliance archives are dormant on purpose, and
quarterly DR drills or annual rebuilds pull on cycles longer than the window. Confirm none
of those apply, then `aws ecr delete-repository --force` removes every image irreversibly.
Where dormancy is legitimate, a lifecycle policy thinning old tags captures most of the
saving without the finality.
