DEV Community

Olivier
Olivier

Posted on

Absorber les +50 % de l'API Claude sans couper une feature

Le 1er septembre 2026, le tarif de lancement de Claude Sonnet 5 s'arrête. L'input passe de 2 $ à 3 $ le million de tokens, l'output de 10 $ à 15 $ : +50 % sur les deux lignes, pour tout le monde qui appelle l'API en paiement à l'usage. La panique par défaut, c'est de couper des fonctionnalités ou de rétrograder vers un modèle plus faible. Il y a mieux, et c'est déjà dans l'API. Deux mécanismes — le prompt caching et le batch — encaissent la hausse à ta place, souvent avec de la marge. Voici le code, les chiffres, et les pièges que j'ai payés pour que tu ne les paies pas.

Ce qui bouge exactement le 1er septembre

Trois lignes suffisent à raisonner. Le reste du barème (Opus, Haiku, contexte 1M) ne change pas.

Poste Sonnet 5 (par M de tokens) Jusqu'au 31 août Dès le 1er sept.
Input standard 2 $ 3 $
Output 10 $ 15 $
Lecture cache (hit) 0,20 $ 0,30 $

Retiens la troisième ligne, parce que c'est elle qui gagne la partie. Un cache hit coûte 10 % du prix d'input. Même après la hausse, lire depuis le cache à 0,30 $ reste moins cher que l'ancien input plein à 2 $. Autrement dit, le contexte que tu répètes à chaque appel — un system prompt costaud, une doc, des exemples few-shot — peut être payé une fois puis relu pour trois fois rien.

Le prompt caching, concrètement

Le principe est simple : tu marques un bloc stable avec cache_control, et tout ce qui précède ce marqueur est mis en cache. Le premier appel paie une écriture ; les suivants, dans la fenêtre TTL, lisent à 10 %.

import anthropic

client = anthropic.Anthropic()
DOCS = load_docs()  # ~20 000 tokens, identiques à chaque requête

def ask(question: str):
    return client.messages.create(
        model="claude-sonnet-5",
        max_tokens=1024,
        system=[
            {"type": "text", "text": "Assistant support de l'app Lumière."},
            {
                "type": "text",
                "text": DOCS,
                "cache_control": {"type": "ephemeral"},  # TTL 5 min
            },
        ],
        messages=[{"role": "user", "content": question}],
    )
Enter fullscreen mode Exit fullscreen mode

La question de l'utilisateur arrive après le bloc caché : elle est volatile, elle n'est pas mise en cache, et c'est exactement ce qu'on veut. Ne te fie jamais à ton intuition. Vérifie dans usage, qui ne ment pas.

r = ask("Comment j'annule un rendez-vous ?")
print(r.usage)
# 1er appel : cache_creation_input_tokens=20000, cache_read_input_tokens=0
# appels < 5 min : cache_creation_input_tokens=0, cache_read_input_tokens=20000
Enter fullscreen mode Exit fullscreen mode

Si cache_read_input_tokens reste à zéro alors que tu t'attends à un hit, tu as un bug quelque part — et ce bug te coûte de l'argent en silence.

Les pièges du cache que j'ai payés

Le caching n'est pas magique, et il échoue sans lever d'exception. Voici les cinq façons de croire qu'on cache alors qu'on paie plein tarif.

  • Minimum 1024 tokens. Sous ce seuil, Sonnet ne met rien en cache et l'API ne dit rien. Tu penses optimiser, tu factures normalement. Contrôle cache_read_input_tokens sur un vrai appel avant de conclure.
  • L'ordre décide de tout. Le cache_control est une frontière : avant, c'est caché ; après, non. Mets le stable en premier (system, docs, few-shots) et le volatil en dernier (question, historique récent). Un identifiant de session glissé en tête casse le préfixe à chaque appel.
  • Un token qui change = cache manqué. Le hit exige un préfixe identique au byte près. Une date injectée dans le system prompt, un timestamp, un ordre de clés JSON non déterministe : le cache saute et tu repaies l'écriture.
  • L'écriture coûte plus cher que l'input plein — 1,25× en TTL 5 min, 2× en TTL 1 h. Cacher un contexte utilisé une seule fois est une perte sèche. Le cache ne gagne que si le même préfixe est relu plusieurs fois dans la fenêtre.
  • Le TTL expire en silence. Il se rafraîchit à chaque hit, mais un trafic clairsemé — une requête tous les quarts d'heure — laisse le cache mourir entre deux appels, et tu repaies l'écriture à répétition. Trafic régulier, ou passe en TTL 1 h avec {"type": "ephemeral", "ttl": "1h"}.

Le batch pour tout ce qui n'est pas temps réel

Le caching couvre le contexte répété. Le batch couvre une autre moitié du travail : tout ce qui peut attendre. L'API Batch applique −50 % sur l'input ET l'output, en échange d'un traitement asynchrone (garanti sous 24 h, souvent bien plus rapide).

batch = client.messages.batches.create(
    requests=[
        {
            "custom_id": f"doc-{i}",
            "params": {
                "model": "claude-sonnet-5",
                "max_tokens": 1024,
                "messages": [{"role": "user", "content": f"Résume : {doc}"}],
            },
        }
        for i, doc in enumerate(documents)
    ]
)
Enter fullscreen mode Exit fullscreen mode

Tu ne batches pas un chatbot en direct, évidemment. Mais l'indexation nocturne, la génération d'embeddings de description, la classification d'un backlog de tickets, les rapports du matin : tout ça part en batch et coûte moitié prix. Et sur les jobs où le même préfixe revient, la remise batch et la remise cache se cumulent.

La facture avant/après, en clair

Un cas concret vaut mieux qu'un discours. Bot de support en RAG : 20 000 tokens de contexte réutilisé, 500 tokens de question, 800 tokens de réponse, 10 000 requêtes par mois.

Scénario Coût/mois
Août, sans cache (2 $/10 $) ~490 $
Septembre, sans cache (3 $/15 $) ~735 $
Septembre, avec cache ~195 $

La hausse brute te fait passer de 490 à 735 $, soit +245 $. Mais le contexte caché fait tomber la facture de septembre à 195 $ — moins que ce que tu payais en août au tarif de lancement. La bonne lecture n'est donc pas « l'API augmente de 50 % » : c'est « l'API punit ceux qui envoient 20 000 tokens en plein tarif à chaque appel ». Le +50 % existe. Il ne te concerne que si tu n'as rien optimisé.

Un dernier réflexe avant de migrer : re-mesure ta consommation réelle sur Sonnet 5 plutôt que de reprendre tes compteurs d'un modèle précédent. Le nombre de tokens facturés pour un même texte dépend du tokenizer du modèle, et il peut différer de ce que tu avais l'habitude de voir. Ta seule source fiable reste le champ usage renvoyé par l'API. Pas une estimation faite à la main.

Par où commencer lundi

Trois gestes, dans l'ordre. Instrumente d'abord : logue input_tokens, output_tokens, cache_creation_input_tokens et cache_read_input_tokens sur chaque appel, sinon tu optimises à l'aveugle. Isole ensuite ton plus gros préfixe stable et pose-y un cache_control. Bascule enfin en batch tout ce qui n'a pas besoin d'une réponse dans la seconde.

Si tu veux le détail de qui paie plus et qui ne paie rien (abonnés Pro/Max, utilisateurs restés sur Sonnet 4.6), on l'a posé à plat dans la fiche sur la hausse. Et si tu construis des apps où le coût IA doit tenir en production sans y penser tous les matins, c'est exactement ce qu'on apprend à cadrer dans la formation Claude Code.

Top comments (0)