Como medir a latência real do DeepSeek V4.1 Flash no seu app (e não no papel)

A latência do DeepSeek V4.1 Flash que importa não é a do anúncio, é a que o seu usuário sente na sua rota, no seu horário, com o seu prompt. Este tutorial mostra como instrumentar o app com o SDK da OpenAI apontando para https://api.deepseek.com e model="deepseek-flash", medindo tempo até o primeiro token (com stream: true), tempo total por requisição, tokens de saída por segundo e hit/miss de cache. Tudo vai pra log com timestamp UTC, pra você olhar percentis em vez de média e descobrir se a lentidão é do modelo ou do seu código 🙂
Fala aí, beleza? A DeepSeek soltou no dia 10 de setembro de 2026 o DeepSeek-V4.1-Flash, o menor modelo da nova família de arquitetura, com foco declarado em velocidade de inferência e throughput
No anúncio vieram os números da casa: pico de 420 tokens por segundo em tarefas de raciocínio com texto longo e throughput ponta a ponta de 409,5 tokens por segundo
Aí vem a parte que ninguém conta: número de anúncio é medido no laboratório de quem anunciou, e o número que importa é o que o seu usuário sente na sua rota, no seu horário, com o seu prompt de 12 mil tokens colado na frente
Esses dois números podem ser verdadeiros ao mesmo tempo, e é justamente por isso que tu precisa medir dentro da tua aplicação
Neste post a gente vai instrumentar o app de verdade: tempo até o primeiro token (o famoso TTFT), tempo total por requisição, tokens de saída por segundo, percentis (p50, p90 e p95) e variação ao longo do dia, tudo caindo em log pra você comparar depois
Bora ver na prática?
O que você precisa antes de começar
Lista curta, sem PC da Nasa:
- Uma chave de API da DeepSeek
- O SDK da OpenAI instalado, porque a API da DeepSeek é compatível com o formato da OpenAI:
pip3 install openaino Python ounpm install openaino Node - A
base_urlapontando prahttps://api.deepseek.com(também aceitahttps://api.deepseek.com/v1, e atenção nisso: essev1não tem NADA a ver com a versão do modelo, é só o caminho da API) - O nome de modelo certo:
model="deepseek-flash"é como você chama o V4.1 Flash - Um relógio monotônico da sua linguagem (
time.perf_counter()no Python,performance.now()no JS) - Um destino de log: arquivo
.jsonl, tabela no banco, o que for mais fácil de consultar depois
E o que este post NÃO cobre, pra deixar honesto desde já: dashboard pronto, ferramenta externa de observabilidade e correlação do seu log com o id do request do lado do provedor
Aqui é medição do lado do seu app, que é o lado que você controla
Passo a passo para instrumentar a latência no seu app
- Faça a chamada com streaming ligado. O endpoint de Chat Completions aceita o parâmetro booleano
stream, e quando ele étruea resposta vem como um stream de server-sent events. Sem isso você não tem primeiro token pra cronometrar
Formação Claude Code
Domine Claude Code do absoluto zero até o avançado
- 118 aulas
- 4 projetos
- 9h 33min
import time
from openai import OpenAI
client = OpenAI(
api_key="SUA_CHAVE",
base_url="https://api.deepseek.com",
)
t0 = time.perf_counter()
stream = client.chat.completions.create(
model="deepseek-flash",
messages=[{"role": "user", "content": "Resuma este texto em 3 linhas: ..."}],
stream=True,
)
O erro comum deste passo: marcar o t0 DEPOIS de montar o prompt gigante e serializar tudo
Se o seu app leva 300ms pra montar o payload, isso é latência sim, só que é sua, não do modelo
Marque t0 no ponto mais próximo do envio e, se quiser, guarde separado o tempo de montagem
- Marque o
t_firstno primeiro chunk que trouxer conteúdo. Esse delta é o TTFT, o tempo em que o seu usuário fica olhando pro cursor piscando
t_first = None
pedacos = []
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
if t_first is None:
t_first = time.perf_counter()
pedacos.append(chunk.choices[0].delta.content)
ttft = t_first - t0
O erro comum deste passo: fazer a chamada sem streaming, cronometrar a resposta inteira e chamar aquilo de TTFT
Sem stream você só tem tempo total, e o primeiro token e o último chegam juntos
Outro deslize clássico é contar o primeiro chunk mesmo quando ele vem sem content, o que te dá um TTFT otimista demais
- Marque o
t_endno encerramento do stream pra ter o tempo total. É o número que você compara com o timeout do seu backend e com a paciência do usuário
t_end = time.perf_counter()
total = t_end - t0
O erro comum deste passo: cronometrar o fim depois de já ter feito parsing, salvamento no banco e mais três coisas
Fecha o cronômetro na saída do loop, o resto é outra métrica
- Ligue o
include_usagee leia ousageno lugar certo. Em streaming, o parâmetrostream_options.include_usagecontrola a entrega das estatísticas de tokens ao longo do stream
Com stream_options: {"include_usage": true}, TODOS os chunks passam a trazer o campo usage, sendo null em todos menos no último
E o total? Esse vem no último chunk antes do marcador de encerramento do stream, com ou sem o parâmetro ligado
Ou seja: o include_usage muda o formato dos chunks do meio, não a existência do total no fim
stream = client.chat.completions.create(
model="deepseek-flash",
messages=[{"role": "user", "content": "..."}],
stream=True,
stream_options={"include_usage": True},
)
usage = None
for chunk in stream:
if chunk.usage is not None:
usage = chunk.usage
# ... aqui continua a lógica do t_first do passo 2
O erro comum deste passo: procurar o usage nos chunks do meio, ver null, achar que a API não devolve token nenhum e sair inventando contagem na mão
Ele vem null mesmo, tu tem que guardar o último que não for nulo
Em JavaScript o desenho é o mesmo:
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.DEEPSEEK_API_KEY,
baseURL: "https://api.deepseek.com",
});
const t0 = performance.now();
let tFirst = null;
let usage = null;
const stream = await client.chat.completions.create({
model: "deepseek-flash",
messages: [{ role: "user", content: "..." }],
stream: true,
stream_options: { include_usage: true },
});
for await (const chunk of stream) {
if (chunk.usage) usage = chunk.usage;
const delta = chunk.choices?.[0]?.delta?.content;
if (delta && tFirst === null) tFirst = performance.now();
}
const tEnd = performance.now();
const ttft = tFirst - t0;
const total = tEnd - t0;
- Calcule os tokens de saída por segundo separando espera de geração. A conta boa não é token dividido pelo tempo total, é token de saída dividido pelo intervalo entre o primeiro token e o fim
completion_tokens = usage.completion_tokens
geracao = t_end - t_first
tps_saida = completion_tokens / geracao if geracao > 0 else 0
Por que separar? Porque essas duas coisas quebram por motivos DIFERENTES
Espera alta cheira a fila, rede ou prompt gigante sendo processado
Geração lenta é outra conversa
O erro comum deste passo: dividir os tokens pelo tempo total e concluir que "o modelo tá lento", quando na real ele passou metade do tempo esperando pra começar
- Registre o status de cache do request. A resposta traz no objeto
usagedois campos que contam essa história:prompt_cache_hit_tokens(os tokens de entrada que deram cache hit) eprompt_cache_miss_tokens(os que não deram)
E tem uma relação simples que serve de conferência: prompt_tokens é igual à soma dos dois
u = usage.model_dump()
cache_hit = u.get("prompt_cache_hit_tokens")
cache_miss = u.get("prompt_cache_miss_tokens")
# conferência rápida: cache_hit + cache_miss == u["prompt_tokens"]
O erro comum deste passo: ignorar esses dois campos e depois não conseguir explicar por que a mesma rota, com o mesmo prompt, teve latência e custo diferentes em duas chamadas seguidas
- Defina a linha de log e não mude mais ela. Métrica sem contexto não serve pra nada, e log inconsistente é pior que log nenhum
O mínimo que vale registrar por requisição:
ts_utc: o timestamp em UTC (em UTC mesmo, você vai entender o porquê logo abaixo)modelo: o nome que você mandou na chamadattft_msetotal_msprompt_tokensecompletion_tokenscache_hit_tokensecache_miss_tokenstamanho_prompt: caracteres ou tokens do que você enviourota: o identificador da rota do seu app (/chat,/resumo,/suporte, o que for)
import json, datetime
linha = {
"ts_utc": datetime.datetime.now(datetime.timezone.utc).isoformat(),
"modelo": "deepseek-flash",
"rota": "/resumo",
"ttft_ms": round(ttft * 1000, 1),
"total_ms": round(total * 1000, 1),
"prompt_tokens": u["prompt_tokens"],
"completion_tokens": completion_tokens,
"cache_hit_tokens": cache_hit,
"cache_miss_tokens": cache_miss,
"tps_saida": round(tps_saida, 1),
}
with open("latencia.jsonl", "a", encoding="utf-8") as f:
f.write(json.dumps(linha, ensure_ascii=False) + "\n")
O erro comum deste passo: gravar o horário no fuso local do servidor
Aí você troca de máquina, o fuso muda, e o seu histórico vira ficção
Grava em UTC e converte na hora de olhar 🙂
- Rode a coleta em horários diferentes e calcule p50, p90 e p95 do
ttft_ms, nunca média. Média esconde o usuário que esperou 9 segundos no meio de cem que esperaram 1, e o p95 é justamente o número que mostra o pior caso que ainda é comum
import json
valores = sorted(
json.loads(l)["ttft_ms"]
for l in open("latencia.jsonl", encoding="utf-8")
)
def percentil(dados, p):
if not dados:
return None
pos = min(int(round(p / 100 * len(dados) + 0.5)) - 1, len(dados) - 1)
return dados[pos]
print("p50:", percentil(valores, 50))
print("p90:", percentil(valores, 90))
print("p95:", percentil(valores, 95))
Que percentil é esse, afinal? p95 quer dizer que 95% das suas requisições ficaram abaixo daquele valor, e é ele que você promete pro usuário, não a média bonitinha
O mesmo cálculo serve pro total_ms e pro tps_saida, é só trocar o campo que você lê do log
O erro comum deste passo: medir 5 requisições de tarde, num prompt curtinho, e sair falando em reunião que "a latência é X"
Cinco amostras não é medição, é palpite com CSV
A lentidão é do modelo ou do seu código?
Agora que o log existe, dá pra parar de chutar
Se liga nos padrões mais comuns:
Sintoma: TTFT alto e geração rápida
O usuário fica encarando a tela e, quando começa, o texto sai voando
Causa provável: fila, rede ou prompt gigante sendo processado antes de qualquer coisa sair
Não é a geração que está lenta, é o que acontece ANTES dela
Solução: cruze o ttft_ms com o tamanho_prompt no seu log e veja se os piores TTFT são justamente os prompts maiores
Como prevenir: teste a mesma rota com um prompt mínimo e um prompt real, no mesmo minuto, e compare os dois TTFT
Sintoma: tempo total alto com TTFT baixo
Começou rápido, terminou tarde
Causa provável: ou a resposta é longa demais mesmo (olhe completion_tokens), ou o seu front só renderiza quando o stream termina, o que anula todo o benefício do streaming
Esse segundo caso é cruel: a API te entregou o primeiro token em pouquíssimo tempo e o seu código guardou tudo num buffer pra mostrar no final
Solução: renderize por chunk, e trate a resposta longa como decisão de produto, não como problema de infra
Como prevenir: logue o TTFT também no cliente, não só no servidor
Sintoma: a latência oscila conforme a hora do dia
Esse é o motivo de eu ter insistido no timestamp em UTC lá em cima
A DeepSeek define uma janela de horário de pico com tarifa cheia: 01:00 às 04:00 UTC e 06:00 às 10:00 UTC, de segunda a sexta
Todas as demais horas são off-peak, com desconto
Ou seja: a hora da chamada muda o seu custo, e é exatamente por isso que ela precisa estar no log ao lado da latência
Solução: agrupe os seus percentis por faixa de hora UTC antes de tirar conclusão
Como prevenir: colete pelo menos um ciclo de 24 horas antes de comparar qualquer coisa
Sintoma: os números de cache variam sem explicação
Um dia prompt_cache_hit_tokens está gordo, no outro está no chão, com o mesmo tipo de requisição
Causa: o cache de contexto em disco da DeepSeek casa APENAS o prefixo da entrada, e funciona em regime de melhor esforço, sem garantia de 100% de acerto
E tem mais: a saída continua sendo gerada por inferência, cache não devolve resposta pronta
Solução: se você tem um bloco fixo de instruções, mantenha ele estável e no COMEÇO do prompt, e deixe a parte que muda pro final
Como prevenir: trate taxa de acerto como tendência que você observa no log, nunca como promessa
Sintoma: comparei duas versões e deu tudo igual
Esse aqui pega muita gente boa
Os nomes de modelo da geração anterior continuam sendo roteados temporariamente para o V4.1 Flash por compatibilidade: deepseek-v4-flash e deepseek-v4-flash-vision-exp caem no V4.1 Flash, e os modelos V4 Flash e V4-Flash-Vision-Exp foram aposentados
E a partir de 14 de setembro de 2026, às 12:00 no horário de Pequim (04:00 UTC), as chamadas ao deepseek-v4-pro também passam a ser roteadas pro V4.1 Flash e cobradas ao preço do V4.1 Flash, até que saia um V4.1 Pro
Traduzindo pro seu log: rótulos diferentes na coluna modelo podem ser exatamente o MESMO modelo respondendo
Solução: antes de comemorar (ou xingar) uma diferença entre versões, confira se os dois nomes não estão sendo roteados pro mesmo lugar
Como prevenir: registre o nome que você enviou e a data da coleta, porque roteamento é coisa que muda com o tempo
Número do anúncio x número do seu app
Aqueles 420 tokens por segundo de pico em tarefas de raciocínio com texto longo e os 409,5 tokens por segundo de throughput ponta a ponta saíram do anúncio oficial da DeepSeek
São números da casa, sobre a capacidade de geração
O seu log fala de outra coisa: a experiência completa, com a sua rede, o seu prompt, o seu horário e o seu código no meio do caminho
| Métrica | De onde vem | Serve pra decidir |
|---|---|---|
| Pico de 420 tokens/s em raciocínio com texto longo | Anúncio oficial da DeepSeek | Se o modelo tem fôlego de geração pro tipo de tarefa |
| Throughput ponta a ponta de 409,5 tokens/s | Anúncio oficial da DeepSeek | Referência de capacidade divulgada pelo fornecedor |
| TTFT do seu usuário | Seu log (t0 até o primeiro chunk com conteúdo) |
Se o chat parece travado ou responsivo |
| Tempo total por requisição | Seu log (t0 até o fim do stream) |
Timeout de backend e desenho da UI |
| p50, p90 e p95 | Seu log, agregado | Meta de qualidade real, sem média enganosa |
| Hit e miss de cache | usage do último chunk |
Custo de entrada e estabilidade do prefixo |
| Horário da chamada (UTC) | Seu log | Cruzar com a janela de pico e planejar carga |
Os dois lados da tabela podem estar certos ao mesmo tempo, beleza?
O anúncio mede geração em condição controlada
O seu log mede espera, geração, rede e o seu código, tudo somado
Quando alguém disser "mas o modelo faz 420 tokens por segundo", a resposta honesta é: faz, e mesmo assim o meu p95 de TTFT é o que decide se o usuário fica ou fecha a aba
O que fazer com os números depois de medir
Medir por medir é gráfico bonito no Notion e nada mudando no produto
O que dá pra fazer com esse log:
- Definir meta de TTFT pro chat com streaming. Escolha um valor de p95 que você considera aceitável e trate qualquer coisa acima disso como bug, não como "é a IA"
- Decidir entre encurtar o prompt ou estabilizar o prefixo. Aqui o custo entra na conta: a entrada com cache hit sai por US$ 0,003 por 1M de tokens, contra US$ 0,15 por 1M sem cache, e a saída fica em US$ 0,60 por 1M, tudo isso em horário fora de pico. Em horário de pico as tarifas são o dobro
- Deslocar carga em lote pra janela off-peak. Se o job não é interativo, rodar fora de 01:00 às 04:00 UTC e 06:00 às 10:00 UTC (de segunda a sexta) muda o que você paga. Vale principalmente pra fluxos de automação, tipo um agente de rastreamento de pedidos no WhatsApp, onde ninguém está olhando pro cursor esperando o token aparecer
- Usar o contexto grande com consciência. O model card oficial descreve o DeepSeek-V4.1-Flash com suporte a contexto de até 1 milhão de tokens. Poder enfiar um prompt gigante não significa que sai de graça em tempo: seu log com
tamanho_promptdo lado dottft_msmostra o preço disso - Medir também as requisições com imagem. O V4.1 Flash é o primeiro modelo nativamente multimodal da DeepSeek, com entrada de texto e imagem e compreensão visual embutida na arquitetura, sem módulo de visão separado. Se a sua rota manda imagem, ela merece a própria linha de log e os próprios percentis
Uma coisa que a DeepSeek afirma no anúncio e que pesa na decisão: segundo ela, o V4.1 Flash superou o V4 Pro em testes internos e externos, em desempenho, custo, velocidade e tempo total de conclusão, e a aposentadoria do V4 Pro está em andamento
Mesmo assim, a pergunta "melhorou no MEU app?" só o seu log responde 😀
Vídeo: entendendo o seu código antes de otimizar
Antes de sair instrumentando rota, ajuda MUITO enxergar o desenho do que você já tem
Pra começar do zero nesse ponto, este vídeo do canal mostra uma skill que faz a IA ler o seu código e desenhar a arquitetura sozinha:
É material complementar pra quem quer mapear onde as chamadas de modelo realmente acontecem no projeto antes de decidir onde colocar o cronômetro
Na mesma linha de usar agente de código pra outras pontas do trabalho, tem também um app open source que serve pra transformar o agente em ferramenta de design
Conclusão: meça antes de trocar de modelo
Recapitulando o que ficou de pé aqui:
Latência não se lê em anúncio, se mede na sua aplicação
Com stream: true, stream_options: {"include_usage": true} e um relógio monotônico, você já tem TTFT, tempo total, tokens de saída por segundo e status de cache por requisição
Com volume de coleta, esses números viram p50, p90 e p95, que é o jeito honesto de falar de latência
Com timestamp em UTC no log, você cruza tudo isso com a janela de pico e para de brigar com fantasma
Seu próximo passo é bem concreto: escolha UMA rota real hoje, instrumente ela, colete 24 horas de dados passando por pico e por off-peak, e só depois olhe os percentis
E antes de trocar o nome do modelo no código achando que resolveu, lembra do roteamento em vigor: nome antigo pode estar caindo no V4.1 Flash do mesmo jeito
Mede primeiro, decide depois
até o próximo post!
Perguntas frequentes
Qual a diferença entre os 420 tokens por segundo anunciados e a latência do DeepSeek V4.1 Flash que eu vou medir no meu app?
O número de 420 tokens por segundo é o pico em tarefas de raciocínio com texto longo, medido pela própria DeepSeek, e o throughput ponta a ponta divulgado foi de 409,5 tokens por segundo. Na sua aplicação entram outras variáveis: tamanho do seu prompt, rede até o seu servidor e horário da chamada, então os dois números podem ser verdadeiros ao mesmo tempo sem bater um com o outro.
Preciso chamar deepseek-v4-flash ou deepseek-flash pra medir a latência certa do modelo novo?
O nome de modelo correto pra usar na API é model="deepseek-flash". Os nomes antigos deepseek-v4-flash e deepseek-v4-flash-vision-exp continuam sendo roteados temporariamente para o V4.1 Flash por compatibilidade, mas os modelos V4 Flash e V4-Flash-Vision-Exp já foram aposentados.
O horário de pico da DeepSeek muda a latência que eu vou medir, ou só o preço da chamada?
O que está confirmado é que o horário de pico (01:00 às 04:00 UTC e 06:00 às 10:00 UTC, de segunda a sexta) dobra o preço por milhão de tokens em relação ao horário fora de pico. Não tem dado oficial sobre variação de velocidade nesse período, então o certo é você mesmo rodar a instrumentação dentro e fora dessa janela e comparar.
O cache de contexto da DeepSeek garante uma latência menor em toda chamada?
Não. O cache em disco da DeepSeek casa apenas o prefixo da entrada e funciona em regime de melhor esforço, sem taxa de acerto garantida. É por isso que o objeto usage separa prompt_cache_hit_tokens de prompt_cache_miss_tokens, pra você enxergar em cada request se o hit realmente aconteceu.
Ainda faz sentido chamar deepseek-v4-pro depois do lançamento do V4.1 Flash?
A partir de 14 de setembro de 2026, às 12:00 no horário de Pequim (04:00 UTC), as chamadas para deepseek-v4-pro passam a ser roteadas para o V4.1 Flash e cobradas no preço do V4.1 Flash, até que saia um V4.1 Pro. Na prática, pra medir a latência do DeepSeek V4.1 Flash direto, o caminho mais limpo já é chamar model="deepseek-flash".
A janela de contexto de 1 milhão de tokens do V4.1 Flash afeta como eu devo testar o TTFT?
O V4.1 Flash suporta contexto de até 1 milhão de tokens, então prompt curto e prompt de 12 mil tokens tendem a gerar TTFT bem diferentes. Teste com o tamanho de prompt real do seu app, não só com uma frase de exemplo, senão o número que você mede não representa o que o usuário sente.
Formações
Formação Vibe Coding
Do Prompt ao Produto: Crie Software Real com IA
- 474 aulas
- 20 projetos
- 39h 27min
Blog | Mais populares
DeepSeek V4 Pro Max: o que é e como escolher entre as variantes da família V4
DeepSeek V4 Pro Max não é um modelo separado: é o modo de raciocínio máximo do V4-Pro. Veja como funciona e como escolher entre as variantes.
DeepSeek V4 Pro: o que é e quando compensa usar em vez do V4 Flash?
DeepSeek V4 Pro tem 1,6 tri de parâmetros e janela de 1 milhão de tokens. Entenda o preço, o desempenho e quando vale mais a pena que o V4 Flash.
Como rodar o DeepSeek V4 no Ollama: o passo a passo e o que checar antes de tentar
Rodar o DeepSeek V4 no Ollama hoje é via tag cloud: veja como fazer login, baixar a tag e usar via CLI ou API local, e quando vale ir de GGUF offline.
