# Bedrock Guardrail Unused

> A Bedrock guardrail bills per text unit only when a model call applies it, so an unused one costs $0 and deleting it saves $0. The finding is about policy that protects nothing. ZopNight watches the DRAFT version's Invocations over 30 days, and says plainly that published-version usage is invisible to this check.

Source: https://zop.dev/integrations/aws/recommendations/bedrock-guardrail-unused
Updated: 2026-08-19

---

## A safety policy nobody wired in

Guardrails are Bedrock's content-policy layer: PII masking, topic denial, word filters,
applied at invocation time. They only do anything when a model call references them. A
guardrail with zero invocations is a policy someone designed (presumably for a reason) that
no production call actually enforces. The exposure is inverted from most idle findings: the
risk is not the resource, it is the model traffic running without the protection this object
was supposed to provide.

## The economics: a configuration object, not capacity

A guardrail has no standing charge: [billing runs per text unit evaluated](https://aws.amazon.com/bedrock/pricing/), so zero invocations
means roughly zero spend, and deletion recovers nothing. ZopNight therefore ships this as an
advisory cleanup with $0 attached rather than dressing it as a savings opportunity. The
concrete action is to attach the guardrail to the calls it was designed for, or delete it so
the policy surface stays legible.

## The DRAFT blind spot, stated up front

CloudWatch dimensions guardrail invocations by version, and discovery can only see the DRAFT
working version. AWS's recommended production pattern is invoking a published numbered
version, and that traffic never appears under DRAFT. A guardrail used exclusively through a
published version will look unused to this rule. Treat a fired finding as a verification
prompt, not a delete order: check the console for version-level usage before removing
anything.

## Two failure modes the rule guards itself against

A metrics outage would make every guardrail in the org look unused simultaneously, so the
rule refuses to fire when the whole metrics map is empty. Conversely, a genuinely unused
guardrail emits no Invocations series at all, because [Bedrock's invocation counters appear
only for periods that carried traffic](https://docs.aws.amazon.com/bedrock/latest/userguide/monitoring.html). Absence of the series on an otherwise-healthy
metrics fetch is itself the zero-traffic signal, while any present series showing activity
suppresses the finding.

## Verify usage yourself

```bash
aws cloudwatch get-metric-statistics \
  --namespace AWS/Bedrock/Guardrails --metric-name Invocations \
  --dimensions Name=GuardrailArn,Value=<guardrail-arn> Name=GuardrailVersion,Value=DRAFT \
  --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
```

Repeat with each published version string in place of DRAFT before concluding the guardrail
is truly unattached.
