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

gráfico medindo a latência do DeepSeek V4.1 Flash em um app real
Resposta rápida

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 openai no Python ou npm install openai no Node
  • A base_url apontando pra https://api.deepseek.com (também aceita https://api.deepseek.com/v1, e atenção nisso: esse v1 nã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

  1. Faça a chamada com streaming ligado. O endpoint de Chat Completions aceita o parâmetro booleano stream, e quando ele é true a resposta vem como um stream de server-sent events. Sem isso você não tem primeiro token pra cronometrar
Formação Claude Code
Formação Recomendada

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

  1. Marque o t_first no 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

  1. Marque o t_end no 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

  1. Ligue o include_usage e leia o usage no lugar certo. Em streaming, o parâmetro stream_options.include_usage controla 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;
  1. 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

  1. Registre o status de cache do request. A resposta traz no objeto usage dois campos que contam essa história: prompt_cache_hit_tokens (os tokens de entrada que deram cache hit) e prompt_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

  1. 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 chamada
  • ttft_ms e total_ms
  • prompt_tokens e completion_tokens
  • cache_hit_tokens e cache_miss_tokens
  • tamanho_prompt: caracteres ou tokens do que você enviou
  • rota: 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 🙂

  1. 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_prompt do lado do ttft_ms mostra 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.




Escrito por | Matheus Battisti

Matheus Battisti
Fundador da Hora de Codar

Programador apaixonado pelo mundo das tecnologias, sempre buscando em aprender e se aprofundar em linguagens, frameworks e o que mais for necessário para executar um bom trabalho. Agora tem uma nova missão que é de passar seu conhecimento adiante para formar novos programadores e especializar mais os que já são.

Subscribe
Notify of
guest

0 Comentários
Oldest
Newest Most Voted

Formações

Formação Vibe Coding

Formação Vibe Coding

Do Prompt ao Produto: Crie Software Real com IA

  • 474 aulas
  • 20 projetos
  • 39h 27min

Blog | Mais populares