{
  "id": "pct-2026-11-09-spotlight-e10e8ebe80",
  "content_type": "article",
  "desk": "spotlight",
  "title": "Keep the OCR queue fed, and keep the receipts",
  "publication_date": "2026-11-09",
  "observation_date": "2026-11-09",
  "editorial_voice": "AI-assisted Spotlight Desk; practical builder voice",
  "body": "# Keep the OCR queue fed, and keep the receipts\n\n*Product spotlight | Peterson Compute Trading | November 9, 2026*\n*AI-assisted public-source analysis. No OCR benchmark, deployment or purchase was performed. Dollar figures are US dollars.*\n\nGive a builder 100,000 scanned catalogue pages and a search box to fill. The job is ordinary: recover printed text, preserve its page coordinates, and let readers jump back to the original image. Our proposed collection is rights-cleared, non-sensitive and mostly English. It is a hypothetical workload, not a customer result.\n\nThe tempting question is which GPU to rent. Start one level earlier: how often will the worker stop, and where will its finished pages live? Runpod Serverless makes those questions unusually concrete. Its queue can keep a worker processing successive requests, but running time includes initialization and waiting. Its completed API results also expire. A successful OCR run needs both a controlled bill and a durable output. [Worker lifecycle](https://docs.runpod.io/serverless/workers/overview), [result retention](https://docs.runpod.io/serverless/endpoints/send-requests)\n\n## Define a usable page\n\nUse PaddleOCR's PP-OCRv5 server detection and recognition models as the candidate engine. The developer's model cards document the two stages separately: locate text, then recognize text lines. They do not establish accuracy on this catalogue. Keep the source image beside the output so readers can verify part numbers, punctuation and tiny type. [Detection model](https://huggingface.co/PaddlePaddle/PP-OCRv5_server_det), [recognition model](https://huggingface.co/PaddlePaddle/PP-OCRv5_server_rec)\n\nPin the model files, pipeline options, dependency versions and container digest. The current PaddleOCR tutorial supports explicit model selection and GPU execution; relying on an unspecified default can change the experiment later. For this first pass, target text search rather than faithful reconstruction of tables or illustrations. [Pipeline documentation](https://www.paddleocr.ai/latest/en/version3.x/pipeline_usage/OCR.html)\n\nPrepare a human-checked sample covering faint scans, rotated pages, dense columns and similar-looking characters. Define acceptance before measuring speed: correct searchable identifiers, usable text coverage and a reliable page link. Track failures separately. A page returned by the API is not automatically a page worth indexing.\n\n## Read the meter literally\n\nRunpod's endpoint-settings documentation, updated November 4, lists its 24-GB category of L4, A5000 and 3090 GPUs at $0.00019 per second. That is $0.684 per worker-hour with one GPU. This is a documented planning rate, not an account quote or a promise of a particular card. The public pricing-page fetch was unreadable in this check, so verify the console rate before spending. [Endpoint settings](https://docs.runpod.io/serverless/endpoints/endpoint-configurations)\n\nThe billing guide, updated October 15, says charges run from worker start until full stop, rounded up to a second. Model loading can be billed; ordinary image pulls and cached-model downloads normally occur before the worker starts. A running worker's idle-timeout window is billed too. The console label Idle instead means the worker has scaled down and is unbilled. Those two uses of idle deserve different counters. [Billing rules](https://docs.runpod.io/serverless/pricing)\n\nFor the proposed trial, set zero active workers, cap concurrency, and explicitly set timeouts. Console and REST v2 defaults differ, so inspect the resulting configuration rather than assuming a copied example matches the console. GPU categories can contain different hardware, and fallback choices can change the execution profile. Record the actual device on every run. [Configuration reference](https://docs.runpod.io/serverless/endpoints/endpoint-configurations)\n\n## The same GPU, two different bills\n\nHere is an intentionally hypothetical cost model. Assume 100,000 pages, two seconds of processing per page, twenty seconds of billed startup per worker activation, and a five-second billed tail before shutdown. Processing includes input handling and durable output writes within the worker. None of these timings has been measured.\n\nIn a fragmented schedule, suppose each worker activation handles ten pages before the queue empties. Ten thousand activations consume 200,000 processing seconds plus 250,000 startup-and-tail seconds. At the documented rate, the compute bill is $85.50.\n\nIn a well-fed schedule, suppose each activation handles 1,000 pages before shutting down. One hundred activations consume the same 200,000 processing seconds plus 2,500 overhead seconds. The compute bill becomes $38.48, a hypothetical reduction of $47.03, or 55%.\n\nThis comparison changes the number of worker activations, not model speed. It does not require a thousand-page API request. Keep jobs small and feed them successively: Runpod documents that workers take queued jobs back to back. One-page requests do not imply one cold start per page. Conversely, batching requests cannot guarantee the assumed hundred activations; arrival timing, scaling, failures and available capacity decide what happens. [Worker execution sequence](https://docs.runpod.io/serverless/workers/overview)\n\nThe arithmetic is simply rate multiplied by processing seconds plus activation overhead. Add 2% extra processing for retries to the well-fed case, while holding activations fixed, and compute rises to $39.24. If only 95,000 unique pages meet the quality bar, that is about $0.413 per thousand accepted pages. These are sensitivity inputs, not reliability claims. Storage, external preparation, transfer charges elsewhere, taxes and human review remain outside the model.\n\n## The receipt must outlive the request\n\nRunpod's request guide, updated October 19, gives asynchronous /run results a thirty-minute retention window after completion. The job's TTL is a separate clock covering queueing and execution. Neither is an archive. Leaving collection until tomorrow can therefore lose access to completed API results. [Request policies and retention](https://docs.runpod.io/serverless/endpoints/send-requests)\n\nHave each proposed worker write its page result to durable storage before returning success. Derive its key from the input hash, page number, model revision and processing options. Commit atomically, retain the original coordinates, and return a compact reference. A retry checks for a valid existing result. A manifest records accepted, rejected and pending pages, with capped attempts and a quarantine for corrupt inputs. This is a design proposal, not implemented exactly-once execution.\n\nStage submissions so queue age stays within the configured TTL. Set execution limits around measured page-runtime tails, not the average. Reconcile source pages against durable outputs and the bill. Record worker starts, billed seconds, device identity, failed attempts and accepted unique pages. That makes a faster GPU's eventual contribution measurable without confusing it with a better-fed queue.\n\nPaddleOCR's repository is Apache-2.0 licensed, and both selected model cards declare Apache-2.0. Preserve applicable license and attribution notices, mark distributed modifications, and review additional dependencies. Those licenses do not grant rights to the scanned catalogue. [Repository license](https://github.com/PaddlePaddle/PaddleOCR/blob/main/LICENSE), [model licenses](https://huggingface.co/PaddlePaddle/PP-OCRv5_server_rec)\n\nThe first trial should prove that a finished page survives, a retry does not duplicate it, and the billed lifetime matches the ledger. Then optimize dollars per accepted page. The most useful GPU purchase may be the one postponed until those three checks pass.\n",
  "sources": [
    {
      "id": "SP-S1",
      "title": "Endpoint settings",
      "publisher": "Runpod",
      "published": null,
      "updated": "2026-11-04",
      "url": "https://docs.runpod.io/serverless/endpoints/endpoint-configurations",
      "accessed": "2026-11-09",
      "access_note": "Opened and checked 24-GB GPU-category rate USD 0.00019/second, hardware grouping, worker controls and explicit warning that console and REST v2 defaults differ. Page displays last-modified November 4, 2026.",
      "license_status": "Public documentation; reuse license not established. Linked and paraphrased, no screenshots reproduced.",
      "publication_date": null,
      "observation_date": "2026-11-09"
    },
    {
      "id": "SP-S2",
      "title": "Serverless pricing",
      "publisher": "Runpod",
      "published": null,
      "updated": "2026-10-15",
      "url": "https://docs.runpod.io/serverless/pricing",
      "accessed": "2026-11-09",
      "access_note": "Opened worker-lifetime billing, rounding up to the next whole second, cold-start and waiting billing, unbilled scaled-down state, storage as separate component, and active-worker discount available only through sales inquiry. No older active-worker percentage used.",
      "license_status": "Public documentation; reuse license not established. Linked and paraphrased.",
      "publication_date": null,
      "observation_date": "2026-11-09"
    },
    {
      "id": "SP-S3",
      "title": "Workers overview",
      "publisher": "Runpod",
      "published": null,
      "updated": "2026-10-15",
      "url": "https://docs.runpod.io/serverless/workers/overview",
      "accessed": "2026-11-09",
      "access_note": "Opened lifecycle showing cached preparation before running, back-to-back processing, billed waiting, scale-down and console Idle distinction.",
      "license_status": "Public documentation; reuse license not established. Linked and paraphrased.",
      "publication_date": null,
      "observation_date": "2026-11-09"
    },
    {
      "id": "SP-S4",
      "title": "Send API requests",
      "publisher": "Runpod",
      "published": null,
      "updated": "2026-10-19",
      "url": "https://docs.runpod.io/serverless/endpoints/send-requests",
      "accessed": "2026-11-09",
      "access_note": "Opened TTL versus execution timeout and separate result-retention table: async /run 30 minutes; sync /runsync 1 minute. Last-modified date visible.",
      "license_status": "Public documentation; reuse license not established. Linked and paraphrased.",
      "publication_date": null,
      "observation_date": "2026-11-09"
    },
    {
      "id": "SP-S5",
      "title": "OCR pipeline usage tutorial",
      "publisher": "PaddleOCR project",
      "published": null,
      "updated": null,
      "url": "https://www.paddleocr.ai/latest/en/version3.x/pipeline_usage/OCR.html",
      "accessed": "2026-11-09",
      "access_note": "Opened explicit model selection, local model paths, version selection and GPU execution. Current tutorial defaults can differ from PP-OCRv5; example does not claim v5 is latest. No trustworthy page publication/update date established.",
      "license_status": "Public project documentation; no extensive quotation or reproduced image. Repository software license checked separately.",
      "publication_date": null,
      "observation_date": "2026-11-09"
    },
    {
      "id": "SP-S6",
      "title": "PP-OCRv5_server_det model card",
      "publisher": "PaddlePaddle",
      "published": null,
      "updated": null,
      "url": "https://huggingface.co/PaddlePaddle/PP-OCRv5_server_det",
      "accessed": "2026-11-09",
      "access_note": "Opened publisher model card; verified text-detection role, model identification and Apache-2.0 declaration. No workload performance claim adopted.",
      "license_status": "Publisher model card declares Apache-2.0; review pinned artifact and additional dependencies before distribution.",
      "publication_date": null,
      "observation_date": "2026-11-09"
    },
    {
      "id": "SP-S7",
      "title": "PP-OCRv5_server_rec model card",
      "publisher": "PaddlePaddle",
      "published": null,
      "updated": null,
      "url": "https://huggingface.co/PaddlePaddle/PP-OCRv5_server_rec",
      "accessed": "2026-11-09",
      "access_note": "Opened publisher model card; verified text-line-recognition role, English support and Apache-2.0 declaration. Published evaluation metrics not used as catalogue benchmark.",
      "license_status": "Publisher model card declares Apache-2.0; input-document rights remain separate.",
      "publication_date": null,
      "observation_date": "2026-11-09"
    },
    {
      "id": "SP-S8",
      "title": "PaddleOCR LICENSE",
      "publisher": "PaddlePaddle",
      "published": null,
      "updated": null,
      "url": "https://github.com/PaddlePaddle/PaddleOCR/blob/main/LICENSE",
      "accessed": "2026-11-09",
      "access_note": "Opened Apache License 2.0 and redistribution obligations including license copies, modified-file notices and applicable attribution/NOTICE material. No source code copied.",
      "license_status": "Apache-2.0 for covered repository software; other dependencies and datasets require their own review.",
      "publication_date": null,
      "observation_date": "2026-11-09"
    },
    {
      "id": "SP-S9",
      "title": "Runpod pricing page (fetch limitation)",
      "publisher": "Runpod",
      "published": null,
      "updated": null,
      "url": "https://www.runpod.io/pricing",
      "accessed": "2026-11-09",
      "access_note": "Attempted direct page open returned only an edge dispatch response rather than a readable price table. Not used as support for a rate; current documented configuration rate comes from SP-S1. Console quote not checked.",
      "license_status": "Not reproduced; no usable price evidence from this fetch.",
      "evidence_status": "attempted_unreadable",
      "publication_date": null,
      "observation_date": "2026-11-09"
    }
  ],
  "facts": [
    {
      "id": "SP-F1",
      "claim": "Runpod endpoint-settings documentation lists L4/A5000/3090 24-GB category at USD 0.00019 per second.",
      "source_ids": [
        "SP-S1"
      ],
      "evidence_type": "documented_configuration_price_not_account_quote"
    },
    {
      "id": "SP-F2",
      "claim": "Serverless bills worker start through full stop, rounded up to a second. Billed phases include cold start, execution and running idle-timeout wait; scaled-down Idle is not billed.",
      "source_ids": [
        "SP-S2",
        "SP-S3"
      ],
      "evidence_type": "current_billing_documentation"
    },
    {
      "id": "SP-F3",
      "claim": "Workers process queued jobs back to back; a new job arriving during their running waiting window can start without another cold start.",
      "source_ids": [
        "SP-S3"
      ],
      "evidence_type": "current_documentation"
    },
    {
      "id": "SP-F4",
      "claim": "Console and REST v2 endpoint defaults differ. Active workers, maximum workers, idle timeout and execution timeout are configurable.",
      "source_ids": [
        "SP-S1"
      ],
      "evidence_type": "current_documentation"
    },
    {
      "id": "SP-F5",
      "claim": "Async /run results are retained 30 minutes after completion; TTL independently covers the job lifespan including queueing and execution.",
      "source_ids": [
        "SP-S4"
      ],
      "evidence_type": "current_documentation"
    },
    {
      "id": "SP-F6",
      "claim": "PaddleOCR documents explicit version/model selection, local model paths and GPU execution. The named PP-OCRv5 server models perform detection and text-line recognition respectively.",
      "source_ids": [
        "SP-S5",
        "SP-S6",
        "SP-S7"
      ],
      "evidence_type": "developer_documentation"
    },
    {
      "id": "SP-F7",
      "claim": "PaddleOCR repository is Apache-2.0 licensed and selected publisher model cards both declare Apache-2.0.",
      "source_ids": [
        "SP-S6",
        "SP-S7",
        "SP-S8"
      ],
      "evidence_type": "published_software_and_model_license"
    }
  ],
  "inferences": [
    {
      "id": "SP-I1",
      "claim": "The documented rate equals USD 0.684 per worker-hour for the one-GPU modeled worker.",
      "basis_fact_ids": [
        "SP-F1"
      ],
      "label": "PCT arithmetic, not an account quote",
      "assumptions": [
        "One GPU in the documented 24-GB category; compute rate unchanged."
      ]
    },
    {
      "id": "SP-I2",
      "claim": "Hypothetical 100,000-page fragmented and well-fed schedules cost USD 85.50 and USD 38.475 in compute, saving USD 47.025 or 55%.",
      "basis_fact_ids": [
        "SP-F1",
        "SP-F2",
        "SP-F3"
      ],
      "label": "Hypothetical scheduling sensitivity model, not measured savings",
      "assumptions": [
        "Two processing seconds per page including in-worker input/output handling.",
        "Twenty billed startup seconds plus five billed tail seconds per activation.",
        "Fragmented schedule: 10,000 activations, 10 pages per activation. Well-fed schedule: 100 activations, 1,000 pages per activation.",
        "Same processing speed and output quality; no additional failures or active-worker charges.",
        "Whole-second timings avoid fractional activation rounding effects in this example."
      ]
    },
    {
      "id": "SP-I3",
      "claim": "Adding 2% repeated processing without extra activations gives USD 39.235. At 95,000 unique accepted pages the compute cost is about USD 0.413 per thousand accepted pages.",
      "basis_fact_ids": [
        "SP-F1",
        "SP-F2"
      ],
      "label": "Hypothetical retry and quality-denominator sensitivity",
      "assumptions": [
        "Extra processing fraction 0.02 and unique acceptance fraction 0.95 are invented sensitivity inputs.",
        "Activation count remains 100; more activations or longer runtime would increase cost."
      ]
    },
    {
      "id": "SP-I4",
      "claim": "A continuously supplied small-job queue can amortize startup while page-level durable commits limit duplicate work and result-loss exposure.",
      "basis_fact_ids": [
        "SP-F3",
        "SP-F5"
      ],
      "label": "Proposed implementation, not deployed or tested",
      "assumptions": [
        "Correct atomic persistence, idempotency keys and reconciliation.",
        "Actual resource availability and scaling permit sustained processing."
      ]
    }
  ],
  "unknowns": [
    "Actual OCR throughput, initialization time, hardware assignment, queue behavior, quality and memory requirements for this exact corpus.",
    "Account-specific price, quotas, current capacity and console rate; pricing-page extractor did not return a usable table.",
    "Actual number of billed activations, seconds lost to retries, and durability behavior.",
    "Total invoice including storage, external preparation and transfer costs elsewhere, taxes and review labor.",
    "Exact pinned software/model revisions, dependency compatibility and legal rights to a production corpus.",
    "End-to-end completion deadline; aggregate worker-seconds do not determine wall-clock latency."
  ],
  "correction_history": [],
  "license_status": "Original PCT editorial text; public reuse license not selected. Source documents, software, models and input-document rights remain separate. No source images, benchmark outputs or long quotations reproduced.",
  "public_url": null,
  "schema_version": "pct-research-item-1.0",
  "desk_extensions": {
    "id": "pct-2026-11-09-spotlight-runpod-ocr",
    "section": "Product spotlight",
    "publisher": "Peterson Compute Trading",
    "as_of_date": "2026-11-09",
    "status": "desk_research_with_audited_hypothetical_cost_model",
    "subject": "A Runpod Serverless queue using explicitly selected PaddleOCR PP-OCRv5 server models",
    "deck": "An OCR backfill shows how worker activations and expiring API results can matter more than a faster GPU.",
    "editorial_word_count": 1051,
    "reading_minutes": 4.8,
    "reading_wpm": 220,
    "publication_note": "Evergreen technical analysis using current primary documentation observed November 9, 2026. Not a launch report, purchase recommendation or actual workload benchmark.",
    "cost_model": {
      "currency": "USD",
      "as_of": "2026-11-09",
      "rate_source_id": "SP-S1",
      "pricing_mode": "Documented Runpod Serverless 24-GB category rate; zero active workers and one GPU per worker assumed; console quote unverified",
      "gpu_category": "L4, A5000, 3090; not a guarantee of a specific model",
      "rate_usd_per_second": 0.00019,
      "rate_usd_per_worker_hour": 0.684,
      "unique_input_pages": 100000,
      "hypothetical_processing_seconds_per_page": 2.0,
      "hypothetical_billed_startup_seconds_per_activation": 20.0,
      "explicit_billed_idle_tail_seconds_per_activation": 5.0,
      "processing_seconds_each_baseline": 200000,
      "fragmented": {
        "pages_per_activation": 10,
        "activations": 10000,
        "overhead_seconds": 250000,
        "total_billed_worker_seconds": 450000,
        "compute_usd": 85.5
      },
      "well_fed": {
        "pages_per_activation": 1000,
        "activations": 100,
        "overhead_seconds": 2500,
        "total_billed_worker_seconds": 202500,
        "compute_usd": 38.475
      },
      "hypothetical_savings_usd": 47.025,
      "hypothetical_savings_percent": 55.0,
      "sensitivity": {
        "extra_processing_fraction": 0.02,
        "activations_unchanged": 100,
        "total_billed_worker_seconds": 206500,
        "compute_usd": 39.235,
        "unique_accepted_pages": 95000,
        "compute_usd_per_thousand_accepted_pages": 0.413
      },
      "formula": "compute = rate * (input_pages * processing_seconds_per_page * (1 + repeated_processing_fraction) + activations * (billed_startup_seconds + billed_idle_tail_seconds))",
      "assumptions": [
        "All numerical workload timings and activation counts are hypothetical.",
        "Processing includes in-worker input handling and durable output writes; resource fit is unverified.",
        "No GPU throughput change between schedule cases.",
        "Model a single rate; no active-worker sales discount, capacity promise or invoice claim.",
        "One thousand pages per activation does not mean one thousand pages per request.",
        "Whole-second activation durations mean modeled totals need no additional billing rounding."
      ],
      "exclusions": [
        "Storage",
        "External PDF/page preparation",
        "External network-transfer charges",
        "Taxes",
        "Credits or negotiated discounts",
        "Human review and engineering labor",
        "Any extra startup or processing absent from the stated sensitivity cases"
      ]
    },
    "implementation_plan": {
      "status": "proposed_not_executed",
      "inputs": "Rights-cleared non-sensitive scanned catalogue pages, primarily English; exact model revisions and container digest to be pinned.",
      "steps": [
        "Establish representative human-checked sample and quality acceptance criteria.",
        "Select explicit PP-OCRv5 server detection and recognition models; verify GPU execution and actual device.",
        "Configure zero active workers, cap concurrency and explicitly set idle/execution/TTL policies; read settings back.",
        "Use small page jobs with a staged producer that keeps workers fed without exceeding job lifetimes.",
        "Persist page outputs under content/model/options identities using atomic commits and retry-safe checks before returning success.",
        "Separate output acceptance from API success; quarantine corrupt pages and cap attempts.",
        "Reconcile every source page to a durable result and audit billed activation/time counts."
      ],
      "no_transactions": true,
      "no_deployment": true,
      "no_performance_test": true
    },
    "verification": {
      "date": "2026-11-09",
      "public_primary_sources_opened": 8,
      "additional_primary_fetch_unreadable": 1,
      "arithmetic": "Decimal-based local assertions passed for hourly rate, scenario bills and sensitivity total. Only arithmetic was executed.",
      "benchmark": "No OCR or GPU benchmark run; no vendor performance metric presented as a result.",
      "cloud_actions": "None. No account changes, model downloads, uploads, purchases, deployments or credentials created.",
      "source_date_caution": "Runpod modification dates are explicitly displayed by its pages. Undated model cards and tutorial use null publication/update dates; access date is not release date.",
      "editorial_checks": [
        "Separated documentation facts from hypothetical inputs and design proposals.",
        "Used current documented configuration rate while disclosing pricing-page fetch limitation.",
        "Did not claim latest model, tested output quality or a guaranteed GPU assignment.",
        "Did not infer one cold start per page or request.",
        "Distinguished billed running wait from scaled-down Idle.",
        "Distinguished result retention from job TTL.",
        "Did not reuse older advertised active-worker discounts.",
        "Distinguished aggregate worker time from wall-clock deadline.",
        "Kept license rights separate from document rights."
      ]
    }
  },
  "public_projection": {
    "version": "1.0.0",
    "date": "2026-11-10",
    "changes": [
      "Internal workspace artifact paths omitted where present. Historical license/status fields retain original provenance; current public reuse policy is stated separately."
    ],
    "rights": "PCT reserves rights in original editorial content; third-party rights retained. No general source-data reuse license."
  }
}
