To delete a single WordPress comment, hover it under Comments in the admin sidebar and click Trash, then empty the trash. That takes about four seconds. The reason you are reading this is almost certainly that you have more than one.
Comment deletion is one of those tasks that is trivial at n=1 and genuinely hard at n=40,000. The dashboard was designed for moderation, not for demolition, and it starts timing out somewhere around the ten-thousand mark. What follows is the whole ladder: the click path, the bulk path, the command-line path, and the database path, with a note on which one to reach for at which scale.
Table of contents
- Deleting one comment from the dashboard
- Bulk deletion in the admin
- The WP-CLI path, which is the right one at scale
- Going straight to the database
- Stopping the next 40,000
- Where the comment table sits in a managed setup
- How this fits the rest of the stack
- FAQ
Deleting one comment from the dashboard
Go to Comments in the admin sidebar. Hovering over a row reveals the action links: Approve, Reply, Quick Edit, Edit, Spam, Trash.
Trash is a soft delete. The comment moves to the Trash view and stays there until you empty it or until WordPress cleans it up automatically, which by default happens after 30 days.
Spam is not the same as Trash, and the difference matters. Marking a comment as spam feeds the anti-spam plugin’s classifier. Trashing it does not. If the comment is spam, mark it as spam; you are training the filter that has to catch the next thousand.
To delete permanently in one step, open the Trash view and use Delete Permanently. There is no undo past that point.
Bulk deletion in the admin
The Comments screen has a checkbox column and a Bulk actions dropdown. Select the rows, choose Move to Trash, apply. The screen defaults to 20 rows per page, which makes this painful at any real volume.
Raise the page size first. Open Screen Options at the top right and set the number of items per page to something larger — 200 is usually safe, 999 will work on a healthy install and time out on a struggling one.
Filter before you select. The status links across the top (All, Pending, Approved, Spam, Trash) narrow the set, and the search box matches comment content, author, and email. Deleting every comment containing a specific spam domain is a search followed by select-all followed by one bulk action.
The practical ceiling here is a few thousand rows. Past that, the POST request outlives the PHP execution limit and you get a blank page and a half-finished job.
The WP-CLI path, which is the right one at scale
If you have shell access, WP-CLI turns a twenty-minute clicking session into one line. It also has no timeout problem, because it is not running inside a web request.
# Count first. Always count first.
wp comment count
# Delete every comment currently marked as spam
wp comment delete $(wp comment list --status=spam --format=ids) --force
# Delete every comment on one post
wp comment delete $(wp comment list --post_id=42 --format=ids) --force
# Empty the trash
wp comment delete $(wp comment list --status=trash --format=ids) --force
The --force flag skips the trash and deletes outright. Without it you are only moving rows between statuses, which on a large table is the slow half of the work for none of the benefit.
wp comment list accepts the same query arguments as WP_Comment_Query, so you can filter on author_email, date_query, search, and the rest. That is usually enough to avoid ever touching SQL.
Going straight to the database
At six figures of spam, even WP-CLI’s per-comment delete hooks get expensive, because each one fires actions and updates counts. Direct SQL is the blunt instrument, and it is the correct one when the table is mostly garbage.
-- Look before you leap
SELECT comment_approved, COUNT(*)
FROM wp_comments
GROUP BY comment_approved;
-- Delete spam and its metadata
DELETE FROM wp_commentmeta
WHERE comment_id IN (
SELECT comment_ID FROM wp_comments WHERE comment_approved = 'spam'
);
DELETE FROM wp_comments WHERE comment_approved = 'spam';
Two things people forget. First, wp_commentmeta has orphan rows if you delete comments without it, and those rows accumulate silently forever. Delete metadata first, while the comment rows still exist to join against. Second, the per-post comment counts in wp_posts.comment_count are now wrong.
# Fix the counts after any direct-SQL delete
wp comment recount $(wp post list --format=ids)
Take a backup before running any of this. Not because the statements are exotic, but because a WHERE clause typed at speed on a Friday is how sites lose their entire comment history. A managed database with point-in-time backups turns this from a heart-stopping moment into an inconvenience.
Stopping the next 40,000
Deleting spam is symptom management. The settings that reduce the inflow live under Settings → Discussion, and most installs never touch them.
- Turn on Comment author must have a previously approved comment. This alone stops most drive-by spam from ever appearing.
- Set Automatically close comments on articles older than 30 days. Old posts attract the overwhelming majority of spam and receive almost no genuine discussion.
- Add the common spam trigger words to the disallowed list. Pharmaceutical and casino keywords do the heavy lifting.
- Disable comments entirely on pages and custom post types that will never need them. There is no reason for a contact page to accept comments.
If comments are not part of the product, turn them off in code and stop paying the moderation tax. A site that does not accept comments does not accumulate a comment table.
// In your theme's functions.php or a small mu-plugin
add_filter( 'comments_open', '__return_false', 20, 2 );
add_filter( 'pings_open', '__return_false', 20, 2 );
add_filter( 'comments_array', '__return_empty_array', 10, 2 );
Where the comment table sits in a managed setup
The awkward part of the database approach on most hosts is access. You need phpMyAdmin credentials or an SSH session and a mysql client, and neither is where you were working a minute ago.
Managed WordPress on RunxBuild puts a database browser in the dashboard next to the file manager, so the tables, rows, and an SQL console are one click from the site you are already looking at. The recount step still matters; the credential hunt does not.
For the WP-CLI path, the same dashboard exposes runtime logs, which is where you find out that the plugin generating half those comments is also throwing a PHP notice on every page load.
How this fits the rest of the stack
Comment cleanup is cheap in effort and expensive in attention, which is a bad combination — it is the kind of task that quietly eats an afternoon a month. Pick the tool that matches the row count, fix the discussion settings while you are in there, and back the database up before the DELETE. If you are pricing out a WordPress move and want to see what the database and the site cost as separate line items rather than one bundled number, the RunxBuild hosting calculator lays them out side by side.
Useful related references:
- Delete Directory Linux: rmdir, rm -rf, and find -delete
- MySQL Delete Database: DROP DATABASE and Recovery Considerations
- Remove Directory Linux Not Empty: rm -rf, find -delete, and Safety
- Services on RunxBuild
FAQ
Does trashing a WordPress comment delete it permanently?
No. Trash is a soft delete — the comment moves to the Trash view and remains in the database. WordPress purges trashed comments automatically after 30 days by default, or you can empty the trash manually with Delete Permanently.
How do I delete all WordPress comments at once?
With WP-CLI, run wp comment delete $(wp comment list --format=ids) --force. From the dashboard, raise the per-page limit in Screen Options, select all, and use the bulk action — though this will time out somewhere in the low thousands.
Why are my comment counts wrong after deleting from the database?
WordPress caches per-post comment counts in the wp_posts.comment_count column, and direct SQL does not update it. Run wp comment recount against your post IDs to rebuild them.
Should I mark spam as spam or just trash it?
Mark it as spam. Anti-spam plugins use those decisions as training signal, so trashing spam throws away information that would have helped catch the next batch.
Can I delete comments without a plugin?
Yes. The dashboard, WP-CLI, and direct SQL all handle deletion natively. Bulk-delete plugins are convenience wrappers around the same operations and add another plugin to maintain.