Skip to content 99% OFF 🎉 Anniversary Sale 99% OFF Shared Hosting Use Code HURRYUP Claim Offer 99% OFF Hosting
99% OFF Hosting — Code HURRYUP
Products
AI Website Builder New VPS Hosting Cloud Servers Web Hosting Dedicated Servers Domains
Company
About Documentation Support Center Contact Get Started Call +91 75795 45488
Login
Hosting Panel — cPanel & Billing Console Panel — VPS Management
ALL SYSTEMS OPERATIONAL
WordPress

WooCommerce Stock Not Updating? Fix Out-of-Sync Inventory

Getwebup 5 min read

A customer emails: the product page says "12 in stock," but the warehouse has zero. Or the opposite — WooCommerce is blocking checkout on an item that's actually sitting on the shelf. Stock drift like this doesn't mean WooCommerce is broken; it usually means one of five things is quietly out of sync. Here's how to find which one and fix it.

The symptom

Stock counts on the storefront don't match what's actually in WooCommerce > Products > Inventory, or don't match your warehouse/ERP system. You'll usually see one of these patterns:

  • Product shows "In stock" but customers get "not enough stock" at checkout.
  • Stock count changes on its own between page loads.
  • An import or sync tool overwrites the number back to something wrong every few hours.
  • Variations show different stock than the parent product, or don't update at all.

Why it happens

1. The product lookup table is stale

Since WooCommerce 3.6, stock and price data used for sorting/filtering on the frontend lives in a separate table, wp_wc_product_meta_lookup, not just in wp_postmeta. If a plugin, a direct SQL update, or a failed cron job writes to _stock in postmeta without updating the lookup table, the two go out of sync — and the storefront reads from the lookup table.

Check for drift directly:

SELECT p.ID, pm.meta_value AS postmeta_stock, l.stock_quantity AS lookup_stock
FROM wp_posts p
JOIN wp_postmeta pm ON pm.post_id = p.ID AND pm.meta_key = '_stock'
JOIN wp_wc_product_meta_lookup l ON l.product_id = p.ID
WHERE pm.meta_value != l.stock_quantity;

Any rows returned confirm the lookup table is the problem.

2. Page or object caching is serving an old number

If you're running LiteSpeed Cache, WP Rocket, or a full-page cache in front of WordPress, a cached product page can keep showing yesterday's stock count long after the database updated. This is worse on high-traffic stores where the cache TTL is generous to save server load.

3. "Hold stock" is quietly reserving inventory

WooCommerce has a setting under Settings > Products > Inventory > Hold stock (minutes) — default is 60. When a customer starts checkout, that stock is reserved even if they abandon the order without paying. On a store with a lot of drop-offs, this makes available stock look lower than it is until the hold expires and the order auto-cancels.

4. Two systems are fighting over the same field

If you sync stock from an ERP, a marketplace (Amazon/Flipkart), or a bulk import plugin like WP All Import, and it's writing on its own schedule, you can end up with a race: your storefront sells 3 units, then the next scheduled import overwrites the count back to the pre-sale number because the external system didn't know about the sale yet.

5. Variations aren't inheriting correctly

On a variable product, stock can be managed at the parent level or per-variation. If "Manage stock" is enabled on the parent but a variation has its own (stale) value, or vice versa, the storefront and the admin list can disagree about what's actually available.

How to fix it

Step 1 — Rebuild the lookup table

Go to WooCommerce > Status > Tools and run "Regenerate the product lookup table." This queues a background job (via Action Scheduler) that rebuilds wp_wc_product_meta_lookup from the source of truth in postmeta. On a large catalog this can take a while — check WooCommerce > Status > Scheduled Actions to confirm it's progressing and not stuck.

Step 2 — Exclude stock-sensitive pages from cache

At minimum, exclude the cart, checkout, and any AJAX add-to-cart endpoints from page caching. In LiteSpeed Cache: Cache > Excludes > Do Not Cache URIs, add:

/cart/*
/checkout/*
/?add-to-cart=*

If you're using an object cache (Redis/Memcached), also clear WooCommerce's own transients after any bulk stock update:

wp transient delete --all
wp cache flush

Step 3 — Tune hold stock minutes deliberately

Don't just disable this — it exists to stop overselling during checkout. Instead, set it to match your actual payment gateway timeout (for most Indian gateways, 10–15 minutes is enough) so abandoned carts release stock quickly instead of sitting reserved for a full hour.

Step 4 — Make one system the source of truth

If you're syncing with an external system, don't let both sides write freely. Either:

  • Push WooCommerce stock changes out via a webhook on woocommerce_reduce_order_stock immediately after a sale, so the external system always has the latest number, or
  • Pull from the external system on a short interval (5 minutes, not daily) and make sure the import respects orders placed since the last sync.

A daily cron import is almost always the root cause when merchants say "it keeps reverting."

Step 5 — Audit variation stock settings

In Products > Edit > Variations, check each variation's "Manage stock?" checkbox. If it's enabled per-variation, the parent-level stock number is ignored for that variation — update it individually, or disable per-variation management and manage stock centrally on the parent.

Prevention checklist

CausePrevention
Stale lookup tableRegenerate after any bulk SQL edit or plugin migration
Cache serving old stockExclude cart/checkout/add-to-cart URIs from page cache
Hold stock too longMatch hold-stock minutes to your gateway's payment window
Import overwrites salesSync every few minutes, not daily; push changes via webhook where possible
Variation mismatchStandardize on parent-level OR per-variation stock management, not both

Run through this list roughly in order — the lookup table and cache fixes solve the majority of "stock is just wrong" tickets, and the sync/variation fixes solve the "it keeps coming back" ones.

Frequently asked questions

Why does WooCommerce show stock that doesn't match my warehouse?

Usually the product lookup table (wp_wc_product_meta_lookup) is out of sync with postmeta, or a page cache is serving an old version of the product page. Regenerate the lookup table under WooCommerce > Status > Tools and exclude cart/checkout pages from caching.

Should I just disable 'Hold stock (minutes)'?

No — it prevents overselling during checkout. Instead, lower it to match your payment gateway's actual timeout window (often 10-15 minutes) so abandoned carts release stock faster instead of reserving it for a full hour by default.

Why does my stock count keep reverting after I fix it manually?

An external sync (ERP, marketplace, or import plugin) is overwriting it on a schedule that doesn't account for recent sales. Sync more frequently and, where possible, push stock changes out via webhook right after a sale instead of relying on a daily import.

How long does regenerating the product lookup table take?

It depends on catalog size — WooCommerce queues it through Action Scheduler as a background job. You can watch progress under WooCommerce > Status > Scheduled Actions; a few hundred products usually finishes in minutes, larger catalogs can take longer.

Why does a product variation show different stock than the parent product?

Stock can be managed at the parent level or per-variation, and mixing the two causes disagreements. Standardize on one approach: either enable 'Manage stock' only on the parent, or manage it individually on every variation.

#woocommerce #inventory-sync #stock-management #product-lookup-table #caching

Keep reading

Chat with Support