Document Processing

Page-Parallel LLMs: The Right Way to Handle Long Invoices

February 13, 2026
-
12 min read

maryam.ahmad

Maryam builds custom document-processing systems for enterprise workflows and writes about practical automation, covering OCR accuracy, data-extraction patterns, and documents processing at scale.

Like what you see? Share with a friend.

LinkedIn Icon X/Twitter Icon

The Multi-Page Invoice Problem 

Modern AI extraction systems using LLMs (GPT-4, Claude) can automatically extract structured data from invoices: invoice numbers, line items, totals, and vendor details. This works great for one or two-page invoices. Send the invoice to the LLM, and get back structured JSON, done. This is the foundation of LLM invoice extraction and broader AI invoice data extraction systems. Send the invoice to the LLM, and get back structured JSON from invoices, done.

But here’s the problem: Most invoices aren’t 1-2 pages. They’re long. Really long. 

Multi-page invoices don’t break AI extraction—poor architecture does. Splitting documents into pages, extracting in parallel, and merging via a consistent schema delivers faster, more reliable results than single-prompt processing.

The Reality of Multi-Page Invoices 

Real-world invoice length distribution: 

1-3 pages:     40% of invoices (simple transactions)
4-10 pages:    35% of invoices standard B2B)
11-20 pages:   15% of invoices (complex orders)
21-50 pages:    8% of invoices (major contracts)
50+ pages:      2% of invoices (enterprise deals

Complex B2B transactions generate long invoices with hundreds of line items and detailed specifications. Construction materials invoices, hospital supplier invoices, IT services invoices, and manufacturing parts orders routinely require serious long invoice processing capabilities.

Examples: Construction materials invoices (45 pages of lumber, concrete, steel pricing), hospital supplier invoices (30 pages, 450 medical equipment line items), IT services invoices (25 pages of hourly consultant breakdowns), and manufacturing parts orders (38 pages, 600+ SKUs with technical specs). 

The critical question: How do you efficiently process a 30-page invoice with an LLM? 

The Naive Approach: Send All Pages at Once 

At first glance, it seems simple: “Just send all 30 pages to GPT-4 and ask it to extract the data.” This is the default approach to invoice extraction with GPT-4, and it works fine for short invoices.
Sending 30 pages to an LLM at once is inefficient and unreliable. Page-parallel extraction turns minutes into seconds while improving completeness across every line item.

Problem 1: Cost and Processing Time 

The Math: 

Average invoice page: 2,000-3,000 tokens
30-page invoice: 60,000-90,000 tokens input

SINGLE LARGE REQUEST (30 pages in one call):
– Cost per invoice: $0.30
– Processing time: 90-120 seconds

PAGE-PARALLEL APPROACH (30 separate extractions):
– Cost per invoice: $0.45
– Processing time: 3-5 seconds (parallel)

Page-parallel extraction is slightly more expensive but 20-30x faster. For production-grade multi-page invoice processing, speed and reliability matter more than marginal token savings.

Problem 2: Attention Dilution

When you give an LLM 30 pages, the model doesn’t treat all content equally. Research shows: 

  • First/last pages get highest attention 
  • Middle pages (10-20) often get skimmed or missed 

Real-World Impact: 

30-page invoice sent in single prompt:
Page 1: Invoice #12345 (HIGH attention – extracted correctly)
Page 15: Line items 160-180 (LOW attention – 60% accurate, items missed)
Page 30: Total: $903,781.18 (HIGH attention – extracted correctly)

Result: Missing 15-20% of line items from middle page

Problem 3: Hallucination Risk 

LLMs can hallucinate – inventing data that doesn’t exist in the document. With long documents, this risk increases. 

Common Hallucinations: 

  • Inventing missing values: Blank quantity field → LLM API “Quantity: 100” (fabricated) 
  • Fabricating line items: Gap in item numbers (001-050, 052) → LLM invents “Item 051: Installation Service, $500” 
  • Creating addresses: Unclear ship-to → LLM generates “123 Main Street, Springfield, IL” (plausible but invented) 
  • Making up IDs: Missing tax ID → LLM creates “12-3456789” (realistic format, completely fake) 

Why long documents make this worse: When processing 30 pages, the LLM loses track of what it actually sees vs. what seems plausible. Missing fields trigger pattern-based “completion” from training data rather than acknowledging absence. 

Problem 4: No Page-Specific Optimization 

Different pages need different handling: 

First page: Header fields + first line items
Middle pages: Only line items (ignore repeated headers)
Last page: Final line items + summary section

Single prompt can’t optimize per page. You waste tokens extracting repeated headers 30 times and can’t prioritize critical pages. 

The Bottom Line 

Sending 20-30 page invoices to an LLM in a single prompt: 

  • Takes 90-120 seconds (vs. 3-5 seconds parallel) 
  • Risks attention dilution on middle pages 
  • Increases hallucination probability 
  • Can’t optimize per page 

If your goal is complete structured JSON from invoices, this approach becomes unreliable as invoices grow longer.

The limitation isn’t the LLM, it’s how it’s used. Treat pages as independent units, not a single long context, and you eliminate attention loss, reduce hallucinations, and scale extraction reliably.

There must be a better way. 

The Solution: Page-Parallel Extraction with Schema Union 

The Core Insight 

Instead of fighting the limitations of long documents, embrace the natural processing unit: the page. 

Key Realization: 

While invoices are multi-page documents, most information on each page can be extracted independently: 

  • First page has header info and line items 
  • Middle pages have line items 
  • Last page has line items, and totals and summary 

The challenge isn’t extracting from individual pages; it’s merging the results intelligently. 

The Three-Part Strategy 

three-part-doc-strategy

Why This Works: 

  1. Small units: Each page is 2-3K tokens – fast, cheap, reliable 
  1. Parallel execution: All pages process simultaneously – 20x speed improvement 
  1. Fault tolerance: Failed pages retry independently 
  1. Natural debugging: Page-level confidence scoring 
  1. Schema uniformity: All extractions use same structure – union is straightforward 

Let’s dive into each step. 

Step 1: Schema-First Design 

The Fundamental Principle 

If every page extraction produces output in the same schema, results become mergeable. 

The schema acts as a contract that all page extractions honor, regardless of what’s actually on that page. 

Example: Invoice Extraction Schema 

{
  “invoice_number”: null,
  “invoice_date”: null,
  “purchase_order”: null,
  “vendor”: {
    “name”: null,
    “address”: null,
    “tax_id”: null
  },
  “customer”: {
    “name”: null,
    “billing_address”: null,
    “shipping_address”: null
  },
  “line_items”: [
    {
      “item_number”: null,
      “description”: null,
      “quantity”: null,
      “unit_price”: null,
      “total”: null
    }
  ],
  “summary”: {
    “subtotal”: null,
    “tax_amount”: null,
    “total”: null
  }
}
  

Key Characteristics: 

  1. Comprehensive: Includes all possible fields across all pages 
  1. Nullable: Fields use null if not present on a page 
  1. Typed: Arrays for lists, objects for nested structures 
  1. Consistent: Same structure for all pages 

How Pages Fill the Schema 

First Page Extraction: 

{
  “invoice_number”: “INV-2024-003847”,
  “invoice_date”: “2024-01-15”,
  “due_date”: “2024-02-14”,
  “purchase_order”: “PO-2024-112458”,
  “vendor”: {
    “name”: “ACME INDUSTRIAL SUPPLY CO.”,
    “address”: “123 Industrial Blvd”,
    “tax_id”: “12-3456789”
  },
  “customer”: {
    “name”: “Precision Manufacturing Corp.”,
    “billing_address”: “4521 Industrial Parkway, Detroit, MI 48201”
  },
  “line_items”: [
    {“item_number”: “001”, “description”: “…”, “quantity”: 5000, “unit_price”: 2.45, “total”: 12250.00},
    {“item_number”: “010”, “description”: “…”, “quantity”: 600, “unit_price”: 6.80, “total”: 4080.00}
  ],
  “summary”: {
    “subtotal”: null,
    “tax_amount”: null,
    “total”: null
  }
}

  Middle Page Extraction: 

{
  “invoice_number”: “INV-2024-003847”,
  “invoice_date”: null,
  “due_date”: null,
  “purchase_order”: null,
  “vendor”: null,
  “customer”: null,
  “line_items”: [
    {“item_number”: “141”, “description”: “…”, “quantity”: 250, “unit_price”: 18.50, “total”: 4625.00},
    {“item_number”: “150”, “description”: “…”, “quantity”: 100, “unit_price”: 95.00, “total”: 9500.00}
  ],
  “summary”: null
}
  

Last Page Extraction: 

{
  “invoice_number”: “INV-2024-003847”,
  “invoice_date”: null,
  “vendor”: {
    “name”: “ACME INDUSTRIAL SUPPLY CO.”
  },
  “customer”: null,
  “line_items”: [
    {“item_number”: “285”, “description”: “…”, “quantity”: 25, “unit_price”: 68.00, “total”: 1700.00},
    {“item_number”: “288”, “description”: “…”, “quantity”: 50, “unit_price”: 12.50, “total”: 625.00}
  ],
  “summary”: {
    “subtotal”: 847523.75,
    “shipping”: 4250.00,
    “tax_amount”: 51157.43,
    “total”: 903781.18
  }
}
  

Notice: 

  • First page fills header fields, last page doesn’t 
  • Last page fills summary, first page doesn’t 
  • All pages contribute line items 
  • Some fields repeat (invoice_number, vendor name) 

This is perfect for union! We can merge these intelligently. 

Schema Generation for Unknown Documents 

What about invoices from vendors you’ve never seen before? You need a schema, but you don’t know the format yet. 

Solution: LLM-Generated Schemas 

Send the first page, one of the middle pages, and the last page to the LLM with a prompt asking it to analyze the invoice structure and create a comprehensive JSON schema. The LLM identifies all fields (header info, line-item structure, summary fields) and generates a schema template with appropriate data types. 

Example Generated Schema for Hospital Supply Invoice: 

{
  “header”: {
    “invoice_number”: “string”,
    “invoice_date”: “string”,
    “account_number”: “string”,
    “facility_name”: “string”
  },
  “line_items”: [
    {
      “item_code”: “string”,
      “item_description”: “string”,
      “ndc_number”: “string”,
      “lot_number”: “string”,
      “expiration_date”: “string”,
      “quantity”: “number”,
      “unit_of_measure”: “string”,
      “unit_price”: “number”,
      “extended_price”: “number”
    }
  ],
  “summary”: {
    “subtotal”: “number”,
    “shipping”: “number”,
    “tax”: “number”,
    “total”: “number”
  }
}
  

Once generated: 

  • Cache the schema by vendor ID 
  • Use for all future invoices from that vendor 
  • Update if vendor format changes 

This ensures union compatibility even for vendors you’ve never processed before. 

 

Step 2: Parallel Page Extraction 

The Extraction Process 

Each page is processed independently using the same schema. The prompt includes: 

  • Context about which page this is (page X of Y) 
  • The full schema structure 
  • Instructions to use null for fields not on this page 
  • The page image / page text from OCR 

The LLM returns JSON matching the schema exactly, filling in whatever fields are visible on that specific page. 

Parallel Execution 

Using concurrent processing, all pages are submit to the LLM simultaneously. Key characteristics: 

  • Truly parallel: All 30 pages process at once 
  • Independent: Each page extraction is isolated 
  • Fast: 30 pages complete in ~3-5 seconds (not 30 × 3 = 90 seconds) 
  • Fault-tolerant: Failed pages don’t block others 
  • Scalable: Add more workers for higher volume 

Step 3: Intelligent Union 

The Union Challenge 

We have 30 separate JSON objects, all with the same structure. How do we merge them into one complete invoice? 

Naive approach (doesn’t work): 

# Just take the last page?
final_result = page_results[-1]
# Missing all data from pages 1-29!

# Merge everything?
final_result = {**page_results[0], **page_results[1], …}
# Overwrites fields, loses data!
  

We need intelligent merging based on field types. 

The First-Non-Null Strategy 

Core Principle: 

For any field, take the first non-null value encountered when processing pages in order (page 1, page 2, page 3…). 

How it works: 

  1. Sort all page results by page number 
  1. For each field in the schema, walk through pages in order 
  1. Take the first non-null value found 
  1. Skip subsequent values (even if different) 

Example – Invoice Number: 

Page 1: invoice_number = “INV-2024-003847” ← Use this
Page 2: invoice_number = “INV-2024-003847” (duplicate, ignore)
Page 15: invoice_number = null (ignore)
Page 30: invoice_number = “INV-2024-003847” (duplicate, ignore)

Result: “INV-2024-003847”
  

This automatically handles repeating headers! The header on pages 2 and 30 is ignored because page 1 already provided the value. 

Array Concatenation 

For array fields like line_items, concatenate all arrays in page order: 

Page 1: [item_001, item_002, …, item_010]  (10 items)
Page 2: [item_011, item_012, …, item_020]  (10 items)
…
Page 30: [item_285, item_286, item_287, item_288]  (4 items)

Result: Array with all 288 items in sequence
  

Nested Object Merging 

For nested objects (like vendor, customer, summary), apply first-non-null to each field within the object: 

Page 1: vendor = {name: “ACME”, address: “123 Main St”, tax_id: “12-3456789”}
Page 30: vendor = {name: “ACME”, address: null, tax_id: null}

Result: {name: “ACME”, address: “123 Main St”, tax_id: “12-3456789”}
  

All fields come from page 1 since it provided non-null values first. 

Union Algorithm Summary 

The union process: 

  1. Singular fields (invoice_number, date, etc.): Use first non-null 
  1. Nested objects (vendor, customer, summary): Merge fields using first non-null 
  1. Arrays (line_items): Concatenate in page order 

Example Union in Action 

Input: Multiple Page Extractions 

First page: 

{
  “invoice_number”: “INV-2024-003847”,
  “invoice_date”: “January 15, 2024”,
  “vendor”: {“name”: “ACME”, “address”: “123 Main St”},
  “line_items”: [item_001, item_002, …, item_010],
  “summary”: {“subtotal”: null, “total”: null}
}
  

Middle page: 

{
  “invoice_number”: null,
  “vendor”: null,
  “line_items”: [item_141, item_142, …, item_150],
  “summary”: null
}
  

Last page: 

{
  “invoice_number”: “INV-2024-003847”,
  “vendor”: {“name”: “ACME”},
  “line_items”: [item_285, item_286, item_287, item_288],
  “summary”: {“subtotal”: 847523.75, “tax_amount”: 51157.43, “total”: 903781.18}
}
  

Output: Single Merged Invoice 

{
  “invoice_number”: “INV-2024-003847”,
  “invoice_date”: “January 15, 2024”,
  “vendor”: {
    “name”: “ACME”,
    “address”: “123 Main St”
  },
  “line_items”: [
    item_001,
    item_002,
    …,
    item_010,
    item_011,
    …,
    item_288
  ],
  “summary”: {
    “subtotal”: 847523.75,
    “tax_amount”: 51157.43,
    “total”: 903781.18
  }
}
  

We have one complete invoice with: 

  • Header from first page 
  • All 288 line items from all pages 
  • Summary from last page 
  • No duplicates, no missing data 

Automate Your Doc Processing Workflows with Docspire

Contact us to see how it works

Handling Edge Cases 

Edge Case 1: Records Spanning Multiple Pages 

The Problem: 

Sometimes a single line item splits across pages: 

Page N bottom:
Item 172: Heavy-Duty Industrial Hydraulic Cylinder Assembly with Extended

[PAGE BREAK]

Page N+1 top:
Warranty Package, 5000 PSI Rated
Quantity: 12, Price: $2,450, Total: $29,400
  

Solution: 

Detection: Check if line items have item numbers but are missing required fields (quantity, price, total). These are incomplete records. 

Reassembly: 

  • Track the last incomplete item from each page 
  • Check if the first item on the next page lacks an item number (continuation marker) 
  • Merge descriptions and copy missing fields from the continuation 
  • Result: One complete line item with full data 

Final Result: 

{
  “item_number”: “172”,
  “description”: “Heavy-Duty Industrial Hydraulic Cylinder Assembly with Extended Warranty Package, 5000 PSI Rated”,
  “quantity”: 12,
  “unit_price”: 2450.00,
  “total”: 29400.00
}
  

Edge Case 2: Duplicate Detection 

Sometimes OCR errors or table formatting cause the same item to appear on consecutive pages. 

Solution: Deduplicate based on item_number. Keep track of seen item numbers and skip duplicates during array concatenation. 

Complete Workflow 

High-Level Processing Pipeline 

The complete multi-page invoice processing workflow: 

  1. Schema Management
  • Identify vendor from first page (logo, vendor name, format) 
  • Check cache for existing schema 
  • If new vendor: generate schema from sample pages 
  • Cache schema for future use 
  1. Parallel Extraction
  • Invoice extraction with GPT-4 splits the invoice into individual pages
  • Submit all pages to LLM API simultaneously 
  • Each page receives same schema + page context 
  • Collect results with retry logic for failures 
  1. Pre-Processing
  • Detect incomplete records (missing quantity/price fields) 
  • Identify split records across page boundaries 
  • Merge fragmented descriptions and data 
  1. Union
  • Apply first-non-null for singular fields 
  • Merge nested objects field-by-field 
  • Concatenate line item arrays 
  • Deduplicate any duplicate line items 
  1. Post-Processing
  • Clean up merged data 
  • Format dates and numbers 
  • Calculate derived fields if needed 
  • Verify line totals and invoice totals 
  1. Return Structured Result
  • Complete invoice JSON 
  • Metadata (page count, processing time) 
  • Per-page confidence scores 

Multi-page document processing isn’t about bigger models—it’s about better pipelines. Split, extract, and intelligently merge to achieve production-grade accuracy at scale.

Conclusion 

Multi-page invoices don’t need special handling—they need better architecture. Split, extract, merge. The same pattern works for purchase orders, contracts, medical records, and any multi-page document. 

How Docspire Helps 

Docspire implements page-parallel extraction for you. Upload multi-page invoices and get structured JSON back—no need to build the splitting, parallel extraction, or union logic yourself. 

What’s handled: 

  • Automatic page splitting and parallel extraction 
  • Schema generation for new vendor 
  • Smart union of the extracted Jsons 
  • Fragment detection for records split across pages 
  • Production infrastructure (10K+ invoices/day) 

Stop losing money to matching errors – See how Docspire can help →

Start your 14-day free trial!

Share with your community!

LinkedIn Icon X/Twitter Icon
↑↓ navigate   ↵ open   esc close
Start typing to search across all content