When to Use GPT-5.4 Reasoning Effort: Low, Medium, High, XHigh?
I defaulted to high reasoning effort for everything. Seemed like the safe choice—more thinking should mean better results, right? After burning through my API budget faster than expected, I dug into the documentation and community discussions. Turns out, higher reasoning effort doesn’t automatically mean better outputs. Sometimes it means worse results at higher cost.
What Reasoning Effort Actually Does
GPT-5.4 models expose a reasoning_effort parameter with five levels: none, low, medium, high, and xhigh. This controls how much computational budget the model spends “thinking” before responding.
Here’s what caught me off guard: reasoning tokens count toward your output token billing. There’s no separate surcharge—higher effort simply generates more tokens. A high effort request might produce 2x more tokens than low for the same task, and you pay for all of them.
none -> Baseline token usage, fastest responselow -> +10-20% tokens, small reliability improvementmedium -> +30-50% tokens, standard complex taskshigh -> +50-100% tokens, planning/coding/synthesisxhigh -> +100%+ tokens, only when evals justify itThe Problem With Defaulting to High
I used high for everything because I thought it would give me the best results. What I actually got:
- Higher costs — More tokens generated means higher bills
- Slower responses — The model spends more time reasoning
- Inconsistent quality — Sometimes worse than lower effort levels
A Reddit comment captured this perfectly: “High should not be your default.” The newer GPT-5 models actually default to none because that’s often sufficient.
When Each Level Makes Sense
I’ve learned to match effort to task complexity:
none/low: - Simple factual queries - Quick summaries - Straightforward translations
medium: - Analysis tasks - Multi-step reasoning - Standard coding problems
high: - Architecture design - Complex synthesis - Planning tasks
xhigh: - Only when evaluation proves it's needed - Exceptionally difficult problems - When cost doesn't matterPython SDK Configuration Examples
Here’s how I configure reasoning effort based on task type:
from openai import OpenAI
client = OpenAI()
# Low effort - Quick reliability bumpresponse = client.chat.completions.create( model="gpt-5.4-mini", messages=[ {"role": "user", "content": "Summarize this article: [text]"} ], reasoning_effort="low")
# Medium effort - Standard complex tasksresponse = client.chat.completions.create( model="gpt-5.4-mini", messages=[ {"role": "user", "content": "Analyze the pros and cons of microservices"} ], reasoning_effort="medium")
# High effort - Planning, coding, synthesisresponse = client.chat.completions.create( model="gpt-5.4", messages=[ {"role": "user", "content": "Design a scalable architecture for a real-time chat system"} ], reasoning_effort="high")
# XHigh effort - Only when justified by evalsresponse = client.chat.completions.create( model="gpt-5.4", messages=[ {"role": "user", "content": "Solve this complex optimization problem..."} ], reasoning_effort="xhigh")Tracking Token Usage Across Effort Levels
I built a simple comparison to see how effort affects token consumption:
import OpenAI from 'openai';
const openai = new OpenAI();
async function compareEffortLevels(prompt) { const levels = ['none', 'low', 'medium', 'high'];
for (const effort of levels) { const response = await openai.chat.completions.create({ model: 'gpt-5.4-mini', messages: [{ role: 'user', content: prompt }], reasoning_effort: effort });
console.log(`\n=== ${effort.toUpperCase()} EFFORT ===`); console.log(`Prompt tokens: ${response.usage.prompt_tokens}`); console.log(`Completion tokens: ${response.usage.completion_tokens}`); console.log(`Total tokens: ${response.usage.total_tokens}`); // Note: Reasoning tokens are included in completion_tokens }}Running this revealed that high effort can double my token usage compared to none. That’s a direct 2x cost increase.
A Cost-Aware Helper Function
I created this helper to standardize effort levels across my codebase:
from openai import OpenAIfrom dataclasses import dataclass
@dataclassclass ReasoningConfig: effort: str max_completion_tokens: int estimated_cost_multiplier: float
# Task-based configurationsTASK_CONFIGS = { "quick_qa": ReasoningConfig("none", 500, 1.0), "summarization": ReasoningConfig("low", 1000, 1.2), "analysis": ReasoningConfig("medium", 2000, 1.5), "coding": ReasoningConfig("high", 4000, 2.0), "complex_reasoning": ReasoningConfig("xhigh", 8000, 3.0),}
def create_completion(task_type: str, prompt: str) -> str: config = TASK_CONFIGS.get(task_type, TASK_CONFIGS["quick_qa"])
response = client.chat.completions.create( model="gpt-5.4-mini", messages=[{"role": "user", "content": prompt}], reasoning_effort=config.effort, max_completion_tokens=config.max_completion_tokens )
# Log token usage for cost tracking print(f"Effort: {config.effort}, Tokens: {response.usage.total_tokens}")
return response.choices[0].message.contentThis approach forces me to think about the task type before making the API call, preventing lazy defaults to high.
The Decision Framework I Use Now
Before making any GPT-5.4 API call, I run through this checklist:
IF task is simple/factual: -> Use 'none' or 'low'
IF task involves planning/coding/synthesis: -> Start with 'medium', upgrade if needed
IF task requires complex multi-step reasoning: -> Try 'high' first
IF evals prove 'high' insufficient AND cost acceptable: -> Consider 'xhigh'
ALWAYS ask: - Can I improve the prompt instead? - Have I tested lower effort levels? - Is the extra latency worth it?What to Optimize Before Increasing Effort
The Reddit discussion highlighted a key insight: “Improve completion rules, verification loops, tool-persistence rules before raising reasoning effort.”
I’ve found these optimizations often work better than cranking up effort:
- Clearer instructions — Be explicit about what you want
- Better examples — Few-shot prompting helps more than extra reasoning
- Structured output — Use response formats to constrain outputs
- Verification steps — Ask the model to check its own work
- Decomposition — Break complex tasks into simpler subtasks
Common Mistakes I Made
- Defaulting to
high— Expensive and often counterproductive - Using
xhighwithout benchmarking — Never justified without evaluation data - Ignoring prompt engineering — Better prompts > higher effort
- Not testing lower levels first — Always start low and increase
- Assuming separate surcharge — It’s just more tokens, billed normally
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments