Getting an LLM to return JSON in a demo is easy. Getting it to return valid, complete, schema-compliant JSON across thousands of real requests is where things start breaking.
The usual mistake is treating structured output as a prompt-writing problem:
“Return the result in JSON format.”
That may work until users send ambiguous input, prompts get longer, models change behavior, or a provider has a bad day. In production, structured output is not a formatting preference. It is an API contract.
1. HTTP 200 is not success
A model request can return successfully while still being unusable:
- JSON is wrapped in Markdown fences
- A required field is missing
- A number arrives as a string
- An enum contains an unsupported value
- Extra commentary appears outside the JSON
- The output is valid JSON but logically incomplete
If your application accepts all of that because the API returned 200 OK, you are pushing failure downstream—to your database, workflow engine, or end user.
The correct flow is:
Model response → Parse → Validate schema → Validate business rules → Accept or recover
Parsing checks whether JSON is syntactically valid. Schema validation checks structure. Business validation checks whether the result is actually usable. These are different jobs.
2. Make the schema do real work
A weak schema only defines field names. A useful schema defines constraints.
Instead of this:
{
"priority": "string",
"score": "number"
}
Use constraints that match your application:
{
"priority": "low | medium | high",
"score": "integer from 0 to 100",
"summary": "non-empty string, maximum 300 characters"
}
For extraction tasks, explicitly define required fields, allowed values, nullable fields, and default behavior when information is unavailable.
One important rule: do not force the model to invent data just to satisfy a required field. Let it return null, "unknown", or a predefined fallback value when the source does not contain the answer. Fake completeness is worse than an honest gap.
3. Repair strategy beats blind retry
When validation fails, many systems simply resend the same prompt. That is lazy engineering, and it often produces the same error with more latency and token cost.
A better recovery policy depends on the failure:
- Invalid JSON: ask for JSON only, remove Markdown, and include the validation error
- Missing required fields: ask the model to regenerate only the incomplete fields
- Wrong enum values: provide the allowed values again
- Business-rule failure: request a corrected result with the exact failed rule
- Repeated failure: switch model, simplify the task, or return a controlled fallback
For example:
Validation failed: "priority" must be one of low, medium, high.
Return only corrected JSON. Do not add explanations.
This gives the model an actionable correction target instead of vaguely saying “try again.”
4. Keep the repair loop bounded
A repair loop without limits is a cost leak waiting to happen. Set clear boundaries:
- Maximum one or two repair attempts
- Separate token budget for retries
- Timeout budget across the entire request
- A defined degraded response when recovery fails
That final fallback might be a partial result, a queue-for-review state, or a clear error response. The worst option is silently sending malformed data into the rest of the system.
Track three metrics in particular:
- Initial schema pass rate
- Recovery rate after validation failure
- Average cost per successful structured response
A high retry success rate is not automatically good news. It may mean your first-pass prompt or model selection is weak.
5. Model choice still matters
Different models behave differently under strict output requirements. One may be cheaper and fast for classification but unreliable with nested schemas. Another may be slower but much more stable for complex extraction.
That is why structured-output workloads benefit from multi-model access. You can route simple jobs to an efficient model, reserve stronger models for complicated schemas, and keep a backup option when validation repeatedly fails.
The goal is not to find one universally “best” model. It is to build a pipeline where invalid output is detected early, repaired intelligently, and prevented from becoming an application failure.
Try Tokenbay: https://www.tokenbay.com/?utm_source=devto&utm_medium=community_content&utm_campaign=week1_free_content
Top comments (0)