When I work with documents, I start by preserving the original PDF or Word file and then treat OCR text, extracted fields, and sections as derived views. I recommend designing for auditability because document mistakes usually become workflow mistakes.
Files that contain business truth
Document data should keep both the original file and the extracted facts because each answers a different question.
How documents move from evidence to workflow
Document data should keep both the original file and the extracted facts because each answers a different question.
Databases that fit this shape
For me, the traceability check is ownership, freshness, and whether someone can safely use the data.
Object storage, PostgreSQL, document databases, OpenSearch, Azure AI Search, Vertex AI Search, warehouse tables for extracted fields, vector indexes for document Q&A.
Cloud building blocks
| Provider | Typical services |
|---|---|
| AWS | S3, Textract, Comprehend, Glue, OpenSearch, Bedrock Knowledge Bases. |
| Azure | Blob Storage, Document Intelligence, AI Search, Synapse. |
| Google Cloud | Cloud Storage, Document AI, Vertex AI Search, BigQuery. |
A known industry pattern
My recommendation in this document pattern is to keep the original file close to every extracted field, because reviewers eventually ask where the answer came from.
Invoice processing is the real world pattern used across finance teams at large enterprises: keep the original PDF, extract supplier and line item fields, route exceptions to humans, then publish approved facts to ERP and analytics.
Where this shows up in real work
What I learnt is that this data needs ownership and freshness as much as storage.
A procurement platform receives supplier PDFs and Word contracts. The pipeline extracts vendor, purchase order, tax, due date, and payment terms, indexes the full text, and routes low confidence fields for review.
Query or pipeline example
I prefer this kind of example because it forces the design to answer real questions about latency, recovery, and handoffs.
InvoiceDecision decide(ExtractedInvoice invoice) {
BigDecimal lineTotal = invoice.lines().stream()
.map(InvoiceLine::amount)
.reduce(BigDecimal.ZERO, BigDecimal::add);
if (invoice.extractionConfidence() < 0.92) return InvoiceDecision.MANUAL_REVIEW;
if (lineTotal.compareTo(invoice.total()) != 0) return InvoiceDecision.TOTAL_MISMATCH;
return InvoiceDecision.READY_TO_POST;
}
The decision is based on extraction confidence and a total check. Low confidence or mismatched invoice math goes to review instead of being posted automatically.
Watch these edges
- Store confidence by field, not only by document.
- Keep the original document for audit.
- Version extraction models because field behavior changes.