ConicPlex

Start Your Project

A server rack with tangled network cables next to a laptop showing an abstract purple data visualization, with a barcode scanner and shipping labels on the desk, representing a large WooCommerce product catalog sync

On this Page

How to Sync a Large WooCommerce Product Catalog without Crashing Your Site

A real 32,000-SKU WooCommerce sync project shows what actually keeps a large product catalog sync reliable: background job queues, idempotent matching, and dry-run testing before anything goes live.

Sajil Memon

August 24, 2026

A WooCommerce catalog past a few thousand SKUs will outgrow a cron-triggered import script, usually around the point stock counts and pricing need to update more than once a day. The fix isn’t a faster server. It’s moving the sync off WP-Cron entirely and onto a background job queue, most commonly Action Scheduler, with idempotent product matching and a dry-run mode before anything writes to the live catalog. That combination is what let us sync a 32,000+ SKU dropshipping catalog for a real client without the site falling over.

Why a Cron-Based Import Falls Apart Past a Few Thousand SKUs

WP-Cron isn’t a real cron job. It’s a PHP process that fires on page load, which means it only runs when someone visits the site, and it competes for the same PHP execution time and memory limit as everything else on that request. A sync script built to loop through a product feed and call wc_update_product in a single pass works fine in testing with 200 products. At 30,000, it hits the PHP max execution time before it finishes, and whatever wasn’t processed just doesn’t happen until the next run picks up wherever the last one silently stopped.

One WordPress.org support thread reporting on a real sync setup put throughput at roughly 1,000 products per hour on a standard configuration, which works out to more than a full day to sync 30,000 products in one pass (source). That’s not a server problem you fix by upgrading hosting. It’s a sign the sync is running the wrong way.

What Actually Handles a 30,000+ SKU Catalog Reliably?

Action Scheduler, the job queue library WooCommerce itself ships with, is the answer for almost every large-catalog sync we’ve built. Instead of one script trying to process a full feed inside a single page load, the sync breaks the feed into small batches, typically 25 to 100 products at a time, and schedules each batch as its own background action. Action Scheduler’s own maintainers are explicit that this queuing pattern is meant for exactly this kind of bulk operation, not for real-time single-record updates (source).

Each batch runs independently, with its own success or failure state logged in the actions table. If batch 340 out of 800 fails because the supplier API timed out, batches 1 through 339 are already committed and batch 341 still runs on schedule. Nothing has to restart from zero, and nothing silently drops. That’s the actual difference between a sync that scales and one that quietly falls behind: not raw speed, but the ability to fail on one record without taking down the other 29,999.

What This Looked Like on a Real 32,000-SKU Catalog

theFeinheit, a luxury dropshipping business, needed its WooCommerce catalog synced automatically from the Luxury Distribution supplier API, over 32,000 SKUs, with manual updates no longer able to keep pace. We built LD Woo Sync, a custom WooCommerce plugin that handles product creation, stock and pricing updates, image imports, and category and brand mapping through asynchronous processing with Action Scheduler. It shipped in four weeks. This is the kind of build our plugin development work centers on: not a generic sync tool, but one built around one supplier’s specific API shape and one store’s specific catalog structure.

The numbers matter here more than the description does. A naive full-catalog loop on this feed would have meant a multi-day sync window with no visibility into what had actually updated. The queued version processes updates continuously in the background, with each SKU’s last-synced timestamp and status logged, so a stalled batch is visible within minutes instead of discovered a day later when a customer orders something that’s actually out of stock.

Matching Products without Creating Duplicates

The part that breaks most homegrown sync scripts isn’t the queueing, it’s matching. A supplier feed identifies products by their own SKU or a supplier-side product ID. Your WooCommerce catalog needs to match that back to the correct existing product, or create one if it genuinely doesn’t exist yet, every single sync cycle, without ever creating a duplicate.

This gets harder with variable products. A single SKU on the supplier side might map to a WooCommerce product with six size and color variations, each of which needs its own stock count and price updated independently while staying attached to the same parent product. Get the matching logic wrong and a sync doesn’t fail loudly, it fails quietly: duplicate products stacking up in the catalog, or variations silently detaching from their parent and showing as out of stock everywhere.

The fix is a strict 1:1 matching key checked before every write, not after. LD Woo Sync matches on supplier SKU first, falls back to a stored mapping table for products where the supplier SKU has changed, and never creates a new product unless both of those checks come back empty. That mapping table is the part most quick-build sync plugins skip, and it’s the part that prevents the catalog from slowly filling with duplicates over months of automated runs.

Cron Import vs a Queued Sync: What Actually Changes

Factor Single-pass cron import Queued Action Scheduler sync
Behavior at 30,000+ SKUs Times out mid-run, partial updates Processes in small batches, no timeout
One record fails Can halt or corrupt the whole run Only that batch retries, rest continues
Visibility into failures Usually none until a customer notices Logged per batch, checkable within minutes
Server load pattern One large spike, risks memory limit Spread across many small background jobs
Safe to test before going live Rarely, changes write immediately Dry-run mode logs intended changes first

Dry-Run Mode and Retry Logic Are Not Optional

Every sync plugin we build for a catalog over a few thousand SKUs ships with a dry-run mode: a full pass through the feed that logs exactly what would change, price by price and SKU by SKU, without writing anything to the live catalog. Run it once before the sync goes live and once after any change to the supplier feed’s structure. It’s the only reliable way to catch a mapped field going wrong, a currency mismatch, or a supplier suddenly sending negative stock values, before those changes hit a customer-facing product page.

Retry handling matters just as much, and it’s easy to underbuild. A supplier API call that fails once because of a timeout shouldn’t mark that SKU as permanently out of sync. LD Woo Sync retries a failed batch a set number of times with backoff before flagging it for manual review, which in practice catches the vast majority of transient API failures without anyone needing to notice they happened. The failures that do reach a human are the ones that actually need a human, a genuinely malformed record or a supplier field that changed shape, not routine network noise.

This is also where a lot of off-the-shelf sync plugins fall short of what a specific business actually needs, the same gap we wrote about when comparing off-the-shelf WooCommerce extensions against a custom build: a generic plugin handles the common case well and has no good answer for the failure modes specific to your supplier’s API. Dry-run and retry logic are exactly the kind of edge-case handling that gets left out of a one-size-fits-all tool, and exactly what a custom WooCommerce build is for.

Category and Pricing Rules Belong in the Sync Layer, Not After It

Dynamic pricing and category or brand mapping are usually treated as a separate step after the sync, run by a second plugin or a manual pass. On a catalog this size, that’s an extra place for products to drift out of sync. LD Woo Sync applies pricing rules and category mapping as part of the same batch that updates stock, so a product’s price, category, and availability all update from the same data at the same moment, rather than getting updated in three passes that can each land at a slightly different time and briefly disagree with each other.

The same logic applies to any large integration, not just dropshipping. If your product data, shipping logic, or fulfillment status all come from different systems, the safest architecture keeps them updating together rather than layering separate sync jobs on top of each other and hoping they stay consistent. We ran into a related version of this problem building a custom shipping carrier integration, where the shipping rate logic had to stay in step with live inventory rather than working from a stale snapshot.

Frequently Asked Questions

Does Action Scheduler work without WP-Cron enabled?

Action Scheduler still relies on a trigger to process its queue, and by default that’s WP-Cron. On a low-traffic site, that means queued actions can sit unprocessed until a visitor loads a page. For any sync that needs to run reliably, disable WP-Cron’s page-load trigger and run it as a real server-side cron job instead, hitting wp-cron.php on a fixed schedule so the queue processes on time regardless of traffic.

How often should a large WooCommerce catalog sync run?

It depends on how fast the source data changes. A dropshipping catalog tied to a supplier’s live stock usually needs stock and price syncing every 15 to 30 minutes, while slower-changing data like descriptions or images can run once a day. Splitting sync frequency by field, rather than re-syncing everything on one schedule, cuts unnecessary load significantly.

Can I sync 30,000+ products without slowing down my site for customers?

Yes, as long as the sync runs through a background queue rather than a single blocking process. Action Scheduler’s batches run independently of the requests customers are making, so a sync in progress shouldn’t add load to a page a shopper is viewing. The risk is a poorly sized batch or an unthrottled retry loop hammering the database, which is a tuning problem, not a reason to avoid queuing in the first place.

What happens if the supplier API sends bad data mid-sync?

With dry-run and per-batch logging in place, a malformed record from the supplier only affects the batch it’s in. That batch fails, gets logged, and retries or gets flagged for review, while every other batch continues normally. Without that structure, a single bad record in a single-pass script can halt the entire run or, worse, write incorrect data before anyone notices.

Sources

Sajil Memon is a co-founder of ConicPlex and a Senior Full Stack Developer focused on backend work: Node.js, PHP, APIs, and the infrastructure decisions that determine whether a system holds up under real traffic. He’s spent years on the side of a project that doesn’t get demoed, the part that has to keep working after launch. He writes here about the technical tradeoffs in backend architecture, deployment, and data handling that only become obvious once something breaks in production.

Leave a Reply

Your email address will not be published. Required fields are marked *

Keep reading

News & Updates

A laptop glowing amber on a desk at night with a city skyline and light trails visible through the window, evoking a distributed network, with a keycard resting nearby

Cloudflare Discloses a Spectre Attack That Could Leak JWTs From Workers

Cloudflare disclosed a Spectre-class attack that leaked JWTs from co-located Workers at 12 bits a second, already mitigated through three…

Sameer Malek

August 24, 2026

News & Updates, Software

A dark minimalist workspace with a laptop open on a concrete desk and a small amber warning light glowing on a nearby wall-mounted network switch, evoking a critical security alert.

Next.js Security Release: Critical Patch Coming August 26

Next.js confirmed a critical security release for August 26, 2026, patching versions 16.3.3 and 15.5.24. Here’s what web teams should…

Sameer Malek

August 24, 2026

News & Updates

An open red cardboard box with faint smoke rising from it sits beside a laptop showing red terminal text, symbolizing a hidden malicious payload inside trojanized npm packages

14 Trojanized npm Packages Are Smuggling an AI-Powered Linux Backdoor

Trend Micro’s TrendAI research team disclosed on August 20, 2026 that 14 npm packages published under names like streak-metrics-math and…

Sajil Memon

August 23, 2026