Zum Inhalt springen
EN DE

Challenge 2.4: Prompt Caching

Wenn Du denselben System Prompt bei jedem Request schickst — zahlt der Provider jedes Mal neu dafuer?

Vergleich: erster Request ohne Cache zum vollen Preis, zweiter Request mit Cache-Hit 90% guenstiger

Beim ersten Request wird der System Prompt normal berechnet und im Cache gespeichert. Ab dem zweiten Request erkennt der Provider das identische Prefix und liest es aus dem Cache — zu einem Bruchteil der Kosten.

Ohne Prompt Caching: Du schickst denselben 2.000-Token System Prompt bei jedem Request. Bei 100 Requests pro Stunde zahlst Du 100x den vollen Preis für identischen Text. Das summiert sich schnell.

Mit Prompt Caching: Der System Prompt wird einmal berechnet, dann aus dem Cache gelesen. Bei Anthropic kostet ein Cache-Read nur 10% des normalen Input-Preises. Bei 100 Requests sparst Du 90% der System-Prompt-Kosten.

Prompt Caching basiert auf Prefix Matching. Der Provider vergleicht den Anfang Deines Requests mit vorherigen Requests:

Request 1: [System Prompt] + [User: "Was ist TypeScript?"]
^^^^^^^^^^^^^^^^
Wird gecacht (= Prefix)
Request 2: [System Prompt] + [User: "Erklaere Promises."]
^^^^^^^^^^^^^^^^
Cache Hit! Nur User-Prompt wird neu berechnet.
Request 3: [Anderer System Prompt] + [User: "Was ist TypeScript?"]
^^^^^^^^^^^^^^^^^^^^^^^^
Cache Miss — Prefix hat sich geaendert.

Wichtig: Der Cache funktioniert nur für den Anfang (Prefix) des Requests. Sobald sich auch nur ein Zeichen im System Prompt ändert, ist der gesamte Cache ungueltig. Deshalb: System Prompt stabil halten, dynamische Teile ans Ende.

Nicht alle Provider unterstuetzen Prompt Caching:

ProviderCachingMin. Prefix-LaengeCache-DauerCache-Read-Rabatt
AnthropicJa1.024 Tokens (Sonnet), 2.048 (Haiku) (Stand: Maerz 2026)5 Minuten (TTL — Time To Live, danach verfaellt der Cache)90% guenstiger
Google (Gemini)Javariabelvariabelvariabel
OpenAIAutomatisch1.024 Tokens (Stand: Maerz 2026)bis zu 1 Stunde50% guenstiger

Anthropic hat eine Mindestlaenge für den Cache-Prefix. Kurze System Prompts unter 1.024 Tokens werden nicht gecacht. Das ist ein bewusster Tradeoff — der Overhead für das Caching lohnt sich nur bei laengeren Prefixes.

Das AI SDK gibt Dir Cache-Informationen im usage-Objekt zurück:

import { generateText } from 'ai';
import { anthropic } from '@ai-sdk/anthropic';
// Ein langer System Prompt (>1024 Tokens für Cache-Eligibility)
const longSystemPrompt = `
Du bist ein erfahrener Code-Review-Assistent.
<rules>
- Pruefe jeden Code auf: Sicherheit, Performance, Lesbarkeit, Best Practices
- Kategorisiere Findings als: KRITISCH, WARNUNG, HINWEIS
- Gib für jedes Finding: Zeile, Problem, Lösung an
- Nutze die OWASP Top 10 als Sicherheits-Referenz
- Beachte TypeScript-spezifische Patterns und Anti-Patterns
- Pruefe auf proper Error Handling und Edge Cases
</rules>
<output-format>
## Review: [Dateiname]
### KRITISCH
- **Zeile X:** [Problem] → [Lösung]
### WARNUNG
- **Zeile X:** [Problem] → [Lösung]
### HINWEIS
- **Zeile X:** [Problem] → [Lösung]
### Zusammenfassung
[1-2 Saetze Gesamtbewertung]
</output-format>
`.trim();
// Dieser System Prompt hat ca. 150 Woerter ≈ 200-250 Tokens (unter dem 1024-Token-Minimum für Caching).
// Für die Demonstration der Mechanik reicht das — für echtes Caching muss der Prompt laenger sein (siehe TRY-Aufgabe).
// Erster Request — Cache wird erstellt
const result1 = await generateText({
model: anthropic('claude-sonnet-4-5-20250514'),
system: longSystemPrompt,
prompt: 'Review: const x = eval(userInput);',
});
console.log('--- Request 1 (Cache Creation) ---');
console.log('Prompt Tokens:', result1.usage.promptTokens);
console.log('Completion Tokens:', result1.usage.completionTokens);
// Zweiter Request — selber System Prompt, Cache Hit erwartet
const result2 = await generateText({
model: anthropic('claude-sonnet-4-5-20250514'),
system: longSystemPrompt, // ← Identisch!
prompt: 'Review: app.get("/api", (req, res) => res.send(db.query(req.body.sql)));',
});
console.log('\n--- Request 2 (Cache Hit erwartet) ---');
console.log('Prompt Tokens:', result2.usage.promptTokens);
console.log('Completion Tokens:', result2.usage.completionTokens);

Beim zweiten Request solltest Du niedrigere effektive Kosten sehen, weil der System Prompt aus dem Cache gelesen wird.

Um den Cache-Hit tatsaechlich zu verifizieren, lies die Cache-Metriken aus providerMetadata aus:

// Cache-Metriken aus providerMetadata auslesen (Anthropic-spezifisch)
const cacheMetrics = result2.providerMetadata?.anthropic;
console.log('Cache Creation Tokens:', cacheMetrics?.cacheCreationInputTokens ?? 0);
console.log('Cache Read Tokens:', cacheMetrics?.cacheReadInputTokens ?? 0);
// Beim zweiten Request: cacheReadInputTokens > 0 = Cache Hit!

Die Preisstruktur mit Caching bei Anthropic:

Preise Stand: Maerz 2026. Aktuelle Preise auf den Anbieterseiten pruefen.

Token-TypPreis (Claude Sonnet 4)Verhaeltnis
Normal Input$3.00 / 1M100%
Cache Write$3.75 / 1M125% (einmalig teurer)
Cache Read$0.30 / 1M10% (90% guenstiger!)
Output$15.00 / 1M

Der erste Request (Cache Write) ist sogar etwas teurer als normal. Aber ab dem zweiten Request sparst Du 90%. Die Break-Even-Rechnung (ab wann sich Caching lohnt):

// Beispiel: 2000-Token System Prompt, Claude Sonnet
const systemTokens = 2000;
const normalCostPerCall = (systemTokens / 1_000_000) * 3.00; // $0.006
const cacheWriteCost = (systemTokens / 1_000_000) * 3.75; // $0.0075 (einmalig)
const cacheReadCost = (systemTokens / 1_000_000) * 0.30; // $0.0006 pro Folge-Call
// Ohne Cache: 10 Calls = 10 × $0.006 = $0.060
const withoutCache = normalCostPerCall * 10;
// Mit Cache: 1 Write + 9 Reads = $0.0075 + 9 × $0.0006 = $0.0129
const withCache = cacheWriteCost + (cacheReadCost * 9);
console.log(`Ohne Cache (10 Calls): $${withoutCache.toFixed(4)}`);
console.log(`Mit Cache (10 Calls): $${withCache.toFixed(4)}`);
console.log(`Ersparnis: ${((1 - withCache / withoutCache) * 100).toFixed(0)}%`);
// → Ersparnis: 79%

Ab 2 Requests mit demselben Prefix lohnt sich Caching. Je mehr Requests, desto größer die Ersparnis — asymptotisch gegen 90%.

Aufgabe: Mache zwei Calls mit demselben langen System Prompt und vergleiche die Usage Details.

Erstelle eine Datei challenge-2-4.ts:

import { generateText } from 'ai';
import { anthropic } from '@ai-sdk/anthropic';
// TODO 1: Erstelle einen langen System Prompt (>1024 Tokens)
// Tipp: Ein detailliertes Regelwerk mit XML Tags, Beispielen und Output-Format
// const systemPrompt = `...`;
// TODO 2: Erster Call — Cache wird erstellt
// const result1 = await generateText({
// model: anthropic('claude-sonnet-4-5-20250514'),
// system: systemPrompt,
// prompt: 'Erste Frage...',
// });
// TODO 3: Zweiter Call — gleicher System Prompt, andere Frage
// const result2 = await generateText({
// model: anthropic('claude-sonnet-4-5-20250514'),
// system: systemPrompt,
// prompt: 'Zweite Frage...',
// });
// TODO 4: Vergleiche die Usage
// console.log('--- Request 1 ---');
// console.log('Prompt Tokens:', result1.usage.promptTokens);
// console.log('Completion Tokens:', result1.usage.completionTokens);
// console.log('--- Request 2 ---');
// console.log('Prompt Tokens:', result2.usage.promptTokens);
// console.log('Completion Tokens:', result2.usage.completionTokens);

Checkliste:

  • System Prompt ist lang genug für Caching (>1024 Tokens)
  • Zwei Calls mit identischem System Prompt
  • Usage-Vergleich geloggt
  • Unterschied zwischen erstem und zweitem Call beobachtet
Lösung anzeigen
import { generateText } from 'ai';
import { anthropic } from '@ai-sdk/anthropic';
const systemPrompt = `
<task-context>
Du bist ein erfahrener Software-Architekt mit 15 Jahren Erfahrung in TypeScript,
Node.js und Cloud-Architekturen. Du reviewst Code und Architekturen für
Enterprise-Anwendungen.
</task-context>
<rules>
- Pruefe jeden Code auf: Sicherheit, Performance, Lesbarkeit, Wartbarkeit
- Kategorisiere Findings als: KRITISCH, WARNUNG, HINWEIS, POSITIV
- Gib für jedes Finding an: Betroffene Stelle, Problem, Empfohlene Lösung
- Nutze die OWASP Top 10 als Sicherheits-Referenz
- Beachte TypeScript-spezifische Patterns: strict mode, type safety, generics
- Pruefe auf Error Handling, Edge Cases und Race Conditions
- Bewerte die Testbarkeit des Codes
- Achte auf SOLID-Prinzipien und Clean Architecture
- Pruefe Dependencies auf bekannte Vulnerabilities
- Bewerte die API-Design-Qualität (REST Best Practices)
- Achte auf proper Logging und Monitoring-Hooks
- Pruefe auf Memory Leaks und Resource Cleanup
</rules>
<examples>
Beispiel für ein KRITISCH-Finding:
- Stelle: Zeile 42, db.query()
- Problem: SQL Injection durch String-Concatenation
- Lösung: Parametrisierte Query verwenden
Beispiel für ein WARNUNG-Finding:
- Stelle: Zeile 15, catch(e) {}
- Problem: Leerer Catch-Block verschluckt Fehler
- Lösung: Error loggen und ggf. re-throwen
Beispiel für ein POSITIV-Finding:
- Stelle: Zeile 8, zod.parse()
- Problem: -
- Lösung: Gute Input-Validierung mit Zod
</examples>
<output-format>
## Code Review: [Kontext]
### KRITISCH
- **[Stelle]:** [Problem] → [Lösung]
### WARNUNG
- **[Stelle]:** [Problem] → [Lösung]
### HINWEIS
- **[Stelle]:** [Problem] → [Lösung]
### POSITIV
- **[Stelle]:** [Was gut ist]
### Zusammenfassung
[2-3 Saetze Gesamtbewertung mit Prioritaeten]
</output-format>
`.trim();
// Request 1 — Cache Creation
const result1 = await generateText({
model: anthropic('claude-sonnet-4-5-20250514'),
system: systemPrompt,
prompt: 'Review: const secret = "sk-1234"; app.post("/login", (req, res) => { if (req.body.pw === secret) res.json({token: jwt.sign({}, secret)}); });',
});
console.log('--- Request 1 (Cache Creation) ---');
console.log('Prompt Tokens:', result1.usage.promptTokens);
console.log('Completion Tokens:', result1.usage.completionTokens);
console.log('Total:', result1.usage.totalTokens);
// Request 2 — Cache Hit erwartet
const result2 = await generateText({
model: anthropic('claude-sonnet-4-5-20250514'),
system: systemPrompt,
prompt: 'Review: app.get("/users/:id", async (req, res) => { const user = await User.findById(req.params.id); res.json(user); });',
});
console.log('\n--- Request 2 (Cache Hit erwartet) ---');
console.log('Prompt Tokens:', result2.usage.promptTokens);
console.log('Completion Tokens:', result2.usage.completionTokens);
console.log('Total:', result2.usage.totalTokens);

Ausfuehren mit:

Terminal-Fenster
npx tsx challenge-2-4.ts

Erwarteter Output (ungefaehr):

--- Request 1 (Cache Creation) ---
Prompt Tokens: 380
Completion Tokens: 195
Total: 575
--- Request 2 (Cache Hit erwartet) ---
Prompt Tokens: 375
Completion Tokens: 180
Total: 555

Die promptTokens-Zahlen sind aehnlich, weil die Tokens trotzdem gezaehlt werden. Den Cache-Hit erkennst Du an den erweiterten Usage-Feldern: Pruefe providerMetadata für cacheReadTokens > 0 beim zweiten Call.

Erklärung: Beide Requests nutzen denselben System Prompt. Beim zweiten Request liest der Provider den System Prompt aus dem Cache. Die effektiven Kosten sind niedriger, auch wenn die Token-Zahlen aehnlich aussehen.

System Prompt (cached) und User Prompt fliessen in generateText, result.usage zu calculateCost, dann Cache-Aware Kostenberechnung

Uebung: Erweitere den Cost Calculator aus Challenge 2.2 um Cache-Awareness.

  1. Fuehre mehrere Calls mit demselben System Prompt aus
  2. Tracke, ob der erste Call teurer ist als Folge-Calls (Cache Write vs. Cache Read)
  3. Berechne die theoretische Ersparnis gegenueber “kein Caching”
  4. Logge nach jedem Call: “Call N: $X.XXXXXX (Cache: Hit/Miss)”

Optional Stretch Goal: Berechne die Break-Even-Analyse: Ab wie vielen Requests mit demselben Prefix lohnt sich Caching gegenueber keinem Caching? Zeige die Berechnung in der Konsole.

Part of AI Learning — free courses from prompt to production. Jan on LinkedIn