Uploaded Invoice OCR Backlogs — Store Extracted Text After Scan Validation
The page fires because invoice search has stopped finding recent orders. On-call sees successful uploads, no missing originals, and a growing interval between uploaded_at and text_stored_at. The customer-facing symptom arrived late: the useful alert was the age of the oldest accepted invoice still waiting for OCR. Short answer: accept and validate the uploaded scan, store the original under its document ID, enqueue OCR, then persist extracted text and confidence separately. Keep the original so a template change or a better extractor can trigger reprocessing. Alert on queue age against the search-availability SLO, not merely on OCR errors. Running OCR inline on a large scan makes the upload request inherit OCR latency and timeout risk. This is an ownership decision disguised as an API choice. An e-commerce team that owns invoice layouts can validate fields against its order record and tune extraction deliberately; a team receiving arbitrary supplier scans needs a review path because confidence, when available, is a routing signal rather than proof that an invoice is correct. How should Node.js store extracted text from an uploaded OCR scan? An OCR failure counter catches explicit failures. It misses slow work, workers that are alive but underprovisioned, and accepted jobs that never become searchable. The earlier signal is backlog age: now - uploaded_at for the oldest document without stored text. Pair it with arrival rate, completion rate, and the count awaiting review. Those four values answer the capacity question the page cannot: is this a brief burst, or is demand outrunning service capacity? In a Node.js upload service, the HTTP handler should validate and admit the scan, return its document ID, and leave extraction and text storage to a worker. Waiting compounds. Set the page from the user promise. If searchable invoice text has a 15-minute SLO, the paging threshold needs enough remaining budget for diagnosis and recovery; paging at minute 15 only documents a breach. I would also separate freshness from correctness. A fast extractor that produces unusable totals is not healthy, while a correct result waiting behind an unbounded queue is not available. The upload handler should return after durable admission, not after recognition. Validate the content type, size, document ID, and known order association before admitting work. Store the scan privately and store the extracted representation as a different object or record. Never overwrite the evidence with its interpretation. Instrument the state transition, not the HTTP request The useful unit is one document moving through named states: accepted, original stored, queued, extracting, text stored, or review required. An HTTP latency histogram around the upload endpoint cannot tell you that the worker stopped completing documents. A transition record can. Before binding a worker to any vendor request shape, inspect the live contract. This Go program calls the platform's public discovery surface, takes its URL and bearer authentication from the environment, uses an explicit method, retries 429 responses with Retry-After, and surfaces response bodies for other errors. The returned catalog is where a client should obtain the documented OCR path and full JSON Schema rather than guessing fields from prose. package main import ( "fmt" "io" "net/http" "os" "strconv" "time" ) func retryDelay(resp *http.Response, attempt int) time.Duration { if seconds, err := strconv.Atoi(resp.Header.Get("Retry-After")); err == nil && seconds > 0 { return time.Duration(seconds) * time.Second } return time.Duration(1
This is a summary aggregated from Dev.to. Read the complete article on the original site:
Read full article at Dev.to