Where Are WooCommerce Products Stored In The WordPress Database?

Where is woocommerce storing product data in the database

TL;DR: WooCommerce stores all products as custom post types in wp_posts, with attributes and meta (price, SKU, stock) in wp_postmeta. Categories, tags, and product attributes live in the wp_terms family of tables. Visibility and product type flags are stored as post meta keys.

Sometimes you add new WooCommerce products on your staging site and just want to add those new products to the live site without affecting other data like orders and transactions. Understanding which database tables WooCommerce uses makes that transfer safe and predictable — you copy only the rows that hold product data and leave order rows untouched.

This article maps every table that holds WooCommerce product data, explains the columns that matter day-to-day, and includes copy-paste SQL for the most common lookups. If you have ever wondered why a product change on staging did not carry over after a partial push, the answer is almost always a missed table.

Why Knowing Product Storage Locations Matters

Understanding where WooCommerce products are stored is useful in several practical situations:

  • Custom Queries: Retrieving product data using SQL queries for reporting or custom functionality.
  • Database Optimization: Cleaning up unnecessary data to improve performance.
  • Troubleshooting Issues: Resolving problems with missing or incorrect product details.
  • Data Migration: Moving products between different WordPress installations without touching order or customer data.
  • Debugging missing attributes: When a product’s color or size does not appear on the front end, knowing which taxonomy table to inspect saves significant debugging time.

Key Tables Storing WooCommerce Product Data

WooCommerce primarily stores product data in two tables:

  • wp_posts – Contains product entries with a post type of product or product_variation.
Find WooCommerce Product Details using wp_posts Table
  • wp_postmeta – Stores additional metadata for each product, linked via post_id (product ID).
Find Product detail using wp_postmeta Table

Table overview

The following table maps each core storage area to what it holds and the columns most often needed in queries or migrations:

Table What it stores Key columns
wp_posts Every product and variation as a row ID, post_title, post_type = 'product', post_status, post_modified
wp_postmeta Price, SKU, stock, weight, dimensions — one row per key per product post_id, meta_key, meta_value
wp_terms Category and tag names, attribute labels term_id, name, slug
wp_term_taxonomy Declares whether a term is a category, tag, or attribute term_taxonomy_id, taxonomy, description
wp_term_relationships Links each product (object_id) to its terms object_id, term_taxonomy_id
wp_termmeta Extra metadata attached to terms term_id, meta_key, meta_value
wp_woocommerce_attribute_taxonomies Global attribute definitions (e.g., Color, Size) attribute_id, attribute_name, attribute_type

Worked example: retrieve a product with its price and stock level

The query below joins wp_posts to wp_postmeta to pull the price and stock status for a single product. Replace 12345 with the product’s ID value from wp_posts:

SELECT
  p.ID,
  p.post_title,
  MAX(CASE WHEN pm.meta_key = '_price'        THEN pm.meta_value END) AS price,
  MAX(CASE WHEN pm.meta_key = '_stock_status' THEN pm.meta_value END) AS stock_status
FROM wp_posts p
JOIN wp_postmeta pm ON pm.post_id = p.ID
WHERE p.ID = 12345
  AND p.post_type = 'product'
GROUP BY p.ID, p.post_title;

In our testing with WooCommerce 9.x, the _price meta key is always populated even when the product has no explicit sale price — it mirrors the regular price. From WP STAGING support experience, the most common source of confusion is the assumption that WooCommerce uses its own entirely separate tables for products. It does not: it extends wp_posts through the custom post type system, so every product is a post row with a post_type value of product.

Quick Reference: Find What You Need

Use this table to go directly to the right table and column without reading the full schema documentation:

I want to … Table Filter
List all products wp_posts post_type = 'product'
Find a product’s price wp_postmeta meta_key = '_price'
Find a product’s sale price wp_postmeta meta_key = '_sale_price'
Check stock status wp_postmeta meta_key = '_stock_status'
Find a product’s SKU wp_postmeta meta_key = '_sku'
List product categories for a product wp_term_relationshipswp_term_taxonomywp_terms taxonomy = 'product_cat'
Check if a product is featured wp_term_relationships term slug featured in product_visibility
Find all variations of a product wp_posts post_type = 'product_variation' and post_parent = <product ID>

Tables Storing Product Categories, Tags, and Attributes

In addition to the core product tables, WooCommerce uses several taxonomy-related tables to manage product types, categories, subcategories, tags, and attributes:

  • wp_terms – Stores product categories and tags.
  • wp_termmeta – Stores metadata for product terms.
  • wp_term_taxonomy – Defines the taxonomy type (e.g., category, tag, attribute).
  • wp_term_relationships – Links products to their categories and attributes.
  • wp_woocommerce_termmeta – Stores additional WooCommerce-specific term data.
  • wp_woocommerce_attribute_taxonomies – Manages product attributes specifically.

When a product attribute does not appear correctly on the front end, check both wp_term_relationships (to confirm the product is linked to the right term) and wp_term_taxonomy (to confirm the taxonomy column matches the expected attribute slug).

WooCommerce Product Types and Visibility

WooCommerce handles different product types using the product_type taxonomy, which includes the following default options:

  • simple – A standard product with no variations.
  • grouped – A collection of related products.
  • variable – A product with multiple variations.
  • external – A product sold on an external website.

Since WooCommerce 3+, a new taxonomy called product_visibility manages:

  • Search and catalog visibility – Uses terms like exclude-from-search and exclude-from-catalog.
  • Featured products – Identified using the term featured.
  • Stock status – Uses outofstock to indicate unavailable products.
  • Ratings – Terms like rated-1 to rated-5 categorize product reviews.

Each product attribute is stored as a custom taxonomy, making it easy to categorize and filter products dynamically.

Common Operations

Bulk-deleting products safely by post type

To remove all products from a test or seeded database, target wp_posts by post type and clean up the related postmeta rows in the same operation:

-- Remove postmeta first (avoids orphaned rows)
DELETE pm
FROM wp_postmeta pm
JOIN wp_posts p ON p.ID = pm.post_id
WHERE p.post_type IN ('product', 'product_variation');

-- Then remove the product and variation rows
DELETE FROM wp_posts
WHERE post_type IN ('product', 'product_variation');

⚠️ Always run this against a staging database first. This permanently deletes all product rows and their meta. It does not touch order tables.

Migrating WooCommerce products from staging to live

When pushing only products — not orders — from a staging environment, the minimum set of tables to include is:

  • wp_posts — rows where post_type IN ('product', 'product_variation')
  • wp_postmeta — rows where post_id belongs to a product or variation
  • wp_terms, wp_termmeta, wp_term_taxonomy, wp_term_relationships — rows tied to product_cat, product_tag, and custom attribute taxonomies
  • wp_woocommerce_attribute_taxonomies — if you have custom global attribute definitions on the source environment

Leave all wp_woocommerce_order* and wp_wc_order* tables out of the push — including them would overwrite live customer orders with staging data.

Resetting test product data

After seeding a staging store with test products, reset to a clean state by deleting rows where post_type = 'product' using the query above. WP STAGING’s selective push also lets you define which post types to include or exclude, so you can push real products from staging to live without writing raw SQL.

Best Practices for Copying Product Data to a Live Site

When moving new products from a staging site to a live site, protect orders and customer data by following these steps:

  1. Back up the live database. Export a full snapshot before any push so you can restore immediately if something goes wrong.
  2. Copy only relevant tables. Focus on wp_posts, wp_postmeta, and taxonomy-related tables.
  3. Exclude order-related tables. Avoid tables prefixed with wp_woocommerce_ unless you specifically intend to migrate order data.
  4. Use a migration tool. Plugins like WP STAGING handle selective table pushes automatically, including serialised-data search-and-replace for URL differences between environments.
  5. Verify on staging first. Run a read-only query against the staging database to confirm the expected product row counts before initiating the push.

Conclusion

WooCommerce products are stored mainly in wp_posts and wp_postmeta, while categories, attributes, and visibility settings are managed in related taxonomy tables. Understanding this structure helps in safely migrating product data without affecting live store operations.

References:

Related Articles

Rene Hermenau

Author: Rene Hermenau

About the author: René Hermenau is the founder of WP STAGING. He works on WordPress backups, staging, migrations, database handling, and safe deployment workflows.