How we structured a vendor feed of 7M+ products into a staged pipeline - ingest, enrich, categorise, distribute - so a full refresh and a four-hourly price sync could run without manual intervention.
By Team WebSync · · 5 min read

A wholesale book distributor's catalog runs to over seven million titles. The requirement was to publish that catalog across several international marketplaces, keep inventory and pricing current, and remove discontinued items - continuously, and without someone babysitting it.
The interesting problem here isn't the volume. It's that the volume removes every shortcut you'd normally take.
The instinctive design is one job: read the feed, transform each row, push it to the marketplaces. At a few thousand records that works fine. At seven million it breaks in four separate ways.
The first stage reads the vendor CSV feed and does almost no thinking. It streams the file, validates that each row is structurally sound, and writes it into a staging database as close to raw as possible.
Resisting the urge to transform here is the whole point. Staging gives you a checkpoint: if enrichment logic changes next month, you re-run from staging instead of re-downloading seven million records. It also gives you somewhere to look when a downstream value seems wrong - you can compare against what the vendor actually sent.
Vendor data is never in your shape, and it's rarely complete. This stage normalises the raw rows into an internal product schema, then fills the gaps by calling a third-party bibliographic API for records missing key metadata.
Two rules kept this manageable. Enrichment is idempotent - running it twice on the same record produces the same result, so a partial run is safe to repeat. And enrichment failures are non-fatal: a product missing an optional field still moves forward, flagged, rather than blocking the batch.
Every marketplace wants products mapped into its own category tree, with its own required attributes. Doing that by hand across millions of titles isn't a staffing problem, it's an impossibility.
We ran this as a queue-backed processing stage: jobs distributed through a Redis-backed queue, with a Python service using sentence-embedding models to predict the right category and generate marketplace attributes from the product's text. Semantic similarity handles the long tail far better than keyword rules, which fall apart the moment a title doesn't contain the obvious word.
Queueing it separately matters as much as the model does. Categorisation is the slowest step, so it needs to scale horizontally - add workers, not patience - without holding up ingestion.
The final stage publishes processed products outward and keeps listings, inventory, pricing and deletions in sync. Each destination gets its own workers with its own rate limits and its own retry state, so one slow or unhappy marketplace degrades only its own channel.
The catalog runs on two different rhythms, and conflating them is a mistake we've seen elsewhere.
Most of what changes day to day is price and stock. Those are small, cheap updates. Rebuilding seven million full product records to propagate a price change wastes hours and adds risk for no benefit.
None of these are exotic techniques. The discipline is applying them from the start - because at this size, retrofitting them means rewriting the pipeline.
Split the pipeline into independently restartable stages - ingest, transform and enrich, categorise, distribute - each streaming data rather than holding it in memory, and each idempotent so a crash only costs the current stage. Run a full refresh on one schedule and a lighter, more frequent price and stock sync on another.
Turn a CSV or TSV table into JSON records, or flatten JSON back into a spreadsheet-ready table.
Convert a column of lines into a comma separated list, or split a delimited list back into one item per line.
Convert Unix epoch timestamps to readable dates and back, in local time or UTC.
Book a free consult - we'll scope it and give you a fixed price.