<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jonathan Ruimi</title>
    <description>The latest articles on DEV Community by Jonathan Ruimi (@jonathanruimi_vinyasa).</description>
    <link>https://dev.to/jonathanruimi_vinyasa</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4016640%2Fde87c2b4-2684-4552-bfbc-3e0086f09ccc.png</url>
      <title>DEV Community: Jonathan Ruimi</title>
      <link>https://dev.to/jonathanruimi_vinyasa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jonathanruimi_vinyasa"/>
    <language>en</language>
    <item>
      <title>Building an Auto-Parts Dropshipping Catalog: Lessons From 180k SKUs</title>
      <dc:creator>Jonathan Ruimi</dc:creator>
      <pubDate>Sun, 05 Jul 2026 19:55:14 +0000</pubDate>
      <link>https://dev.to/jonathanruimi_vinyasa/building-an-auto-parts-dropshipping-catalog-lessons-from-180k-skus-4a7</link>
      <guid>https://dev.to/jonathanruimi_vinyasa/building-an-auto-parts-dropshipping-catalog-lessons-from-180k-skus-4a7</guid>
      <description>&lt;p&gt;Aggregating auto-parts catalogs from several distributors sounds like a plumbing problem until you actually try it. Once you are ingesting feeds from four different suppliers, each with its own format, encoding, and idea of what a "product" is, the hard part stops being the download and becomes reconciliation. Here are the lessons that stuck after building a catalog that now spans more than 180,000 SKUs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Every supplier speaks a different dialect
&lt;/h2&gt;

&lt;p&gt;One supplier ships a 1.4M-row comma-separated file over SFTP with space-padded columns. Another gives you a UTF-8-BOM CSV plus a separate stock-only file that refreshes more often. A third has no feed at all and has to be scraped. A fourth hands you a Latin-1 snapshot with tri-state stock (Yes / Low / No) and no barcodes anywhere.&lt;/p&gt;

&lt;p&gt;The practical takeaway: normalize aggressively at the edge and keep the raw parse dumb. We stream each feed straight into an UNLOGGED staging table with &lt;code&gt;COPY&lt;/code&gt;, then do a single set-based upsert. Trying to be clever in the row parser (or pushing parsing into SQL) was consistently slower than a plain streaming parser feeding a bulk load, because the workload is I/O-bound, not CPU-bound.&lt;/p&gt;

&lt;h2&gt;
  
  
  Matching products across suppliers is the whole game
&lt;/h2&gt;

&lt;p&gt;The moment two suppliers sell the same part, you want to show cost, margin, and stock side by side. That requires deciding they &lt;em&gt;are&lt;/em&gt; the same part. GTIN/UPC is the strongest signal, but barcodes are messy: some are junk (too short), some suppliers omit them entirely, and manufacturer part numbers collide across brands.&lt;/p&gt;

&lt;p&gt;We settled on honest, explicit match tiers instead of one fuzzy score:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;exact&lt;/strong&gt; — both suppliers carry a valid GTIN-14 and they agree.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;verified&lt;/strong&gt; — a GTIN backfilled from an authoritative echo (a product page UPC).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;probable&lt;/strong&gt; — manufacturer part number plus brand agreement, no barcode.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;none&lt;/strong&gt; — single supplier, no cross-match.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Normalization (stripping, casing, check-digit handling) is the actual contract here, so it lives in exactly one place and is unit-tested. A backfilled or MPN-based link never gets to masquerade as a hard dual-barcode match. Keeping the confidence label honest is what keeps buyers from seeing two unrelated parts merged into one listing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dropship fulfilment needs a fast stock path
&lt;/h2&gt;

&lt;p&gt;Listing a part you cannot ship is worse than not listing it. A daily full feed is fine for pricing but too stale for inventory, so the stock-only refresh runs on a much tighter cadence and a 5-minute oversell guard pushes quantity zero to every sales channel the instant a supplier goes out of stock.&lt;/p&gt;

&lt;p&gt;If you are curious what this looks like as a live storefront, it powers &lt;a href="https://vinyasa-automotive.com" rel="noopener noreferrer"&gt;Vinyasa Automotive&lt;/a&gt;. The engineering lesson generalizes to any multi-source catalog: keep parsing dumb, make matching explicit and testable, and treat inventory freshness as a first-class latency problem.&lt;/p&gt;

</description>
      <category>ecommerce</category>
      <category>webdev</category>
      <category>database</category>
      <category>python</category>
    </item>
  </channel>
</rss>
