The Context Constraint
Every LLM has a context window limit. Even with 128K or 1M token windows, context is precious.
What you put in the context window determines what the model can know and do. Wasted tokens are wasted capability. This guide covers strategies for maximizing the value of every token.
Understanding Context Windows
Context Window Sizes
| Model | Context Window | Effective Limit |
|---|
| GPT-4o | 128K | 100K recommended |
| Claude 3.5 | 200K | 150K recommended |
| Gemini 1.5 Pro | 1M | 500K recommended |
| Llama 3.1 | 128K | 80K recommended |
| GPT-3.5 | 16K | 12K recommended |
| Factor | Impact | Mitigation |
|---|
| Output tokens | Reserves space | Account in planning |
| Quality degradation | Lost in middle | Prioritize placement |
| Latency | Linear with length | Minimize when possible |
| Cost | Per-token billing | Optimize for value |
| Content Type | Tokens per 1K chars | Notes |
|---|
| English text | ~250 | Standard estimate |
| Code | ~350 | More special chars |
| JSON | ~400 | Structural overhead |
| Markdown | ~280 | Formatting chars |
Context Prioritization
The Context Hierarchy
| Priority | Content Type | Example |
|---|
| 1 - Critical | System prompt | Role, rules |
| 2 - Essential | User query | Current question |
| 3 - Important | Retrieved context | RAG documents |
| 4 - Helpful | Conversation history | Recent messages |
| 5 - Nice to have | Background info | Preferences |
Code
┌─────────────────────────────────────────────────────────────┐
│ CONTEXT WINDOW LAYOUT │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────────────────┐ │
│ │ SYSTEM PROMPT (High Attention Zone) │ │
│ │ Role, rules, critical instructions │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ CRITICAL CONTEXT │ │
│ │ Most relevant documents, key facts │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ MIDDLE ZONE (Lower Attention - "Lost in Middle") │ │
│ │ Supporting context, additional documents │ │
│ │ Less critical information │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ RECENT CONVERSATION (Recency Boost) │ │
│ │ Last few messages, recent context │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ USER QUERY (High Attention Zone) │ │
│ │ Current question - immediate focus │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐ │
│ OUTPUT SPACE (Reserved for generation) │
│ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ │
└─────────────────────────────────────────────────────────────┘
| Strategy | Description | Best For |
|---|
| Recency | Recent first | Conversations |
| Relevance | Most similar first | RAG |
| Importance | Pre-scored | Mixed content |
| Hybrid | Combine signals | Production |
| Signal | Weight | Calculation |
|---|
| Semantic similarity | 40% | Embedding distance |
| Recency | 25% | Time decay |
| Source quality | 20% | Pre-assigned score |
| User feedback | 15% | Historical rating |
Context Compression
| Technique | Compression | Quality Loss | Cost |
|---|
| Truncation | 50-90% | High | Free |
| Summarization | 60-80% | Low | LLM call |
| Extraction | 70-90% | Low | LLM call |
| Selective inclusion | 50-80% | Very low | Logic |
| Strategy | Use Case | Compression |
|---|
| Abstractive | Long documents | 80-90% |
| Extractive | Key points | 60-80% |
| Hierarchical | Multi-level | 90%+ |
| Incremental | Conversations | 70-80% |
| Scenario | Compression | Method |
|---|
| Long document | High | Summarize |
| Many short docs | Medium | Select top N |
| Conversation history | Progressive | Rolling summary |
| Structured data | Low | Schema optimization |
| Stage | Action | Tokens Saved |
|---|
| 1 | Remove duplicates | 10-30% |
| 2 | Strip formatting | 5-15% |
| 3 | Summarize old content | 40-60% |
| 4 | Extract key points | 20-40% |
| 5 | Final selection | Remaining |
Python
from typing import List, Tuple
from dataclasses import dataclass
import tiktoken
@dataclass
class ContextChunk:
content: str
source: str
relevance_score: float
timestamp: float
importance: float
class ContextManager:
def __init__(self, max_tokens: int = 32000, model: str = "gpt-4"):
self.max_tokens = max_tokens
self.encoder = tiktoken.encoding_for_model(model)
# Token budget allocation
self.budgets = {
"system_prompt": int(max_tokens * 0.05), # 5%
"retrieved_docs": int(max_tokens * 0.50), # 50%
"conversation": int(max_tokens * 0.25), # 25%
"output_reserve": int(max_tokens * 0.15), # 15%
"buffer": int(max_tokens * 0.05), # 5%
}
def count_tokens(self, text: str) -> int:
return len(self.encoder.encode(text))
def build_context(
self,
system_prompt: str,
retrieved_chunks: List[ContextChunk],
conversation_history: List[dict],
user_query: str
) -> str:
"""Build optimized context within token budget."""
context_parts = []
used_tokens = 0
# 1. System prompt (always include, truncate if needed)
system_tokens = self.count_tokens(system_prompt)
if system_tokens > self.budgets["system_prompt"]:
system_prompt = self._truncate_to_tokens(
system_prompt, self.budgets["system_prompt"]
)
context_parts.append(("system", system_prompt))
used_tokens += self.count_tokens(system_prompt)
# 2. Retrieved documents (prioritized by hybrid score)
retrieved_chunks = self._rank_chunks(retrieved_chunks, user_query)
doc_tokens = 0
for chunk in retrieved_chunks:
chunk_tokens = self.count_tokens(chunk.content)
if doc_tokens + chunk_tokens <= self.budgets["retrieved_docs"]:
context_parts.append(("document", chunk.content))
doc_tokens += chunk_tokens
used_tokens += doc_tokens
# 3. Conversation history (most recent first, summarize old)
conv_tokens = 0
recent_messages = []
for msg in reversed(conversation_history):
msg_tokens = self.count_tokens(str(msg))
if conv_tokens + msg_tokens <= self.budgets["conversation"]:
recent_messages.insert(0, msg)
conv_tokens += msg_tokens
else:
# Summarize remaining old messages
old_messages = conversation_history[:len(conversation_history) - len(recent_messages)]
if old_messages:
summary = self._summarize_conversation(old_messages)
context_parts.append(("history_summary", summary))
break
for msg in recent_messages:
context_parts.append(("message", str(msg)))
used_tokens += conv_tokens
# 4. User query (always at the end)
context_parts.append(("query", user_query))
used_tokens += self.count_tokens(user_query)
return self._assemble_context(context_parts)
def _rank_chunks(
self,
chunks: List[ContextChunk],
query: str
) -> List[ContextChunk]:
"""Hybrid ranking: relevance + recency + importance."""
def score(chunk: ContextChunk) -> float:
# Recency decay (halves every 24 hours)
age_hours = (time.time() - chunk.timestamp) / 3600
recency = 0.5 ** (age_hours / 24)
return (
0.50 * chunk.relevance_score +
0.25 * recency +
0.25 * chunk.importance
)
return sorted(chunks, key=score, reverse=True)
def _summarize_conversation(self, messages: List[dict]) -> str:
"""Use LLM to summarize old conversation."""
# In production, call LLM here
return f"[Summary of {len(messages)} earlier messages]"
Context Placement
| Position | Recall Rate | Recommendation |
|---|
| Beginning | 90%+ | Critical info |
| Middle | 60-70% | Less important |
| End | 85-90% | Recent/query |
| Position | Content | Why |
|---|
| First | System prompt | Sets behavior |
| Second | Critical context | High attention |
| Middle | Supporting docs | Lower priority |
| Near end | Recent history | Recency boost |
| Last | User query | Immediate focus |
| Chunk Size | Placement Strategy | Use Case |
|---|
| Small (256) | Distribute evenly | Many sources |
| Medium (512) | Top-weighted | Few key sources |
| Large (1024) | Single placement | One main doc |
RAG Context Optimization
| Parameter | Impact | Recommendation |
|---|
| Top K | More context | 3-10 depending on size |
| Similarity threshold | Quality filter | 0.7-0.85 |
| Diversity | Reduce redundancy | MMR or similar |
| Chunk overlap | Context continuity | 10-20% |
| Stage | Action | Improvement |
|---|
| Initial retrieval | Vector search | Baseline |
| Rerank | Cross-encoder | +10-20% relevance |
| Filter | Remove low scores | -30% tokens |
| Dedupe | Remove similar | -10-20% tokens |
Context Window Budget
| Component | Allocation | Tokens (32K window) |
|---|
| System prompt | 5% | 1,600 |
| Retrieved docs | 50% | 16,000 |
| Conversation | 25% | 8,000 |
| Output reserve | 15% | 4,800 |
| Buffer | 5% | 1,600 |
History Strategies
| Strategy | Memory | Quality | Complexity |
|---|
| Full history | All | Best | Simple |
| Sliding window | Last N | Good | Simple |
| Summarization | Compressed | Good | Medium |
| Hybrid | Recent + summary | Best | Complex |
| Window Size | Use Case | Trade-off |
|---|
| 5 messages | Quick tasks | May lose context |
| 10 messages | Standard chat | Balanced |
| 20 messages | Complex tasks | More tokens |
| Unlimited | Short sessions | Budget dependent |
| Trigger | Action | Content |
|---|
| N messages | Summarize oldest | Key points |
| Token threshold | Compress history | Decisions, facts |
| Topic change | Summarize topic | Topic summary |
| Element | Priority | Reason |
|---|
| User preferences stated | High | Personalization |
| Decisions made | High | Consistency |
| Facts established | Medium | Accuracy |
| Clarifications | Medium | Understanding |
| Chit-chat | Low | Usually unneeded |
| Technique | Savings | Example |
|---|
| Short keys | 20-40% | "name" vs "customer_name" |
| Remove nulls | 10-20% | Omit null fields |
| Compact format | 15-25% | No whitespace |
| Schema reference | 30-50% | Define once, reference |
Table to Text
| Format | Tokens | Readability |
|---|
| Full table | Baseline | Good |
| Key-value pairs | -20% | Good |
| Prose summary | -40% | Medium |
| Schema + data | -30% | Good |
| Strategy | Description | When |
|---|
| Column selection | Only relevant columns | Wide tables |
| Row sampling | Representative rows | Long tables |
| Aggregation | Summarize numbers | Analytics |
| Filtering | Only matching rows | Conditional |
| Content | Cache Duration | Invalidation |
|---|
| System prompts | Long | On change |
| Static context | Long | On update |
| Embeddings | Long | On content change |
| Summaries | Medium | On source change |
| Retrieval results | Short | Per session |
| Strategy | Hit Rate | Implementation |
|---|
| Query normalization | +15% | Lowercase, trim |
| Semantic matching | +25% | Embedding similarity |
| Prefix caching | +20% | Provider feature |
| Template caching | +30% | Reuse structure |
| Provider | Feature | Savings |
|---|
| OpenAI | Automatic | 50% on repeated prefix |
| Anthropic | Prompt caching | 90% on cached |
| Google | Context caching | Variable |
Measuring Context Efficiency
| Metric | Description | Target |
|---|
| Token efficiency | Useful tokens / total | Over 80% |
| Relevance score | Context relevance | Over 0.8 |
| Retrieval recall | Found relevant | Over 90% |
| Compression ratio | Original / compressed | 3-5x |
| Test | Compare | Metric |
|---|
| Chunk size | 256 vs 512 vs 1024 | Answer quality |
| Top K | 3 vs 5 vs 10 | Relevance, cost |
| Compression | None vs summarized | Quality, latency |
| Placement | Order variations | Recall accuracy |
Debugging Context Issues
| Issue | Symptom | Investigation |
|---|
| Missing info | Wrong answer | Check retrieval |
| Contradictions | Inconsistent | Check duplicates |
| Ignored context | Not using docs | Check placement |
| Hallucination | Made up facts | Check relevance |
- 1Context is precious - Every token should earn its place. Ruthlessly prioritize.
- 2Placement matters - Critical information goes at the beginning and end. Middle gets forgotten.
- 3Compress strategically - Summarization preserves meaning while saving tokens.
- 4Budget your window - Allocate tokens intentionally across system prompt, context, history, and output.
- 5Cache aggressively - Repeated context should be cached, not recomputed.
- 6Measure and iterate - A/B test context strategies. Small improvements compound.
The context window is your AI's working memory. Use it wisely, and your applications will be more accurate, faster, and cheaper.