← All posts
Provider notes5 min read

Bedrock API keys are bearer tokens. That changes everything about caching.

SigV4 signs the SHA-256 of the request body, so no intermediary can add a cache breakpoint without the secret key. Bedrock API keys carry no body signature. That decides everything.

AWS Bedrock has two ways to authenticate a request, and they have opposite consequences for anything that sits between your app and the API. If you run a gateway, a proxy, or any middleware that wants to improve Bedrock requests in flight — cache injection being the canonical example — the auth mode is the whole ballgame.

SigV4 signs the body. All of it.

Classic AWS authentication is SigV4: the client builds a canonical request whose sixth line is the SHA-256 of the request body, derives a string-to-sign from it, and HMACs that with the secret key. The signature lands in the Authorization header:

Authorization: AWS4-HMAC-SHA256 Credential=.../bedrock/aws4_request,
  SignedHeaders=..., Signature=8f3a...

Now put a proxy in the path and let it insert one small thing — a cache_control: {"type": "ephemeral"} breakpoint, say. The body's hash changes, the string-to-sign changes, the signature no longer matches, and Bedrock rejects the request outright. Not degraded: failed, with a signature error the customer will read as the proxy breaking their integration. And the proxy cannot re-sign, because re-signing requires the SecretAccessKey, which lives in the caller's environment — never in the header, and never in anything the proxy sees. Holding customer AWS secrets to re-sign traffic is a trust-boundary expansion nobody should want; the alternative, an AssumeRole/STS delegation apparatus, is a project, not a feature. Body mutation under SigV4 is binary: zero, or broken.

Bedrock API keys have no body binding

Then AWS shipped Bedrock API keys — long-lived credentials sent as a plain header:

Authorization: Bearer bedrock-api-key-...

A bearer token authenticates the caller, not the content. There is no body hash anywhere in it. An intermediary holding that header can rewrite the body freely — add a cache breakpoint, restructure a system prompt around a timestamp — with no signing code at all, and Bedrock accepts the result. The entire re-signing project the SigV4 analysis demands simply evaporates. One header prefix decides which world you are in, and the request itself tells you: AWS4-HMAC-SHA256 means look-don't-touch, Bearer means mutation is possible.

The rule a proxy should draw from this

Vigil's Bedrock module is built on exactly one rule: mutate only what is provably bearer-authorized, and degrade to observe-only on everything else. The auth-mode check is deliberately conservative — an absent Authorization header and an unrecognised scheme are both refusals, because "we could not classify the credential" must never grant mutation rights. Under SigV4 the request forwards byte-for-byte, still measured, still priced, still fingerprinted for cache diagnosis — the whole observability layer works identically in both worlds. Only injection is gated.

That split — measure everywhere, act only where the crypto permits — is worth stating generally, because it reframes what "supporting Bedrock" means for any middleware. The question is not "can we integrate" but "which verbs does the auth mode license", and the honest product answer names both: watch everywhere, optimise where injection is possible.

Practicalities if you go the API-key route

Your SDK may block the path. The AWS SDKs are SigV4 machines; pointing one at a proxy and expecting bearer semantics fights its design, and the SDK will sign — putting you back in the immutable world even though your credential did not require it. The bearer path wants a plain HTTP client, or an SDK configuration that genuinely disables signing, and it needs the proxy to verify which arrived rather than assume.

Scope and rotation are on you. SigV4 credentials expire and scope tightly by role; a Bedrock API key is closer to a durable password for the runtime API. The caching flexibility is paid for in credential hygiene: rotation schedules, minimal IAM policy behind the key, and never letting it near a log line.

The cache you are injecting into is Bedrock's, not Anthropic's. Same model name, separate platform, separate cache and separate rate table — a prefix warmed via bedrock-runtime does nothing for a direct Anthropic call. And the minimum-token rules still apply, keyed off the model inside Bedrock's namespace (anthropic.claude-…, with a geo prefix like us. on most production traffic), so the id has to be mapped before any eligibility judgment means anything.

Streaming is a different wire format entirely. Bedrock streams application/vnd.amazon.eventstream — length-prefixed binary frames with two CRC32s each, not SSE. Split it on \n\n like an OpenAI stream and you corrupt it. Usage lives inside those frames, so metering streamed Bedrock calls means a real decoder; ours is hand-rolled against the published frame format because the official codec package imports Node built-ins a Worker runtime does not have. Which providers Vigil can inject on, and which it can only watch, is listed on the FAQ.

What to do

Check which auth mode your Bedrock traffic actually uses — read the Authorization header prefix on a captured request rather than assuming from your SDK config. If it is SigV4 and you want proxy-injected caching, know that no intermediary can give it to you without holding your secret key, whatever anyone's marketing says; the choices are client-side injection, the API-key path with its credential trade-offs, or observe-only. And if you adopt Bedrock API keys, treat them as the long-lived passwords they are: scoped IAM behind them, rotation on a calendar, and out of your logs.