DeepSeek V4.1-Flash: Rewrite the Off-Peak and Cache-Hit Runbook
DeepSeek V4.1-Flash halves prices off-peak and bills cache hits at $0.006/MTok. The UTC windows, the prompt shape that hits cache, and the re-based budgets.
Go deeper. Build your own.
At 04:00 UTC on September 14, every request your fleet sent to deepseek-v4-pro started landing on a different model at less than a third of the price, and the only line in your logs that changed was the bill. DeepSeek V4.1-Flash had launched four days earlier, on September 10, 2026, and the launch did three things to an operator’s cost model at once: it cut the per-token prices, it kept a clock-based off-peak discount that halves every line item, and it made a cache hit so cheap that the shape of your prompt now matters more than which DeepSeek model you picked.
This is the runbook for that. By Tuesday, the flexible DeepSeek jobs in your fleet wait for the off-peak window and the latency-bound ones do not; every prompt puts its stable material first so the disk cache can find it; the V4-Pro budgets and alerts are re-based to what those requests cost now; and no retired model id sits in a failover list pretending to be a second lane.
Chatbots suggest; agents act, and an agent acting for forty turns re-sends its context forty times. On a per-token meter, that repetition is the bill. DeepSeek’s launch copy says so in its own words: “Cache-hit charges often account for a large share of agent costs.” A model that bills a cache hit at $0.006 per million tokens rewards the fleet that knows how to hit it.
What DeepSeek V4.1-Flash shipped on Sep 10, and what it rerouted on Sep 14
On September 10, 2026, DeepSeek published Introducing DeepSeek-V4.1-Flash, a 552B-parameter mixture-of-experts model presented under the heading “Asymmetric architecture. More intelligence, less cost.” The sentence that explains the price list is the architecture note: “New Causal Encoder–Decoder architecture: just 8B active parameters for input, 16B for output.” The model reads your prompt with half the active parameters it uses to write. DeepSeek does not tie its price list to that split, but it is the architecture’s case for cheap input.
The second claim is about memory. The launch page says the new KV cache needs “1/4 the HBM” and “1/8 the SSD storage” of the previous generation, and follows it with the line quoted above about cache-hit charges. Smaller cache, cheaper hits, and a pricing table built to make you want them. The weights and technical report are on Hugging Face.
Screenshot: DeepSeek, “Introducing DeepSeek-V4.1-Flash: smarter, faster, more efficient.” (September 10, 2026), captured Sep 19, 2026.
The API side, per the release note: the model id is deepseek-flash, and the instruction is one line, “Set your model to deepseek-flash.” V4-Flash and V4-Flash-Vision-Exp are retired; the legacy ids deepseek-v4-flash and deepseek-v4-flash-vision-exp temporarily route to V4.1-Flash. New pricing took effect at 04:00 UTC on September 10.
Then the sentence that quietly re-priced every fleet still pointing at the older flagship: “Starting at 04:00 UTC on Sept 14, 2026, all deepseek-v4-pro requests will route to V4.1-Flash at V4.1-Flash rates. This will continue until V4.1-Pro launches.” The docs give no date for V4.1-Pro.
The numbers, from the pricing page, in USD per million tokens:
deepseek-flash |
Off-peak | Peak |
|---|---|---|
| Input, cache hit | $0.003 | $0.006 |
| Input, cache miss | $0.15 | $0.30 |
| Output | $0.60 | $1.20 |
The same page still lists deepseek-v4-pro at $0.022 / $0.044 for hits, $0.66 / $1.32 for misses and $1.98 / $3.96 for output, which is 4.4 times Flash on a miss, 3.3 times on output and about 7 times on a hit, and then bills V4-Pro requests at Flash rates anyway. It also lists a concurrency limit of 2500 for Flash against 500 for V4-Pro, a 1M context length, and a maximum output of 384K tokens. Those are the facts. The config swaps and rollback lanes from the V4 cutover are covered elsewhere; this piece stays on the two levers the September launch added.
Why the price of a cache hit is now the whole game
A cache miss on Flash costs fifty times a cache hit at either rate. The off-peak discount is a flat half. Put those next to each other and the priority order for a multi-turn agent writes itself: first make the prompt hit the cache, then move the job to the cheap half of the clock.
A job that runs off-peak with a cold cache saves 50%; a job that runs at peak with a warm cache saves roughly 98% on the cached portion. Do both and the miss column shrinks to the tokens that were new this turn.
The usual cost advice starts with the model and ends with the schedule. On DeepSeek the model choice was made for you on September 14. What is left is shape and time.
Step 1: Put the peak window on the fleet calendar, in UTC, with a holiday list you own
The pricing page’s footnote is the schedule. Verbatim: “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, excluding Chinese public holidays. All other hours are off-peak, including weekends and Chinese public holidays in full.”
Screenshot: DeepSeek API Docs, “Models & Pricing” (page undated), captured Sep 19, 2026.
Three things to notice before you encode it. Peak is seven hours per weekday, split by a two-hour trough from 04:00 to 06:00 UTC that is priced off-peak. Peak lines up with Beijing’s working day, 09:00 to 12:00 and 14:00 to 18:00 local, and weekends and Chinese public holidays are off-peak in full. And the docs publish no holiday list, no SLA for the window, and no promise it will not move; the page says “Product prices may vary and DeepSeek reserves the right to adjust them.”
The holiday calendar is yours to maintain and yours to get wrong.
| Peak block (UTC) | Beijing (UTC+8) | Central Europe, CEST (UTC+2) | US Pacific, PDT (UTC−7) |
|---|---|---|---|
| 01:00–04:00 | 09:00–12:00 | 03:00–06:00 | 18:00–21:00 previous day |
| 06:00–10:00 | 14:00–18:00 | 08:00–12:00 | 23:00 previous day–03:00 |
The conversions hold for September and shift by an hour when daylight time ends, on October 25 in Europe and November 1 in the US.
Encode the window once, in the scheduler, never in a prompt or a shell alias:
# provider-windows.yaml (illustrative shape; the scheduler reads it, agents never do)
deepseek:
tz: UTC
peak:
days: [Mon, Tue, Wed, Thu, Fri]
blocks: ["01:00-04:00", "06:00-10:00"]
holidays_file: calendars/cn-public-holidays-2026.yaml # off-peak in full
off_peak_multiplier: 0.5
model: deepseek-flash # never a legacy id
lanes:
flexible:
run_in: off_peak
max_wait_hours: 14 # longest a job may sit waiting for the cheap half
latency_bound:
run_in: any
A flexible job with a fourteen-hour maximum wait never misses the cheap half: the longest peak stretch is four hours, so a job released at 06:00 UTC on a weekday runs by 10:00. The classification itself, latency-bound against flexible, is the subject of the clock-routing schedule, which this piece assumes rather than repeats.
Step 2: Shape every prompt as stable prefix, then variable tail
DeepSeek’s context cache is a disk cache keyed on prefix, and the caching guide is short enough to read in full. The rules that matter for a fleet: it is on by default with no code change; a hit requires that the prefix was already persisted to disk; and “Each cached prefix is an independent, complete unit. A subsequent request can only hit the cache if it fully matches a cache prefix unit.” Persistence happens at request boundaries, through common-prefix detection, and at fixed token intervals. The guide calls the system “best-effort” with no guaranteed hit rate, and says an idle cache is cleared “usually within a few hours to a few days.”
Fully matches is the operative phrase. One changed byte at position ten thousand means every cache unit after it misses. So the prompt for a long-running agent is built in layers of decreasing stability, in the same order on every turn.
Stable material first, in a fixed order; new material last. The scheduler only decides when the tail gets sent.
The prefix rules, in the order the cache sees them:
- System prompt and operating rules first, and byte-identical across turns. No timestamp, no run id, no random example order, no line that states the current date. Put the date in the tail if a task needs it.
- Tool schemas second, in a fixed order. A harness that sorts tools by last use, or that appends a newly discovered MCP server in the middle of the list, invalidates every cache unit after the insertion point. Pin the order in config.
- Repo brief and reference documents third. These change per project, not per turn. Load them once and keep them verbatim.
- Conversation history as append-only. Never rewrite, summarize or reorder earlier turns mid-job; the turn you edit is the turn the cache stops matching. If you must compact, do it at a job boundary, then pay one miss on the new prefix and warm it.
- The current task and the latest tool results last. This is the only part that should change between turns, and it is the only part you should expect to pay the miss rate on.
The request shape, with the prefix marked so a reviewer can see it:
# illustrative request shape against https://api.deepseek.com (OpenAI-compatible format)
messages = [
{"role": "system", "content": OPERATING_RULES}, # stable, byte-identical
{"role": "system", "content": TOOL_SCHEMAS_PINNED}, # stable, fixed order
{"role": "system", "content": REPO_BRIEF}, # stable per project
*history, # append-only
{"role": "user", "content": task_for_this_turn}, # variable tail
]
resp = client.chat.completions.create(model="deepseek-flash", messages=messages)
u = resp.usage
hit, miss = u.prompt_cache_hit_tokens, u.prompt_cache_miss_tokens
log_turn(job_id, hit, miss, u.completion_tokens, window=current_window_utc())
The prompt_cache_hit_tokens and prompt_cache_miss_tokens fields are the whole feedback loop. Log them per turn, per job, per window, from day one, before a harness update that reorders its tool list teaches you to.
Step 3: Read the DeepSeek V4.1-Flash hit rate off the usage object every night
Hit rate is hits divided by hits plus misses, over tokens rather than requests, because one 200k-token miss weighs as much as fifty 4k-token hits. A nightly summary is enough:
# illustrative: token-weighted hit rate per job from the turn log
jq -r '[.job, .hit, .miss] | @tsv' turns.jsonl \
| awk '{h[$1]+=$2; m[$1]+=$3} END {for (j in h) printf "%s %d%%\n", j, 100*h[j]/(h[j]+m[j])}'
Starting thresholds, not laws:
| Signal | Healthy | Investigate | Stop and fix |
|---|---|---|---|
| Hit rate, multi-turn job (turn 3 onward) | ≥ 80% | 50–80% | < 50% |
| Hit rate, turn 1 of a job | 0% expected (cold) | n/a | n/a |
| Miss tokens per turn, steady state | ≈ size of the tail | 2× the tail | ≥ prefix size (prefix is churning) |
| Share of flexible tokens billed at peak | < 10% | 10–30% | > 30% (scheduler is not holding) |
A turn-3-onward hit rate under 50% on a job that re-sends a large prefix means the prefix is not stable, and the fix is in step 2, never in the model. A first-turn miss every night is normal, since an idle cache is cleared within hours to days. Budget one miss per job start.
Step 4: Re-base every V4-Pro budget, alert and eval, because the meter already moved
Since 04:00 UTC on September 14, a request that names deepseek-v4-pro is served by V4.1-Flash and billed at Flash rates. Three of your artifacts were built on the old assumption, and each fails in its own way.
Budgets. A per-job ceiling set for V4-Pro output at $3.96 per million tokens is now 3.3× too loose at peak and 6.6× too loose off-peak. Nothing overspends against it, so nobody notices, and the ceiling stops being a control. Re-derive every DeepSeek ceiling from the Flash column and date the change.
Anomaly alerts. Most cost-anomaly alerting fires on spikes. A roughly fourfold drop is also an anomaly, and on September 14 it was the only signal that a routing change had happened. Add a floor: if a lane’s daily spend falls below 40% of its trailing-week median with volume unchanged, page someone, because either the meter moved or jobs are failing silently.
Evals. Any eval baseline pinned to deepseek-v4-pro since September 14 measured Flash while labeled Pro. Re-run the baseline set against deepseek-flash explicitly, keep the pre-14th V4-Pro numbers as a historical row, and when V4.1-Pro launches, treat it as a new model with a new baseline rather than the old one coming back. The general drill for any in-catalog reroute, ordered fallbacks and smoke tests included, is in forced model routing as a continuity drill; the homework here is the three artifacts above.
Concurrency belongs on the list too. The pricing page gives Flash a limit of 2500 against 500 for V4-Pro, so a rate limiter tuned for 500 is throttling a lane that could run five times wider. Whether you want it to is a budget question.
Step 5: Strip retired ids out of every failover list
A failover list that reads [deepseek-v4-pro, deepseek-v4-flash] contains two aliases of one model. The pricing page’s footnote says the legacy names are “still accepted, but the corresponding models have been retired,” and the routing note calls the compatibility routing temporary. So the list fails over from Flash to Flash, and on the day the routing ends it fails over from Flash to an error. Neither is a second lane.
The rule: a failover target must be a distinct model that the provider documents as its own lane. Aliases, legacy names and forced routes do not qualify. Write the DeepSeek entry in your failover matrix as one lane, deepseek-flash, and pair it with a lane somewhere else. When V4.1-Pro ships, it earns its own row after its own baseline, not before.
# failover.yaml (illustrative shape)
lanes:
- id: deepseek-flash # the only DeepSeek id that is a lane today
provider: deepseek
pricing_windows: provider-windows.yaml#deepseek
- id: <distinct model at another provider>
provider: <other>
retired_never_route: # a linter fails the build if these appear anywhere
- deepseek-v4-flash
- deepseek-v4-flash-vision-exp
- deepseek-v4-pro # billed as Flash since 2026-09-14 04:00 UTC; not a lane
Add the linter. A grep across configs, dotfiles and CI for the three ids takes a minute and catches the alias pasted from a six-week-old README.
Worked example: one overnight job on DeepSeek V4.1-Flash, four ways
Illustrative job, real prices. Picture a research-and-refactor agent that runs forty turns, sends a 60k-token prompt each turn (a 50k stable prefix and a 10k tail), and writes 2k tokens per turn: 2.4M input tokens and 80k output tokens per job. The variables are the clock and the hit rate; a poorly shaped prompt hits 20% of its input tokens, a well-shaped one 80%.
Real prices from the DeepSeek pricing page, drawn to one linear scale. The cache-hit bars are slivers on purpose.
| Case | Window | Hit rate | Hit cost | Miss cost | Output cost | Per job (illustrative) | Per 100 jobs |
|---|---|---|---|---|---|---|---|
| A | Peak | 20% | $0.003 | $0.576 | $0.096 | $0.68 | $68 |
| B | Peak | 80% | $0.012 | $0.144 | $0.096 | $0.25 | $25 |
| C | Off-peak | 20% | $0.001 | $0.288 | $0.048 | $0.34 | $34 |
| D | Off-peak | 80% | $0.006 | $0.072 | $0.048 | $0.13 | $13 |
The arithmetic is tokens times price from the table above; DeepSeek’s own deduction rule is “The expense = number of tokens × price.” Case A to case D is a 5.4× difference on an identical job, and the prompt shape (A to B) is worth more than the clock (A to C). The same job before September 14, billed at V4-Pro peak prices with a 20% hit rate, would have cost about $2.87, which is the number your old budget line still assumes.
One more line for the ledger: the pricing page says fees are deducted from a topped-up balance or a granted balance, with the granted balance drawn first when both exist. A promotional grant makes the first weeks of a lane look free. Meter tokens times list price, whichever balance paid.
Four signals the DeepSeek cache or off-peak lane slipped
The hit rate collapses after a harness update. A new version sorts tools differently, injects a per-run header, or compacts history mid-job. Signal: turn-3-onward hit rate drops on one lane only, the night of a version bump. Fix: pin the harness version per lane and diff the first request before and after any upgrade.
A flexible job never runs. The holiday file is stale, someone wrote the window in local time, or the scheduler treated 04:00–06:00 UTC as peak. Signal: a job with max_wait_hours: 14 still queued at hour fifteen. Fix: the scheduler emits the planned release time at enqueue, and a wait past the maximum is a failure, not a delay.
The temporary routing ends. V4.1-Pro launches, deepseek-v4-pro requests stop being billed as Flash, and any config still naming that id changes price overnight. Signal: the spend floor from step 4 inverts into a spike on one lane. Fix: the linter from step 5 means no config names that id, so the day passes with nothing to do.
The cache is cold every turn, not just the first. The prefix contains something that changes per request. Signal: miss tokens per turn equal to the prefix size. Fix: diff the first 2k bytes of two consecutive requests; the changing field is in there.
The operating layer owns the clock; the model only answers
None of this belongs inside a prompt. The window, the holiday list, the lane definitions, the hit-rate log and the retired-id linter live in the layer that starts, holds, steers and stops agents across every CLI and provider you run, the operating layer described in the agentic-ops thesis. A model that halves its price at 10:00 UTC is a fact about the world; deciding which jobs may wait for 10:00 is a decision about your fleet, made in one place so every agent inherits it.
That same place separates the operating bill from the token bill, and it is where a sibling piece on metering overnight Claude jobs on cheaper cache reads meets this one. The prefix-first rule in step 2 is the rule Anthropic’s prompt caching docs teach for a cache with a five-minute default lifetime rather than a disk; the price lists differ, the shape does not. Two providers, two cache dialects, one scheduler.
FAQ: DeepSeek V4.1-Flash off-peak and cache pricing
What are DeepSeek’s off-peak hours in UTC?
Peak hours are 01:00 to 04:00 and 06:00 to 10:00 UTC, Monday through Friday, excluding Chinese public holidays; every other hour is off-peak at half the peak rate, including all weekend hours and Chinese public holidays in full. The 04:00 to 06:00 UTC trough on weekdays is off-peak, per the DeepSeek API pricing page.
How much does a DeepSeek V4.1-Flash cache hit cost?
On the deepseek-flash model a cache hit is $0.006 per million input tokens at peak and $0.003 off-peak, against $0.30 and $0.15 for a cache miss and $1.20 and $0.60 for output. A hit costs one fiftieth of a miss, which is why prompt shape matters more than the clock for multi-turn agents.
Is deepseek-v4-pro still a separate model?
Since 04:00 UTC on September 14, 2026, all deepseek-v4-pro requests route to V4.1-Flash and are billed at V4.1-Flash rates until V4.1-Pro launches, per DeepSeek’s release note. Treat the id as an alias of deepseek-flash for budgets and evals, and do not list it as a failover target.
Sources
- DeepSeek, Introducing DeepSeek-V4.1-Flash: smarter, faster, more efficient. (September 10, 2026)
- DeepSeek API Docs, DeepSeek-V4.1-Flash Release (2026/09/10)
- DeepSeek API Docs, Models & Pricing
- DeepSeek API Docs, Context Caching
- Hugging Face, deepseek-ai/DeepSeek-V4.1-Flash (model card and technical report)
- @deepseek_ai on X, V4.1-Flash launch thread, KV cache post (September 10, 2026)
- Anthropic, Prompt caching (the prefix-stability rules of the other cache dialect this fleet runs)
