keepcalculator

06 Numbers and Powers

Node.js LLM Invoice Extraction Retries and Idempotency

Card No. 06·56380 · Updated · Standard formula, shown below

For reliable supplier-invoice extraction in Node.js, validate each LLM response against a schema, retry only failures that may recover, and persist each invoice through an idempotent processing workflow. A retry can safely repeat an operation only when the system can recognize that it is the same invoice and prevent duplicate side effects.

Why invoice extraction needs more than a retry

An LLM can turn invoice text into structured fields such as supplier name, invoice number, issue date, currency, tax, and total. But a syntactically valid response is not necessarily accurate: a model may omit a field, return a date in an unexpected format, or confuse a subtotal with the amount due. Network timeouts and rate limits create a separate problem: the caller may not know whether a request completed.

These failure modes need different handling. Schema validation catches malformed or incomplete output; business checks catch inconsistent values; retry logic addresses transient service failures. Idempotency protects downstream actions, such as creating an invoice record or triggering an approval workflow, when a job is delivered more than once.

Design the extraction pipeline

Keep extraction separate from committing financial records. A practical pipeline stores the source document, extracts text or image content, asks the model for a constrained structure, validates the result, and then records the accepted data. Preserve the original document and the model output so an operator can review uncertain cases.

  1. Assign the document a stable internal ID when it enters the system.
  2. Record a document hash and relevant metadata, such as supplier and received time.
  3. Send the document content and a clear field schema to the model.
  4. Parse the response and validate types, required fields, and allowed formats.
  5. Apply business checks, then save the result using an idempotent database operation.
  6. Send unresolved or low-confidence cases to human review rather than silently accepting them.

For instance, a schema might require an invoice number, ISO-formatted date, three-letter currency code, and decimal amounts represented consistently. Treat invoice numbers as strings: they may contain leading zeros or letters. Avoid converting monetary amounts to JavaScript floating-point numbers for accounting calculations; use a decimal representation or integer minor units where appropriate, while accounting for currencies that do not use two fractional digits.

Validate before retrying

In Node.js, use a schema validator or explicit checks after parsing JSON. Reject extra fields if they could be confused with trusted data, and distinguish missing values from explicit nulls. Validate date formats and currency codes, and check relationships such as whether line-item totals reconcile with the stated subtotal within a defined tolerance. Do not assume every invoice has the same tax structure or that totals always reconcile exactly after rounding.

A validation failure is not automatically fixed by repeating the same prompt. If the model returned invalid JSON or omitted a field, a bounded retry can include a concise correction instruction and the validation errors. Keep the original response and each attempt for diagnosis. If the document itself is unreadable or ambiguous, repeated calls may produce different guesses rather than reliable facts; route such cases for review.

Do not let an LLM’s confidence statement stand in for validation. If confidence is useful in your workflow, treat it as one signal alongside field-level checks, source text, and review outcomes. Keep deterministic fields and calculated totals under application control wherever possible.

Retry transient failures with limits

Retry failures that may be temporary, such as network interruptions, service timeouts, or rate limiting, subject to the provider’s documented behavior. Use a small maximum attempt count, exponential backoff, and random jitter so many workers do not retry in lockstep. Respect a server-provided retry delay when available, and set an overall deadline so one invoice cannot occupy a worker indefinitely.

  • Usually retryable: transient connection errors, timeouts, and rate-limit responses, with backoff.
  • Usually not retryable unchanged: invalid credentials, unsupported input, malformed request parameters, and persistent schema or business-rule failures.
  • Needs care: a timeout after sending a request. The provider may have processed it even though the client did not receive the response.

Retries may incur additional requests and do not guarantee identical outputs. Record attempt number, latency, failure category, and request correlation identifiers. Avoid logging full invoice contents by default: documents can contain sensitive commercial or personal information. Redact or restrict access to diagnostic data.

Make persistence idempotent

Idempotency means that repeating the same logical operation has the same intended effect as performing it once. It does not mean model responses are identical. Use a stable processing key, such as a combination of tenant ID and internal document ID, and enforce uniqueness in the database. On repeated delivery, return or resume the existing processing record instead of creating another invoice.

A document hash can help identify identical files, but it is not a complete duplicate-invoice rule: the same invoice may arrive as a scan with different bytes, and two legitimate documents can have similar contents. Business duplicate checks may use supplier identity and invoice number, with review for collisions. Keep these checks separate from the idempotency key that identifies a particular ingestion job.

For external side effects, such as publishing an event or starting approval, use a transactional outbox or another durable delivery pattern. Write the accepted invoice and an outbox record in one database transaction; a separate worker publishes the event and marks it delivered. Consumers should also deduplicate using a stable event ID. This addresses the gap where a process crashes after a database commit but before acknowledging a message.

Observe attempts and recover safely

Make the workflow observable with structured logs and metrics. Include a document ID, idempotency key, attempt number, processing state, validation outcome, and correlation ID, but do not expose document text or secrets in routine logs. Track measures such as retry counts, schema-failure rates, time to completion, duplicate detections, and human-review volume.

Use explicit states such as received, extracting, validated, needs-review, committed, and failed. A worker recovering after a crash should inspect durable state and continue from a safe boundary. Define how stale in-progress jobs are reclaimed, and ensure two workers cannot both commit the same logical invoice. Database uniqueness constraints and conditional updates are stronger safeguards than relying only on an in-memory lock.

Keep a record of model and prompt versions when reproducibility matters. Reprocessing an invoice after changing prompts or extraction logic should be an explicit new run linked to the original, not an accidental duplicate financial record.

Frequently Asked Questions

Should I retry an LLM request after a timeout?
Often, but use a bounded retry with backoff and assume the original request may have completed. Use an idempotent processing record so a repeated result cannot create a second invoice.

Does a schema guarantee correct invoice data?
No. A schema checks structure and types, not whether the extracted values match the source. Add business validation and preserve a review path for uncertain cases.

What should I use as an invoice idempotency key?
Use a stable internal document or job ID scoped to the relevant tenant or account. Do not rely on invoice number alone, since numbering can repeat across suppliers or be entered incorrectly.

Can I safely retry invoice creation in a database?
Yes, if the operation uses a uniqueness constraint or equivalent conditional write and repeated requests resolve to the same record. Confirm that related events and notifications are deduplicated too.

Should every invalid extraction be sent back to the model?
No. A bounded correction attempt can help with formatting or omissions, but unreadable source material and ambiguous business facts usually need human review.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →