Custom model deployments with no invocations in 30 days
What does ZopNight detect here?
Bedrock custom-model deployments bill per minute only while serving and scale to 0 when quiet, so an unused one costs nothing. ZopNight still flags 30 days without an Invocations datapoint as cleanup-worthy clutter. Because CloudWatch omits the series entirely at zero traffic, the missing metric itself is the evidence, provided the rest of the org's metrics arrived.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-1634 |
| Category | advisory |
| Severity | low |
| Metric | none — pure configuration read |
| Source | bedrock_custom_model_deployment_unused.go |
No standing charge, still worth deleting
An on-demand custom model deployment is usage-priced: it bills per minute while it serves traffic and scales itself to zero between requests. Deleting one recovers no dollars, which is why this finding is categorised as advisory with a stated saving of $0 rather than filed under a cost category. The honesty matters: a $0 card dressed up as an “orphan” would ride an exemption meant for resources with real standing residuals. What a stale deployment does cost you is clarity: it clutters the model list, confuses cost attribution, and invites someone to point production at an artifact nobody maintains.
CloudWatch’s silence is the datapoint
Invocations in the AWS/Bedrock namespace is a count metric, and Bedrock publishes it
only for periods that actually had traffic. A deployment with zero invocations across the whole window
produces no series at all, not a series of zeroes. Earlier logic treated the missing series
as missing data and abstained, which made the rule structurally unable to fire: present
meant active, absent meant abstain. The corrected reading is that for a resource discovery
has confirmed exists, an absent Invocations series is itself the zero-traffic evidence.
A present series showing any activity ends the evaluation: any datapoint, average or
maximum above zero, judged over the full fetched history, not just the trailing 30 days.
The guard against a fleet-wide false fire
Absence-as-evidence needs one protection: if the whole per-org metrics fetch fails, every deployment would look series-less and the rule would mass-recommend deletion across the fleet. So an empty metrics map (nil or zero entries) hard-abstains. Absence only counts when other resources’ metrics did arrive in the same batch.
Pulling a deployment’s Invocations series
aws cloudwatch get-metric-statistics \ --namespace AWS/Bedrock --metric-name Invocations \ --dimensions Name=ModelId,Value=<custom-model-deployment-arn> \ --start-time "$(date -u -v-30d +%Y-%m-%dT%H:%M:%SZ)" \ --end-time "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ --period 86400 --statistics SumAn empty Datapoints array over 30 days reproduces the finding.
Removing the deployment, keeping the model
The deployment and the underlying custom model are separate objects. Verify no application invokes the deployment, keep the trained model artifact, and delete only the deployment. It can be recreated from the model in minutes when next needed.