Problem: LLM-driven services face measurable latency and cost from output tokens and heavy input contexts. Picking the right I/O format—strict JSON with schema validation or a token-oriented compact notation (TOON)—changes latency, throughput, and operational complexity. This article gives a production-ready decision matrix, benchmarks, parsing guards, and step‑by‑step implementation recipes.
Architecture overview (high-level flow)
Executive tradeoffs (concise)
- JSON:
- Pros: Deterministic parsing (JSON.parse), strong validation (JSON Schema/zod), safe for nested/typed data.
- Cons: Token-heavy punctuation; can increase both input and output tokens, raising latency and cost.
- TOON (Token-Oriented Object Notation):
- Pros: Compact for flat structures; reduces token usage and LLM latency when controlled.
- Cons: Parsing fragility on nested/complex data; needs robust validators and monitored fallbacks.
Benchmarks: microbench on a mid-tier LLM (representative results; your mileage will vary)
| Format | Avg Output Tokens | Avg Input Tokens (context added) | Round-trip Latency (ms) | Memory per-request (MB) |
|---|---|---|---|---|
| JSON (full reasoning included) | 315 | 15,000 | 11,000 | 45 |
| JSON (no reasoning; structured output) | 170 | 10,000 | 7,000 | 38 |
| TOON (compact, flat mapping) | 90 | 2,000 | 5,700 | 25 |
| JSON Schema + strict validation (additional processing) | 170 | 10,000 | 7,400 | 42 |
When to choose which format (practical checklist)
- Use JSON when:
- Data is nested or contains arrays/heterogeneous types.
- You require deterministic downstream processing or strong schema guarantees.
- Security and auditability obligate strict validation.
- Use TOON when:
- Data is flat (rows, key→value) and you control both the prompt and the parser.
- Token cost and latency are first-class constraints.
- You can implement robust fallback and sampling to detect parse drift.
- Use a hybrid:
- Top-level TOON for tokens and inline short JSON blobs for nested substructures.
- Or compress context with TOON and validate critical fields via JSON schema on a small set.
Common pitfalls and mitigations
- Hallucinated IDs: always application-validate IDs (DB lookup) and treat LLM outputs as untrusted.
- Schema drift: sample outputs and run periodic offline validation to detect changes.
- Over-reliance on JSON-LD or page schema: don’t assume LLMs see web page schema at inference time; validate via agent-driven crawls only if using agent-run browsing.
Production-ready implementation patterns
1) Estimate token and latency impact deterministically
2) Implement a small, typed serializer/deserializer layer
3) Add lightweight validator and a "safe fallback" replay/retry path
4) Monitor token counts and parsability metrics; sample raw outputs into an audit store
Typed code examples (TypeScript, production-ready)
- TOON serializer + parser + validator (Node.js/TypeScript)
- JSON path with schema validation (zod) and fallback to TOON if needed
TypeScript: TOON serializer, parser, and guard (Node 18+, ES Modules)
// toon.ts
import { z } from "zod";
import { createHash } from "crypto";
export type DashboardRow = {
id: string;
title: string;
metric: number;
tag?: string;
};
export const DashboardRowSchema = z.object({
id: z.string().min(1),
title: z.string().min(1),
metric: z.number(),
tag: z.string().optional(),
});
export type DashboardRows = DashboardRow[];
// Serialize to TOON: one line per row, pipe-separated (compact)
export function serializeToTOON(rows: DashboardRows): string {
return rows
.map((r) =>
[
escapeField(r.id),
escapeField(r.title),
String(r.metric),
r.tag ? escapeField(r.tag) : "",
].join("|")
)
.join("\n");
}
function escapeField(s: string): string {
// Minimal escape for control chars and pipe
return s.replace(/\|/g, "\\|").replace(/\n/g, "\\n");
}
// Parse TOON with validation; returns validated objects or throws
export function parseTOON(input: string): DashboardRows {
const lines = input.trim().split(/\r?\n/).filter(Boolean);
const parsed: DashboardRows = lines.map((line, idx) => {
const parts = splitPreserveEscapes(line, "|");
// Expect exactly 4 columns (id,title,metric,tag)
if (parts.length !== 4) {
throw new Error(`TOON_PARSE_ERROR line=${idx + 1} parts=${parts.length}`);
}
const maybe = {
id: unescapeField(parts[0]),
title: unescapeField(parts[1]),
metric: Number(parts[2]),
tag: parts[3] ? unescapeField(parts[3]) : undefined,
};
const result = DashboardRowSchema.safeParse(maybe);
if (!result.success) {
throw new Error(`TOON_VALIDATION_ERROR line=${idx + 1} ${result.error}`);
}
return result.data;
});
return parsed;
}
function splitPreserveEscapes(s: string, delim: string): string[] {
const out: string[] = [];
let cur = "";
let esc = false;
for (let i = 0; i < s.length; i++) {
const ch = s[i];
if (esc) {
cur += ch;
esc = false;
continue;
}
if (ch === "\\") {
esc = true;
continue;
}
if (ch === delim) {
out.push(cur);
cur = "";
continue;
}
cur += ch;
}
out.push(cur);
return out;
}
function unescapeField(s: string): string {
return s.replace(/\\\|/g, "|").replace(/\\n/g, "\n");
}
// Deterministic compact checksum for quick integrity checks
export function compactChecksum(s: string): string {
return createHash("sha256").update(s).digest("hex").slice(0, 12);
}TypeScript: Strict JSON path using zod + fallback to TOON parser
// parser.ts
import { z } from "zod";
import { parseTOON, compactChecksum } from "./toon";
export const DashboardSchema = z.object({
dashboards: z.array(
z.object({
id: z.string(),
title: z.string(),
metric: z.number(),
tag: z.string().optional(),
})
),
});
export type DashboardPayload = z.infer<typeof DashboardSchema>;
export async function robustParse(llmRaw: string): Promise<DashboardPayload> {
// Attempt JSON parse + schema validation first
try {
const parsed = JSON.parse(llmRaw);
const validated = DashboardSchema.parse(parsed);
return validated;
} catch (jsonErr) {
// Fallback: assume it's TOON compact form
try {
const rows = parseTOON(llmRaw);
return { dashboards: rows };
} catch (toonErr) {
// Final defence: log and throw with both errors for observability
const err = new Error(
`PARSE_FAILED json:${String(jsonErr)} toon:${String(toonErr)} checksum:${compactChecksum(
llmRaw
)}`
);
// attach observable metadata
(err as any).jsonErr = jsonErr;
(err as any).toonErr = toonErr;
throw err;
}
}
}Prompting patterns to reduce tokens (practical)
- Remove verbose reasoning bubbles from output. Use system messages to require concise outputs.
- Compact context: serialize repeated metadata as a short schema map (TOON) or template tokens and reference them.
- Use "example-based" few-shot only when necessary; for large context sets, prefer small, high-signal examples.
Prompt recipe (short, reproducible)
- 1System message: "Output only the compact representation. Do not include extra commentary."
- 2Provide single-line docstring that defines TOON columns: "Format: id|title|metric|tag"
- 3Example: "ex1|Example Dashboard|42|prod"
- 4Supply minimal dynamic context (2k tokens max preferred)
- 5Request final output only (no reasoning)
Operational observability and telemetry
- Track: token counts (input/output), parse success rate, checksum mismatches, time-to-parse, and retry counts.
- Sample 1% of raw LLM outputs to long-term storage (immutable) for offline QA and model debugging.
- Alert when parse success rate drops below a threshold (e.g., 98%); run automated rollback to JSON mode.
Failure modes and mitigation strategies
- Parser regressions: run contract tests that feed edge cases and fuzz tokens into the parser.
- Model drift: retrain docstrings and add new examples; do not overfit prompts to current model outputs only.
- Security: sanitize fields used in system actions (no direct eval of strings). Use allowlists for action names and lookup validated IDs.
Reproducible implementation steps
- 1Audit existing prompts and measure current token counts (input and output) per endpoint.
- 2Identify candidate endpoints where data is shallow and token savings are significant.
- 3Implement a TOON serializer + parser library (use typed schemas like zod).
- 4Add fallback path to JSON parsing and a safe retry logic (e.g., request model to re-output in JSON if TOON parse fails).
- 5Deploy behind a feature flag and run A/B: measure latency, cost, and parse errors.
- 6Gradually extend TOON to more endpoints where it is safe.
- 7Keep JSON Schema validation on the critical path (for safety) and use TOON for latency-sensitive portions.
Operational code snippet: retry-on-parse-failure with backoff (TS)
// retry.ts
import { robustParse } from "./parser";
export async function parseWithRetry(llmRaw: string, maxRetries = 2): Promise<any> {
let attempts = 0;
while (true) {
try {
return await robustParse(llmRaw);
} catch (err) {
attempts++;
if (attempts > maxRetries) throw err;
// Telemetry: increment parse_retry metric
await delay(100 * attempts); // linear backoff
// If we have structured callbacks to the model, ask for JSON explicitly:
// NOTE: callModelForJson(llmRaw) is an application-specific call to re-query the model
// with strict "output JSON only" instruction. Implement with capped retries.
// For brevity, we only delay here.
}
}
}
function delay(ms: number): Promise<void> {
return new Promise((res) => setTimeout(res, ms));
}Comparison summary (operational decision matrix)
- Latency-sensitive + flat data → TOON (with parser + fallback)
- Nested/complex data or safety-critical → JSON + JSON Schema
- Mixed workloads → hybrid: TOON top-level, JSON for nested subsets
Closing operational checklist
- Instrument token counts end-to-end.
- Implement typed parser and schema validation for both formats.
- Build safe fallbacks and application-level verification.
- Sample raw responses to audit storage.
- Gradually expand TOON usage where safe and beneficial.
Further reading and links
- Incident.io article: optimizing LLM prompts for low latency (practical reductions by removing reasoning and switching formats).
- TOON spec and reference SDKs (for token-oriented formats and examples).
- JSON Schema + zod patterns for strict validation.
Appendix: Quick token estimator (Python) for offline measurement
# token_estimator.py
from typing import List
import hashlib
def estimate_tokens_text(text: str) -> int:
"""
Heuristic token estimator: approximate using bytes/4 rule for UTF-8.
Not exact; use provider tokenizer for production.
"""
b = text.encode("utf-8")
return max(1, len(b) // 4)
def estimate_tokens_rows(rows: List[dict], format: str = "json") -> int:
import json
if format == "json":
s = json.dumps(rows, separators=(",", ":"))
elif format == "toon":
lines = []
for r in rows:
lines.append(f"{r.get('id','')[:64]}|{r.get('title','')[:128]}|{r.get('metric',0)}|{r.get('tag','')}")
s = "\\n".join(lines)
else:
raise ValueError("format must be 'json' or 'toon'")
return estimate_tokens_text(s)
if __name__ == "__main__":
sample = [{"id":"d1","title":"Main","metric":42,"tag":"prod"}]*100
print("json tokens:", estimate_tokens_rows(sample, "json"))
print("toon tokens:", estimate_tokens_rows(sample, "toon"))
print("checksum:", hashlib.sha256(b'example').hexdigest()[:12])Final note: Optimizing for token efficiency is a systems design decision. Combine format choices with telemetry, typed parsers, and safe fallbacks. TOON buys latency when used correctly; JSON buys correctness. Use both as tools in a pragmatic engineering toolkit.



