Accidentally permanently deleted a post? If you acted within 30 days and your host hasn’t optimized the database, there’s a good chance it’s still recoverable.
How WordPress “Deletes” Posts:
When you empty trash, WordPress doesn’t immediately erase the post row. It updates the post_status to ‘trash’ first, then later to ‘inherit’ (for revisions). The actual deletion happens during database optimization or after 30 days.
Quick Check via phpMyAdmin:
SELECT * FROM wp_posts
WHERE post_title LIKE '%keyword from your post%'
AND post_status IN ('trash', 'inherit', 'auto-draft')
ORDER BY post_modified DESC
LIMIT 20;
Replace ‘keyword from your post’ with something you remember from the title or content.
Recovery Steps:
If you found your post in the results:
UPDATE wp_posts
SET post_status = 'draft'
WHERE ID = YOUR_POST_ID;
Your post is now in Drafts! Go to WordPress admin → Posts → Drafts to find it.
Advanced: Recover from Binary Logs (MySQL):
If your host enables binary logging, you can recover even truly deleted data:
mysqlbinlog /var/lib/mysql/mysql-bin.000001 | grep -A 50 "INSERT INTO wp_posts"
This shows all INSERT statements, including your deleted post’s original data. You’ll need server SSH access and MySQL permissions.
Why This Works:
Databases use “lazy deletion” for performance. Marking rows as deleted (via status flags) is faster than removing them entirely. The physical deletion happens during OPTIMIZE TABLE operations:
OPTIMIZE TABLE wp_posts; # Don't run this if trying to recover!
Prevention for Future:
Install this mu-plugin (mu-plugins folder, auto-active):
<?php
// Prevent permanent deletion
add_action('wp_trash_post', function($post_id) {
update_post_meta($post_id, '_deleted_date', current_time('mysql'));
});
This stamps every trashed post with deletion timestamp in post meta. Even if the post row disappears, postmeta often survives longer and helps locate backup points.
