Skip to content

Deepseek API burning too many tokens. #32911

Closed as not planned
Closed as not planned

Description

@tehNate

Description

There is an issue that I am experiencing, and other are experiencing. If you are using the Deepseek API with a key VIA the newer 1.17 versions of Opencode then you are being overbilled because of a bug in the code.

The bug has been tested in this Reddit thread:

https://www.reddit.com/r/opencodeCLI/comments/1u9grix/opencode_not_using_prompt_caching_with_deepseek/

Ongoing problem for a week you all need to address this.

DeepSeek V3/V4 supports native prompt caching so the model can do it.

The issue seems to be OpenCode not sending cache_control in its API requests.

Plugins

No response

OpenCode version

1.17+

Steps to reproduce

The bug has been tested in this Reddit thread:

https://www.reddit.com/r/opencodeCLI/comments/1u9grix/opencode_not_using_prompt_caching_with_deepseek/

Every prompt I send costs 160–170K input tokens because the full conversation history gets re-sent each turn with no caching. Tested in a brand new empty folder — even "hello" costs ~8K tokens (that's OpenCode's fixed system prompt + tool definitions overhead, apparently normal). The real problem: after a long session there's zero cache reduction. No "cache read" field in the UI, no cost savings between turns.

DeepSeek V3/V4 supports native prompt caching so the model can do it. The issue seems to be OpenCode not sending cache_control in its API requests.

Screenshot and/or share link

No response

Operating System

Linux CLI

Terminal

Activity

  1. github-actions commented on Jun 18, 2026

    @github-actions
    Contributor

    This issue doesn't fully meet our contributing guidelines.

    What needs to be fixed:

    • The Steps to reproduce field is empty. Please describe what you were doing when you noticed excess token usage so maintainers can investigate.
    • The Description field only contains a Reddit link and a brief comment. Please describe the actual problem you're experiencing (e.g. which model/provider, what behavior you observe, approximate token counts, etc.) rather than linking externally.

    Please edit this issue to address the above within 2 hours, or it will be automatically closed.


    This issue might be a duplicate of existing issues. Please check:

    If you believe this was flagged incorrectly, please let a maintainer know.

  2. added
    needs:complianceThis means the issue will auto-close after 2 hours.
    and removed
    needs:complianceThis means the issue will auto-close after 2 hours.
    on Jun 18, 2026
  3. github-actions commented on Jun 18, 2026

    @github-actions
    Contributor

    Thanks for updating the issue! The description now includes the specific problem (missing cache_control in API requests), observed behavior with token counts, a reference to community testing, version info, and OS details. Everything looks good — appreciate you taking the time to fill this out properly.

  4. RBQAAQ commented on Aug 15, 2026

    @RBQAAQ

    I investigated this independently on OpenCode with the official DeepSeek provider and found a concrete cause for the cache behavior in my setup.

    In my case, this was not caused by OpenCode failing to send cache_control. The problem was a globally auto-loaded opencode-agent-memory plugin that injected a millisecond-precision timestamp near the beginning of the system prompt on every request:

    <memory_metadata>
    - The current system date is: 2026-08-15T18:49:19.957Z
    

    A few seconds later, the next request contained:

    <memory_metadata>
    - The current system date is: 2026-08-15T18:49:23.275Z
    

    I captured the actual outgoing /chat/completions JSON bodies and compared adjacent requests. The first differing content was this timestamp in the second system message. The tool definitions were identical.

    Because DeepSeek prompt caching is prefix-based, the changing timestamp caused the reusable prefix to end before the conversation history. This exactly matched the observed symptom: cache reads stayed pinned around the static prompt size while uncached input kept growing.

    For example, in a long failing session I observed cache reads plateauing around:

    11,008 cached tokens
    

    while uncached input grew to hundreds of thousands of tokens.

    I then performed controlled A/B tests:

    1. Removing the memory plugin entirely restored normal cache growth.
    2. Making the injected metadata stable restored append-only request construction.
    3. With the stable-metadata patch, one test session produced:
    total_miss:    32,118
    total_hit:    969,344
    total_prompt: 1,001,462
    cache hit rate: 96.79%
    

    Later requests in that session were typically in the 98–99%+ cache-hit range.

    The adjacent request comparison after the fix looked like:

    Identical message prefix: 6 messages (A=6, B=18)
    Identical tool prefix: 14 tools (A=14, B=14)
    
    FIRST JSON DIFFERENCE:
    path: $.messages.<length>
    

    So the previous request became a true prefix of the next request again.

    The upstream plugin fix has now been merged here:

    joshuadavidthomas/opencode-agent-memory#20

    One important detail: simply removing the plugin from the plugin array in opencode.json was not enough in my setup, because ~/.config/opencode/plugins/memory.ts was auto-loaded from the local plugins directory. Moving that file/symlink out of the directory was necessary for the clean A/B test.

    This may not explain every report in this issue, but for users who have opencode-agent-memory or another plugin that injects dynamic data near the start of the system prompt, it is worth checking the exact outgoing request bodies before attributing the behavior to DeepSeek cache support or cache_control.

  5. github-actions commented on Oct 16, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions