Skip to main content
advisory · aws

Custom model deployments with no invocations in 30 days

rule IDs covered
1
severity
low

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

How ZopNight evaluates Custom model deployments with no invocations in 30 days.
Field Value
Rule IDsRC-1634
Categoryadvisory
Severitylow
Metricnone — pure configuration read
Sourcebedrock_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

Terminal window
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 Sum

An 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.

See it fire on your bill.

Connect an account read-only. The first findings land in minutes.

417 rule families across 353 resource types on 22 platforms. Every threshold, metric, and IAM action is documented on these pages before you grant anything.

417 rule families documented
353 resource types covered
read-only default access level
Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console· Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console·