The wp_postmeta table in WordPress stores metadata or additional information about posts, pages, and custom post types. Over time, this table can become excessively large (“too large”) due to several reasons, which can lead to slower website performance and increased database size.
wp_postmeta
is a core WordPress table that stores “extra” information about every post, page, attachment, custom post type, etc. Each row is a simple key-value pair:
meta_id
– internal row IDpost_id
– which post this belongs tometa_key
– the name of the piece of datameta_value
– the actual data (can be up to 4 GB long in TEXT)
Why it can explode in size
- Plugins/themes write a lot of autogenerated keys (especially page-builder, SEO, WooCommerce, ACF, LMS, multilingual, analytics plugins).
- Example:
_elementor_css
,_yoast_wpseo_*
,_wc_session_*
,_wp_attachment_backup_sizes
…
- Example:
- Revisions – every revision duplicates most meta keys.
- Orphaned data – when you delete a post the meta is often left behind.
- Autoloaded options – some plugins incorrectly store transient/session data as post meta instead of using the options table.
- Long JSON blobs – page builders store full layouts or Base64-encoded images in
meta_value
.
Quick diagnosis
-- How big is it?
SELECT
ROUND(SUM(LENGTH(meta_value))/1024/1024, 2) AS GB
FROM wp_postmeta;
-- Top 20 largest keys
SELECT meta_key,
COUNT(*) AS rows,
ROUND(SUM(LENGTH(meta_value))/1024/1024, 2) AS MB
FROM wp_postmeta
GROUP BY meta_key
ORDER BY MB DESC
LIMIT 20;
Look for keys that are huge but not obviously useful to you.
Safe cleanup checklist
- Back up the database
mysqldump -uUSER -p DBNAME > pre-cleanup.sql
- Delete orphaned postmeta
sql
DELETE pm FROM wp_postmeta pm LEFT JOIN wp_posts p ON pm.post_id = p.ID WHERE p.ID IS NULL;
- Delete old revisions and their meta
(Use WP-CLI; cleans bothwp_posts
andwp_postmeta
)bashwp post delete $(wp post list --post_type='revision' --posts_per_page=-1 --format=ids) --force
- Drop known bloat keys you no longer need
Example:sqlDELETE FROM wp_postmeta WHERE meta_key IN ('_edit_last', '_edit_lock', '_wp_old_slug', '_wp_trash_meta_time');
- Shrink oversized keys
If_elementor_css
or_fl_builder_*
rows are tens of megabytes each, consider regenerating them later and removing the old ones:sqlDELETE FROM wp_postmeta WHERE meta_key = '_elementor_css';
- Run OPTIMIZE TABLE
After large deletions, reclaim space:sqlOPTIMIZE TABLE wp_postmeta;
Preventing future bloat
- Disable or limit post revisions in
wp-config.php
:
define('WP_POST_REVISIONS', 3);
- Use object cache so plugins stop storing transients as post meta.
- Periodically run
wp-cli
cleanup commands in cron. - Review new plugins for how much meta they create.
If the table is still massive after cleanup, you can also convert meta_value
from LONGTEXT to MEDIUMTEXT (if you are sure no value exceeds 16 MB) to shave a byte per row, but that’s rarely worth the risk.
Always test on a staging site first.
WordPress database optimization (don’t neglect) plugins & phpmyadmin manually