DEV Community

Cover image for Using Amazon Bedrock Prompt Caching to Cut Repeated Context Costs and Latency
Noah Taro
Noah Taro

Posted on

Using Amazon Bedrock Prompt Caching to Cut Repeated Context Costs and Latency

Why prompt caching matters in Bedrock workflows

If your application keeps resending the same large context to a foundation model, prompt caching is worth a close look. In Amazon Bedrock, it can reduce input token costs by up to 90 percent when the same context is repeated across requests. The practical win is not just lower spend: fewer repeated tokens also means less work per request, which can help reduce latency in workflows that reuse stable context.

This is especially relevant when you are building around long system instructions, reused reference material, or multi-turn flows where a large portion of the prompt stays unchanged. Instead of treating every request as a full rebuild, you can mark parts of the prompt as cacheable and let Bedrock reuse them.

Daniel Abib, a Specialist Solutions Architect for Generative AI at AWS, frames this as a production-oriented pattern. The point is not to cache everything, but to identify the parts of your prompt that are repeated often enough to justify it.

What the cache needs before it becomes useful

The main implementation detail to keep in mind is that prompt caching only activates once the prompt reaches a minimum size. In the example setup, the cache threshold is 1,024 tokens. That means very small prompts are not good candidates, and the benefit appears when you have enough repeated context to cross that threshold.

A concrete setup in the source uses:

MODEL_ID = "global.anthropic.claude-sonnet-4-5-20250929-v1:0"
AWS_REGION = "us-west-2"
Enter fullscreen mode Exit fullscreen mode

That gives you the basic model and region context for the workflow. From there, the prompt is structured so that reusable sections can be separated from the parts that change from request to request.

A simple prompt layout with cache points

One of the clearest parts of the implementation is the way the content array is assembled. Instead of sending one long block of text, the prompt is broken into sections with cache points inserted between them:

content = [
    {"text": SECTION_1},
    {"cachePoint": {"type": "default"}},
    {"text": SECTION_2},
    {"cachePoint": {"type": "default"}},
    {"text": SECTION_3}
]
Enter fullscreen mode Exit fullscreen mode

That structure makes the caching intent explicit. You are telling Bedrock where the reusable boundaries are, rather than hoping the model or the service infers it from a monolithic prompt. For developers, this is useful because it keeps prompt composition readable and easier to reason about.

A pattern like this also makes it easier to separate concerns:

  • SECTION_1 can hold stable instructions or background
  • SECTION_2 can hold another reusable block
  • SECTION_3 can hold the request-specific portion

The exact section boundaries depend on your application, but the idea is consistent: keep the repeated context stable so Bedrock can cache it, and keep the changing part outside the cached core.

What a cache write looks like

The first request is the one that writes the cache. In the example, the request is:

usage1, _ = converse_system_cached(
    "What are the most promising locations for finding microbial life?"
)
print("Request 1 (cache write expected):")
Enter fullscreen mode Exit fullscreen mode

That first call is the warm-up step. It creates the cached state that later requests can reuse. If you are testing this in your own workflow, this is the point where you should expect the initial request to carry the cost of setting up the cache.

This matters for evaluation. If you benchmark only the first call, you are measuring cache creation, not cache reuse. To understand the real benefit, you need to compare that first request with later requests that reuse the same context.

Reading the response and usage data

The source also shows a direct way to pull back usage and text from the model response:

usage = response["usage"]
text = response["output"]["message"]["content"][0]["text"]
return usage, text
Enter fullscreen mode Exit fullscreen mode

This is a small but important implementation detail. If you are trying to validate whether caching is helping, usage data is the part you want to inspect. The response text gives you the model output, while the usage object is where you can observe the token accounting tied to the request.

In practice, that means your testing loop should not stop at "did the model answer?" It should also answer:

  • Did the first request create the cache as expected?
  • Are later requests reusing the same context?
  • Does the usage profile reflect the reduced repeated input?

That is the kind of instrumentation you need if you care about cost and latency as engineering constraints rather than abstract benefits.

A direct-message example for contrast

The source also includes a direct message construction example:

Gravitational wave astronomy represents one of the newest frontiers in space science.

This is useful as a contrast to the cached prompt pattern. A direct message like this is short and self-contained, so it does not obviously benefit from prompt caching. The caching approach becomes more valuable when the prompt carries repeated background material that would otherwise be resent every time.

That distinction is important when deciding whether to add caching to a workflow. If your prompts are tiny and mostly unique, caching may not buy you much. If your application repeatedly sends a large shared context, the economics change quickly.

Practical decision points for builders

If you are deciding whether to use Bedrock prompt caching, a quick checklist helps:

  1. Is the same context being sent repeatedly?
    Caching only helps when reuse is real and frequent.

  2. Does the prompt exceed the minimum token threshold?
    In the example, you need at least 1,024 tokens before the cache activates.

  3. Can the prompt be split into stable and variable sections?
    The more cleanly you can separate them, the easier the implementation becomes.

  4. Are you measuring usage, not just output?
    You need response usage data to verify the effect.

  5. Is the workflow latency-sensitive enough to justify the change?
    The cost reduction is the headline, but less repeated work can also matter for response time.

Tradeoffs to keep in mind

Prompt caching is not a universal optimization. It is a targeted tool for repeated context. That means you should expect the best results in production-style flows where the prompt structure is stable over many requests.

The tradeoff is added prompt design discipline. You have to think about which sections should be cached, how to structure the content array, and how to validate the behavior using usage data. That is more work than sending a single flat prompt, but it gives you control over a cost center that can otherwise grow quietly over time.

Bottom line

Amazon Bedrock prompt caching is most useful when your application repeatedly sends the same large context to the model. With a minimum activation threshold of 1,024 tokens and a prompt structure that uses cache points, you can build a workflow that reduces repeated input costs and can also improve latency. The main engineering task is to separate stable context from changing input, then verify the effect by inspecting usage on the cache write and later reuse requests.

Top comments (0)