Short answer: make invoice extraction a bounded pipeline, not one heroic prompt. Measure tokens before the model call, chunk by invoice structure, retrieve only relevant passages, validate the JSON, and retry only operations that are safe to retry. This keeps a long supplier invoice from turning into a timeout while preserving a path to another model or gateway later.

I build for an edtech product that turns supplier invoices into fields such as invoice number, billing period, tax, currency, and line items. The awkward documents are not always the largest PDFs. A 12-page invoice with repeated terms and scanned tables can be harder than a clean 40-page statement because the useful evidence is sparse and badly ordered.

Timeout triage starts with the evidence boundary

Start with a provider-neutral contract. The application should pass text and a schema to an adapter and receive either typed JSON or a classified failure. Keep provider SDK objects out of the rest of the codebase. A gateway such as LiteLLM can sit behind that adapter, but the same boundary can also point directly at a self-hosted model.

The first pass is accounting. Estimate tokens, preserve page and table-row metadata, and reject or split input that cannot fit the selected context budget. A timeout is an operational symptom; an overlong prompt is a predictable input condition. Treat those differently in logs and dashboards. When the worker sees an HTTP 408 or its own deadline, it should retain the source hash and chunk IDs before returning the job to the queue; otherwise the next attempt has no way to tell “same work, later attempt” from “new invoice.” That distinction affects deduplication, review screens, and the eventual provider migration, because evidence remains comparable even when the model response format changes.