Skip to content

DeepSeek V4 tiers hold the pre-2026-08-16 card, and get_pricing has no axis for the new peak/off-peak schedule #904

Description

@xyzs996

_TIER_DEEPSEEK_PRO and _TIER_DEEPSEEK_FLASH in src/services/pricing.py hold DeepSeek's pre-2026-08-16 rate card. Since 2026-08-16 the published card is peak / off-peak, which get_pricing has no axis for.

The modeling is right; the constants and one axis are not

The comment above those tiers is careful and still correct:

# DeepSeek V4 (USD per million tokens). DeepSeek's automatic prefix cache
# bills cache HITS at the low ``cache_read`` rate and cache MISSES at the
# normal input rate; there is no separate cache-write charge, so
# ``cache_creation`` mirrors ``input`` (a non-cached token is just input).

That mirror still holds under the new card — a miss is still just input — so the shape of both dicts survives. What changed is the six numbers, and the fact that each of them now doubles on a UTC schedule.

Current rates from https://api-docs.deepseek.com/quick_start/pricing/, read 2026-08-24, USD per 1M tokens:

input / cache_creation output cache_read
deepseek-v4-flash off-peak 0.22 0.66 0.007
deepseek-v4-flash peak 0.44 1.32 0.014
deepseek-v4-pro off-peak 0.66 1.98 0.022
deepseek-v4-pro peak 1.32 3.96 0.044

Off-peak rates are half of the peak rates. Peak hours are 01:00 - 04:00 and 06:00 - 10:00 UTC, Monday through Friday (all other hours are off-peak).

The Chinese page carries the same table in CNY and converts at a fixed 6.8182 on every v4-pro cell, so the USD column is DeepSeek's own conversion.

Why neither existing tier axis reaches it

get_pricing already selects among tiers on two inputs:

def get_pricing(
    model: str,
    *,
    input_tokens: int = 0,
    service_tier: str = "standard",
) -> dict[str, float] | None:

Neither can carry this one:

  • input_tokens is prompt size. DeepSeek's tier does not depend on prompt size.
  • service_tier comes from the response — compute_cost reads usage.get("service_tier") and defaults to "standard". DeepSeek's API does not return a service tier, so this always resolves to "standard", and even if it did, peak/off-peak is not something the caller or the provider declares per request. It is a function of the wall-clock time the request was sent.

So this needs a third input — the request timestamp — rather than a new value on either existing axis. That is a design call, which is why I am opening an issue rather than a PR.

If a timestamp axis is more than you want to add, the contained version is to put the off-peak card in the constants and say so:

_TIER_DEEPSEEK_PRO = {  # off-peak; peak (Mon-Fri 01:00-04:00, 06:00-10:00 UTC) is 2x
    "input": 0.66 / 1_000_000,
    "output": 1.98 / 1_000_000,
    "cache_creation": 0.66 / 1_000_000,
    "cache_read": 0.022 / 1_000_000,
}

Off-peak covers 143 of every 168 hours, so it is the better single answer if only one is available. tests/test_deepseek_prefix_cache.py asserts against these values and would need the same update.

Size of the gap

Weighted by a measured agent token mix — 95.64% cache read / 4.07% cache miss / 0.29% output, from an 8.04B-token public trace (gist) — per 1M tokens:

compute_cost returns actual off-peak actual peak
deepseek-v4-pro $0.0237 $0.0536 (2.26×) $0.1073 (4.53×)
deepseek-v4-flash $0.0092 $0.0176 (1.91×) $0.0351 (3.82×)

cache_read is what drives it. At ~96% of agentic input tokens, 0.003625 versus 0.022 moves the total more than the input and output fields combined — and the docstring's own reasoning about status-bar honesty ("The user picks 'no number' over 'wrong number'") applies here: a number that is 4.5× low reads as authoritative in exactly the way a missing one does not.

One suggestion regardless of which route you take: the neighbouring Anthropic tiers have no checked-on date either, but DeepSeek is the entry most likely to move again, since the values currently in the file were themselves a time-limited card. A # checked YYYY-MM-DD line on the DeepSeek block would make the next drift visible on inspection rather than only in the bill.

Per-vendor cache-read rates I checked these against: https://xyzs996.github.io/llm-api-pricing/

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions