While organizing my WordPress blog recently, I noticed an issue again that had bothered me before: post IDs seem to grow a bit too fast.
This time, a new post happened to serve as a good sample.
The ID of the Chinese post is:
27442The ID of the corresponding English translation is:
27455There is a difference of 13 between the two.
This post only added 1 new tag; even counting the corresponding English tag, that is only 2. So from the start, I wondered what content was actually consuming these IDs.
Following this thread, I ended up not only disabling WordPress Revisions entirely but also cleaning up:
7085 revisions
2495 wp_sync_storage recordsI also confirmed that no orphaned postmeta were left behind.
This article documents the entire process.
1. First, confirm what exactly exists between 27442 and 27455
First, I queried this ID range in wp_posts:
wp eval --allow-root '
global $wpdb;
$rows = $wpdb->get_results("
SELECT
ID,
post_parent,
post_type,
post_status,
post_title,
post_date
FROM {$wpdb->posts}
WHERE ID BETWEEN 27442 AND 27455
ORDER BY ID
");
foreach ($rows as $row) {
printf(
"%s\t%s\t%s\t%s\t%s\t%s\n",
$row->ID,
$row->post_parent,
$row->post_type,
$row->post_status,
$row->post_title,
$row->post_date
);
}
'The main records found before cleanup were:
27442 Chinese post
27443 attachment
27444 attachment
27445 attachment
27446 attachment
27447 attachment
27448 attachment
27449 attachment
27450 attachment
27451 revision
27452 revision
27454 revision
27455 English postIn other words, the growth across these 13 IDs primarily came from:
| Type | Count |
|---|---|
| Image attachments | 8 |
| Revisions | 3 |
| Non-existent ID 27453 | 1 |
| English post | 1 |
This also confirmed one thing along the way:
Tags do not consume wp_posts.ID.
What actually causes wp_posts.ID to grow are posts, attachments, Revisions, and other data stored using the wp_posts table.
After cleaning up the Revisions, querying the same range again shows that the original 27451, 27452, and 27454 no longer exist.
![[Figure 1: Querying 27442–27455 again after cleaning Revisions; the original Revision records are gone]](https://media.shuijingwanwq.com/2026/09/1-14-1024x186.png)
It is worth noting that once records are deleted, the already used IDs will not be reused.
So even though 27451 has been deleted, future new posts will not start from this ID again.
2. Historical Revisions had accumulated to 7085
Since this single new post left behind 3 Revisions, I went ahead and counted the entire site:
wp eval --allow-root '
global $wpdb;
$count = (int) $wpdb->get_var(
"SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_type = '\''revision'\''"
);
echo "revision_count={$count}\n";
'Result:
revision_count=70857085 records.
My blog has been running for many years and is now bilingual in Chinese and English, so having a certain number of Revisions is normal.
But the problem is: I actually almost never use WordPress’s “restore to previous version” feature.
Since this feature goes unused for long periods, keeping thousands of historical versions—or even more in the future—has little practical value for me.
3. The vast majority of Revisions come from blog posts
To avoid simply treating all Revisions as post history, I also broke them down by parent content type:
wp eval --allow-root '
global $wpdb;
$rows = $wpdb->get_results("
SELECT
p.post_type AS parent_type,
COUNT(*) AS revision_count
FROM {$wpdb->posts} r
LEFT JOIN {$wpdb->posts} p
ON p.ID = r.post_parent
WHERE r.post_type = '\''revision'\''
GROUP BY p.post_type
ORDER BY revision_count DESC
");
foreach ($rows as $row) {
printf(
"%-25s %d\n",
$row->parent_type ?: "(missing parent)",
$row->revision_count
);
}
'Result:
post 7024
wp_template 19
page 13
wp_navigation 9
nimble_post_type 6
wp_template_part 6
wp_global_styles 3
custom_css 3
contx_post_type 2Out of the 7085 Revisions:
7024 come from postsAccounting for the vast majority.
Here, post includes both Chinese and English posts. Under Polylang, Chinese and English posts are essentially still two independent WordPress post.
The rest come from:
- Pages
- Templates
- Navigation
- Template parts
- Global styles
- Custom CSS
- Custom content types from some plugins
These quantities are all quite small.
Since I already decided not to use the Revision rollback feature going forward, I ultimately decided: delete all of them, rather than just deleting Revisions for blog posts.
4. Completely disabling WordPress Revisions
The original configuration was:
define( 'WP_POST_REVISIONS', 3 );Meaning each piece of content kept at most 3 Revisions.
I changed it directly to:
define( 'WP_POST_REVISIONS', false );![[Figure 2: Setting WP_POST_REVISIONS to false in wp-config.php]](https://media.shuijingwanwq.com/2026/09/2-14.png)
After making the change, I verified it via WP-CLI:
wp eval --allow-root '
echo "WP_POST_REVISIONS=";
var_export(WP_POST_REVISIONS);
echo PHP_EOL;
echo "AUTOSAVE_INTERVAL=" . AUTOSAVE_INTERVAL . PHP_EOL;
'Result:
WP_POST_REVISIONS=false
AUTOSAVE_INTERVAL=60There is an important distinction here:
Disabling Revisions does not mean disabling Autosave.
I did not separately configure AUTOSAVE_INTERVAL in wp-config.php, so WordPress still uses the default:
60 secondsThat means my current strategy is:
Do not keep historical Revisions long-term, but retain autosave during editing.
This suits my needs much better.
5. Back up the database before deleting
Because I was about to delete thousands of database records this time, I used UpdraftPlus to perform a database backup before the actual operation.
This only involved the database, so I only checked:
Include the database in the backup
There was no need to back up all uploaded files again.
![[Figure 3: Backing up the WordPress database separately with UpdraftPlus before cleanup]](https://media.shuijingwanwq.com/2026/09/3-16.png)
Although I was only deleting Revisions, given that the database has accumulated over many years, I still preferred to have a complete restore point first.
6. Cleaning up 7085 Revisions in batches
I did not directly execute something like:
DELETE FROM wp_posts WHERE post_type = 'revision';Instead, I continued processing through WordPress’s own deletion interface.
Deleting 500 records per batch:
while true; do
IDS=$(wp eval --allow-root '
global $wpdb;
$ids = $wpdb->get_col("
SELECT ID
FROM {$wpdb->posts}
WHERE post_type = '\''revision'\''
ORDER BY ID
LIMIT 500
");
echo implode(" ", $ids);
')
if [ -z "$IDS" ]; then
echo "全部 revisions 已清理完成"
break
fi
COUNT=$(echo "$IDS" | wc -w)
echo "本批删除 ${COUNT} 条 revision"
wp --allow-root post delete $IDS --force
doneOne benefit of handling it this way is that instead of simply deleting rows directly from wp_posts, it goes through WordPress’s deletion workflow.
Finally, I counted again:
revision_count=0The original:
7085has been completely cleaned up.
7. After cleaning Revisions, I discovered 2495 wp_sync_storage records
After clearing the Revisions, I recounted the various post_type in wp_posts:
attachment 9678
post 2999
wp_sync_storage 2495
series_grouping 48
nav_menu_item 34
wpcode 31
...At this point, a very conspicuous content type appeared:
wp_sync_storage 2495The count was surprisingly close to 2500.
I continued to inspect these records:
wp eval --allow-root '
global $wpdb;
$rows = $wpdb->get_results("
SELECT
post_status,
COUNT(*) AS count,
MIN(ID) AS min_id,
MAX(ID) AS max_id,
MIN(post_date) AS first_date,
MAX(post_date) AS last_date
FROM {$wpdb->posts}
WHERE post_type = '\''wp_sync_storage'\''
GROUP BY post_status
ORDER BY count DESC
");
foreach ($rows as $row) {
printf(
"status=%-15s count=%-6d ID=%d-%d date=%s -> %s\n",
$row->post_status,
$row->count,
$row->min_id,
$row->max_id,
$row->first_date,
$row->last_date
);
}
'Result:
status=publish
count=2495
ID=9453-23604
date=2026-04-09 11:16:45 -> 2026-08-07 19:15:33The last record stayed at:
2026-08-07 19:15:33And it is already September 6.
I vaguely remembered that I had previously turned off WordPress’s collaborative editing features, so I continued to verify the current status.
8. Confirming that the collaboration feature is indeed disabled
Execute:
wp eval --allow-root '
echo "wp_is_collaboration_enabled=";
var_export(
function_exists("wp_is_collaboration_enabled")
? wp_is_collaboration_enabled()
: "function_missing"
);
echo PHP_EOL;
echo "WP_ALLOW_COLLABORATION=";
if (defined("WP_ALLOW_COLLABORATION")) {
var_export(WP_ALLOW_COLLABORATION);
} else {
echo "(not defined)";
}
echo PHP_EOL;
echo "wp_collaboration_enabled option=";
var_export(get_option("wp_collaboration_enabled", "(not set)"));
echo PHP_EOL;
'Result:
wp_is_collaboration_enabled=false
WP_ALLOW_COLLABORATION=(not defined)
wp_collaboration_enabled option='(not set)'That means the actual current state is indeed:
wp_is_collaboration_enabled=falseCombined with:
The last wp_sync_storage record stayed at 2026-08-07It is basically confirmed that these 2495 records are historical data left over from when the related features were in use.
9. The 2495 wp_sync_storage records also had 2682 associated postmeta entries
Before actually deleting them, I checked the postmeta corresponding to these records:
wp eval --allow-root '
global $wpdb;
$count = (int) $wpdb->get_var("
SELECT COUNT(*)
FROM {$wpdb->postmeta} pm
INNER JOIN {$wpdb->posts} p
ON p.ID = pm.post_id
WHERE p.post_type = '\''wp_sync_storage'\''
");
echo "sync_storage_postmeta_count={$count}\n";
'Result:
sync_storage_postmeta_count=2682That is:
2495 wp_sync_storage records
2682 associated postmeta entriesSo here too, I did not directly use hard SQL deletes.
I continued to use:
wp post delete --forceto clean them up in batches.
10. Final cleanup results
After everything was complete, I put together several key states for final verification.
![[Figure 4: Final verification results after WordPress database cleanup]](https://media.shuijingwanwq.com/2026/09/4-11.png)
Result:
=== WordPress cleanup verification ===
WP_POST_REVISIONS=false
AUTOSAVE_INTERVAL=60
collaboration_enabled=false
revision_count=0
wp_sync_storage_count=0
orphan_postmeta_count=0The final state is now:
| Item | Result |
|---|---|
| WordPress Revisions | Disabled |
| Autosave | 60 seconds, retained |
| Historical Revisions | 7085 → 0 |
| Collaborative editing | Disabled |
wp_sync_storage | 2495 → 0 |
wp_sync_storage associated postmeta | Cleaned up with records |
Orphaned postmeta | 0 |
This time, just wp_posts deleted:
7085 + 2495 = 9580That is 9580 historical or internal records.
11. Why I ultimately chose to completely disable Revisions
Initially, I actually considered:
define( 'WP_POST_REVISIONS', 1 );Meaning, keeping at least the previous historical version.
But on second thought, I have used WordPress for many years and almost never actually used the Revision restore feature.
For me:
- Accidental exits during editing can be covered by Autosave;
- Once a post is officially published, I rarely need to revert to a version from hours or days ago;
- The database itself is also backed up regularly;
- The site already has a large number of posts;
- And it is now bilingual in Chinese and English, so the number of posts will continue to grow.
So I ultimately chose:
define( 'WP_POST_REVISIONS', false );Which better fits my actual usage.
Of course, this choice is not necessarily suitable for all websites.
For multi-user editing, newsrooms, or team collaboration sites, the value of Revisions is clearly higher.
But for a personal tech blog mainly maintained by myself, where I almost never roll back post history, disabling it is perfectly acceptable.
12. Do not reset AUTO_INCREMENT just to “reclaim IDs”
There is another point that easily causes confusion.
This time I deleted 9580 wp_posts records, but that does not mean the previously occupied IDs will be reused.
For example:
27451
27452
27454The original Revisions have been deleted, but these IDs will remain permanently vacant.
This is normal behavior.
Therefore, I did not do this:
Reset AUTO_INCREMENTNor did I try to rearrange post IDs.
A large number of internal WordPress relationships depend on IDs; manipulating them just to make the numbers “consecutive and pretty” has no practical meaning and may only increase risk.
13. The biggest takeaway from this investigation
At the very beginning, I simply noticed:
Chinese post ID: 27442
English post ID: 27455And felt the gap between the two IDs was a bit large.
Following it all the way down, I discovered two long-accumulated data sources:
7085 revisions
2495 wp_sync_storage recordsI also confirmed several other easily confused issues:
- Tags do not consume
wp_posts.ID - Image attachments consume IDs
- Revisions consume IDs
- Deleting Revisions does not reuse IDs
- Disabling Revisions does not mean disabling Autosave
- Chinese and English Polylang posts are still independent
postin themselves - Disabled collaboration features may still leave behind historical
wp_sync_storage - After deleting associated data, you should also check for orphaned
postmeta
Now:
revision_count=0
wp_sync_storage_count=0
orphan_postmeta_count=0The database state is much cleaner now.
When publishing new Chinese and English posts next, I can continue to observe the ID changes between them.
At that point, the remaining ID consumption should be easier to attribute to image attachments, autosaves, or other internal WordPress records.
需要长期技术维护或远程问题排查?
我是拥有 15+ 年经验的 PHP / Go 后端工程师,长期关注已有系统维护、Bug 修复、性能优化、服务器排查、WordPress 网站维护和小功能迭代。
如果你的项目遇到以下情况,可以先从一次小问题排查开始合作:
- ✅ PHP / Laravel / Yii2 老项目无人维护
- ✅ Go / Gin 后端接口需要排查或优化
- ✅ WordPress 网站访问慢、报错或插件冲突
- ✅ Nginx / MySQL / Redis / Linux 服务器异常
- ✅ CDN / Cloudflare / DNS / HTTPS 配置问题
- ✅ 需要长期远程技术支持或兼职维护
更多介绍请查看:关于我 & 合作
微信:13980074657
邮箱:shuijingwanwq@gmail.com
Telegram:@shuijingwan
GitHub:https://github.com/shuijingwan
