
How Smart Context Engineering Can Cut Your AI Costs by 90%
If you're using AI APIs like ChatGPT, Claude, or Gemini for your business, you're probably wondering: "How can I make this faster and cheaper?"
The answer lies in something called KV-caching - a technique that can dramatically reduce both response times and costs. Think of it like this: instead of the AI reading your entire conversation from scratch every time, it remembers and reuses parts it's already processed.
In this article, I'll show you exactly how changing the way you structure your context can save you thousands of dollars and make your AI applications lightning fast.
Why This Matters: The $10,000 Mistake
Here's what most people don't know: AI models have a "memory" feature called KV-caching. When you send a prompt, the AI doesn't just throw it away after responding - it can remember and reuse parts of it.
Think of it like this: Imagine you're asking a librarian questions. Would you rather:
- Option A: Start every question with "Hi, I'm John, I'm researching medieval history, here are the rules you should follow..." (wasteful)
- Option B: Say that introduction once, then just ask your specific questions (efficient)
Most AI applications accidentally choose Option A, wasting both time and money.
The cost difference is huge: Some AI providers charge 10x less for "cached" text compared to "fresh" text. If you're spending $1000/month on AI, poor caching could mean you're wasting $900.
The Costly Mistakes Most People Make
Here are the three biggest mistakes that destroy your caching efficiency:
Mistake #1: Changing Your Instructions Every Time
Many people include timestamps or random IDs in their system instructions:
// ❌ BAD: Changes every second, breaks cache
function generatePrompt() {
const timestamp = new Date().toISOString();
const sessionId = Math.random().toString(36);
return `You are a helpful assistant.
Current time: ${timestamp}
Session ID: ${sessionId}
Guidelines: Be helpful and professional.`;
}
Problem: Since this changes every second, the AI can never reuse any previous work. It's like reintroducing yourself to the librarian every single time.
Mistake #2: Constantly Updating Old Messages
Some systems go back and modify previous conversation messages, adding timestamps or updating metadata.
// ❌ BAD: Modifying old messages breaks cache
conversationHistory.forEach((message) => {
message.timestamp = Date.now(); // Updates ALL previous messages!
message.updated = true;
});
Problem: This breaks the AI's ability to remember the conversation efficiently. It's like asking the librarian to forget everything and restart.
Mistake #3: Using Random Data Unnecessarily
Adding random session IDs, weather information, or other changing data when the AI doesn't actually need it.
Problem: Every random element forces the AI to process everything from scratch.
The Solution: Three Simple Rules
Here's how to fix your prompts for maximum cache efficiency:
Rule #1: Keep Your Core Instructions Static
Create a "base prompt" that never changes:
// ✅ GOOD: Static prompt that gets cached
function getSystemPrompt() {
return `You are a helpful customer service assistant.
Always be professional and escalate complex issues to humans.
Remember the conversation context.
--- CONVERSATION START ---`;
}
Why this works: The AI can remember and reuse this part for every conversation.
Rule #2: Put Dynamic Information AFTER Static Parts
If you need timestamps or session info, put them after your stable instructions:
// ✅ GOOD: Structure context for maximum cache reuse
async function buildContext(userMessage) {
const stablePrompt = getSystemPrompt(); // This gets cached!
// Dynamic info comes after (not cached, but available to AI)
const dynamicInfo = `
SESSION INFO:
- Current time: ${new Date().toLocaleString()}
- User: ${userMessage}`;
return stablePrompt + dynamicInfo;
}
Rule #3: Never Modify Old Messages
Always add new messages to the end. Never go back and change previous parts of the conversation.
// ✅ GOOD: Append-only approach
function addMessage(conversation, role, content) {
// Just add to the end - never modify existing messages
conversation.push({
role: role,
content: content,
index: conversation.length,
});
return conversation;
}
// ❌ BAD: Don't do this
function updateAllMessages(conversation) {
conversation.forEach((msg) => {
msg.timestamp = Date.now(); // Breaks cache!
});
}
Think of it like a diary: You add new entries, but you don't go back and edit old ones.
What If I Really Need Dynamic Information?
You might be thinking: "But I need timestamps and session IDs for my business logic!"
The solution is smart placement. Here's a complete example:
// ✅ COMPLETE EXAMPLE: Cache-optimised chatbot
class optimisedChatbot {
constructor() {
this.conversation = [];
}
// Static part - gets cached
getSystemPrompt() {
return `You are a helpful customer service assistant.
Always be professional and helpful.
Escalate complex issues to human agents.
--- CONVERSATION START ---`;
}
async chat(userMessage, sessionId = null) {
// 1. Stable prefix (cached)
const systemPrompt = this.getSystemPrompt();
// 2. Dynamic info (not cached, but after stable part)
const sessionInfo = sessionId ? `\nSession: ${sessionId}` : "";
// 3. Add user message (append-only)
this.conversation.push({
role: "user",
content: userMessage,
});
// 4. Build final context
const conversationText = this.conversation
.map((msg) => `${msg.role}: ${msg.content}`)
.join("\n");
const fullContext = systemPrompt + sessionInfo + "\n" + conversationText;
// Send to AI and add response
const response = await callAI(fullContext);
this.conversation.push({
role: "assistant",
content: response,
});
return response;
}
}
This way:
- The AI caches your core instructions (the expensive part)
- You still get your dynamic data when the AI actually needs it
- You save money on the parts that can be reused
The Tradeoff: Performance vs Features
Here's the honest truth: adding changing information like timestamps reduces cache benefits. But you have choices:
Option 1: Maximum Savings (No Dynamic Data)
What it is: Keep your instructions completely static Performance: 🟢 Excellent (60-70% faster) Best for: When the AI doesn't need to know current time or session details
Option 2: Balanced Approach (Smart Updates)
What it is: Update dynamic info every minute or hour, not every second Performance: 🟡 Good (40-50% faster) Best for: When you need some context but can update less frequently
Option 3: Full Features (Accept Performance Cost)
What it is: Include all dynamic data you need Performance: 🔴 Lower (but still 15-25% better than doing it wrong) Best for: When the AI needs real-time context
The Real Numbers: What You'll Save
Here's what these optimisations actually mean for your AI costs:
Speed Improvements
Approach | Response Time | vs Worst Case |
---|---|---|
🟢 Maximum Cache | 3.2 seconds | 61% faster |
🟡 Smart Updates | 4.2 seconds | 51% faster |
🔴 Full Dynamic | 6.9 seconds | 18% faster |
💀 Wrong Way | 8.5 seconds | baseline |
Your Action Plan: Three Simple Steps
Here's exactly what to do to optimise your AI costs:
Step 1: Create Static Instructions
What to do: Write your AI instructions once and never change them. Avoid: Adding timestamps, random IDs, or changing information to your core prompt. Example: Instead of "Current time: 2:34 PM, Session: abc123", just use "You are a helpful assistant."
Step 2: Add New Messages, Don't Edit Old Ones
What to do: Always add new conversation messages to the end. Avoid: Going back and changing previous messages or reordering them. Think: Like texting - you send new messages, you don't edit sent ones.
Step 3: Be Consistent
What to do: If you need to include data (like user preferences), always format it the same way. Avoid: Random ordering or changing how you structure information. Example: Always put user info in the same order: name, then email, then preferences.
Quick Example: Before vs After
❌ Before (Cache-Breaking)
You are a helpful assistant.
Current time: 2024-01-15 14:32:47
Session: abc123xyz
Weather: sunny
User: John wants help with his order
Every request has different timestamps and session IDs, so nothing gets cached.
✅ After (Cache-Friendly)
You are a helpful assistant for customer service.
Always be professional and helpful.
---
User: John wants help with his order
The core instructions stay the same, so they get cached and reused.
Pro Tips for Maximum Savings
Monitor Your Results
Track your AI costs: Most AI providers show you token usage in their dashboards. Watch for sudden increases that might indicate cache issues.
Design for Efficiency from Day One
Plan ahead: When building new AI features, think about caching from the start rather than fixing it later.
Stay Consistent
Use the same format: Whether it's user data, timestamps, or any other information, always structure it the same way across your entire application.
The Bottom Line
Smart context engineering isn't just a nice optimisation trick, it's essential if you want to use AI cost-effectively for your business.
What you can achieve:
- Cut AI costs by up to 90%
- Make your AI respond 50% faster
- Handle more users without higher costs
The secret is simple: make the AI reuse work instead of starting from scratch every time.
Remember: The best optimisation is making the AI do less work while getting the same results. That's exactly what KV-cache optimisation does, it's working smarter, not harder.
Ready to optimise your AI costs and unlock serious savings? Partner with AvestaLabs to implement smart context engineering strategies that reduce costs while improving performance.
Questions? Reach out to us at hello@avestalabs.ai

Seasoned software engineer and AI strategist with over 13 years of experience. I specialize in building high-performance, secure cloud-native systems and crafting AI solutions that deliver real business value.