Context Window Optimization: Getting More from Limited Tokens
Back to all articles
AI Engineering
18 min read12 min read

Context Window Optimization: Getting More from Limited Tokens

Maximizing the value of every token. Strategies for context selection, compression, prioritization, and efficient use of LLM context windows.

Debasish Maji
Debasish Maji
AI Engineering Lead
May 8, 2026
ContextTokensOptimizationRAGPerformance

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

ModelContext WindowEffective Limit
GPT-4o128K100K recommended
Claude 3.5200K150K recommended
Gemini 1.5 Pro1M500K recommended
Llama 3.1128K80K recommended
GPT-3.516K12K recommended

Why Effective Limits Differ

FactorImpactMitigation
Output tokensReserves spaceAccount in planning
Quality degradationLost in middlePrioritize placement
LatencyLinear with lengthMinimize when possible
CostPer-token billingOptimize for value

Token Counting

Content TypeTokens per 1K charsNotes
English text~250Standard estimate
Code~350More special chars
JSON~400Structural overhead
Markdown~280Formatting chars
•••

Context Prioritization

The Context Hierarchy

PriorityContent TypeExample
1 - CriticalSystem promptRole, rules
2 - EssentialUser queryCurrent question
3 - ImportantRetrieved contextRAG documents
4 - HelpfulConversation historyRecent messages
5 - Nice to haveBackground infoPreferences
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)                   │
│  └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘   │
└─────────────────────────────────────────────────────────────┘

Prioritization Strategies

StrategyDescriptionBest For
RecencyRecent firstConversations
RelevanceMost similar firstRAG
ImportancePre-scoredMixed content
HybridCombine signalsProduction

Relevance Scoring

SignalWeightCalculation
Semantic similarity40%Embedding distance
Recency25%Time decay
Source quality20%Pre-assigned score
User feedback15%Historical rating
•••

Context Compression

Compression Techniques

TechniqueCompressionQuality LossCost
Truncation50-90%HighFree
Summarization60-80%LowLLM call
Extraction70-90%LowLLM call
Selective inclusion50-80%Very lowLogic

Summarization Strategies

StrategyUse CaseCompression
AbstractiveLong documents80-90%
ExtractiveKey points60-80%
HierarchicalMulti-level90%+
IncrementalConversations70-80%

When to Compress

ScenarioCompressionMethod
Long documentHighSummarize
Many short docsMediumSelect top N
Conversation historyProgressiveRolling summary
Structured dataLowSchema optimization

Compression Pipeline

StageActionTokens Saved
1Remove duplicates10-30%
2Strip formatting5-15%
3Summarize old content40-60%
4Extract key points20-40%
5Final selectionRemaining
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

The Lost in the Middle Problem

PositionRecall RateRecommendation
Beginning90%+Critical info
Middle60-70%Less important
End85-90%Recent/query

Optimal Layout

PositionContentWhy
FirstSystem promptSets behavior
SecondCritical contextHigh attention
MiddleSupporting docsLower priority
Near endRecent historyRecency boost
LastUser queryImmediate focus

Chunking for Placement

Chunk SizePlacement StrategyUse Case
Small (256)Distribute evenlyMany sources
Medium (512)Top-weightedFew key sources
Large (1024)Single placementOne main doc
•••

RAG Context Optimization

Retrieval Tuning

ParameterImpactRecommendation
Top KMore context3-10 depending on size
Similarity thresholdQuality filter0.7-0.85
DiversityReduce redundancyMMR or similar
Chunk overlapContext continuity10-20%

Reranking

StageActionImprovement
Initial retrievalVector searchBaseline
RerankCross-encoder+10-20% relevance
FilterRemove low scores-30% tokens
DedupeRemove similar-10-20% tokens

Context Window Budget

ComponentAllocationTokens (32K window)
System prompt5%1,600
Retrieved docs50%16,000
Conversation25%8,000
Output reserve15%4,800
Buffer5%1,600
•••

Conversation Management

History Strategies

StrategyMemoryQualityComplexity
Full historyAllBestSimple
Sliding windowLast NGoodSimple
SummarizationCompressedGoodMedium
HybridRecent + summaryBestComplex

Sliding Window Design

Window SizeUse CaseTrade-off
5 messagesQuick tasksMay lose context
10 messagesStandard chatBalanced
20 messagesComplex tasksMore tokens
UnlimitedShort sessionsBudget dependent

Rolling Summarization

TriggerActionContent
N messagesSummarize oldestKey points
Token thresholdCompress historyDecisions, facts
Topic changeSummarize topicTopic summary

What to Preserve

ElementPriorityReason
User preferences statedHighPersonalization
Decisions madeHighConsistency
Facts establishedMediumAccuracy
ClarificationsMediumUnderstanding
Chit-chatLowUsually unneeded
•••

Structured Data Optimization

JSON Optimization

TechniqueSavingsExample
Short keys20-40%"name" vs "customer_name"
Remove nulls10-20%Omit null fields
Compact format15-25%No whitespace
Schema reference30-50%Define once, reference

Table to Text

FormatTokensReadability
Full tableBaselineGood
Key-value pairs-20%Good
Prose summary-40%Medium
Schema + data-30%Good

Data Selection

StrategyDescriptionWhen
Column selectionOnly relevant columnsWide tables
Row samplingRepresentative rowsLong tables
AggregationSummarize numbersAnalytics
FilteringOnly matching rowsConditional
•••

Caching Strategies

What to Cache

ContentCache DurationInvalidation
System promptsLongOn change
Static contextLongOn update
EmbeddingsLongOn content change
SummariesMediumOn source change
Retrieval resultsShortPer session

Cache Hit Optimization

StrategyHit RateImplementation
Query normalization+15%Lowercase, trim
Semantic matching+25%Embedding similarity
Prefix caching+20%Provider feature
Template caching+30%Reuse structure

Provider Prefix Caching

ProviderFeatureSavings
OpenAIAutomatic50% on repeated prefix
AnthropicPrompt caching90% on cached
GoogleContext cachingVariable
•••

Measuring Context Efficiency

Metrics

MetricDescriptionTarget
Token efficiencyUseful tokens / totalOver 80%
Relevance scoreContext relevanceOver 0.8
Retrieval recallFound relevantOver 90%
Compression ratioOriginal / compressed3-5x

A/B Testing

TestCompareMetric
Chunk size256 vs 512 vs 1024Answer quality
Top K3 vs 5 vs 10Relevance, cost
CompressionNone vs summarizedQuality, latency
PlacementOrder variationsRecall accuracy

Debugging Context Issues

IssueSymptomInvestigation
Missing infoWrong answerCheck retrieval
ContradictionsInconsistentCheck duplicates
Ignored contextNot using docsCheck placement
HallucinationMade up factsCheck relevance
•••

Key Takeaways

  1. 1Context is precious - Every token should earn its place. Ruthlessly prioritize.
  1. 2Placement matters - Critical information goes at the beginning and end. Middle gets forgotten.
  1. 3Compress strategically - Summarization preserves meaning while saving tokens.
  1. 4Budget your window - Allocate tokens intentionally across system prompt, context, history, and output.
  1. 5Cache aggressively - Repeated context should be cached, not recomputed.
  1. 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.

Found this helpful?

Share it with others who might benefit

TweetShare

Related articles