An open comment form receives automated submissions continuously, and the volume is not proportional to your traffic: a site nobody reads gets the same attention as a busy one, because the systems posting are not reading either.
Left alone, the comments table fills, moderation becomes unusable, and the site slowly acquires links it did not ask for.
Decide whether you want comments at all
The question worth asking first, because the answer is often no.
Comments are worth having when readers actually discuss things, and on a business site they frequently do not: leaving a form that produces nothing but spam and moderation work.
Turning them off entirely, or leaving them on for the handful of posts where discussion happens, removes the problem rather than managing it. Set the default under Settings, and enable per post where you want it.
Close them on old posts
Automated posting targets older content, because it is indexed and because nobody is watching it.
WordPress can close comments automatically after a number of days. Fourteen to thirty is a reasonable window: long enough for real discussion, short enough that the archive stops being a target.
This one setting removes a large share of the volume, and it costs almost nothing in genuine conversation.
Require approval for the first comment
The default arrangement, and the right one: a person's first comment is held, and once approved their later ones appear immediately.
That means nothing reaches your readers unreviewed, and regular commenters are not held up every time.
What matters is that you actually review the queue. A moderation queue nobody reads is a site with no comments and extra work.
An anti-spam service does most of the work
Content-based filtering compares submissions against patterns seen across many sites, which is far more effective than anything you can write yourself.
It is the single highest-value addition here, and the usual options have free tiers for non-commercial use.
Check the false-positive folder occasionally. A legitimate comment held as spam and never seen is a reader who concluded you ignored them.
A honeypot beats a CAPTCHA
A hidden field that humans never fill and automated systems do. Invisible to your readers, free, and it stops a large share.
A CAPTCHA also works, and it costs you real comments, some people cannot complete it and others will not bother. Use it only if the honeypot and the filter are not enough.
What does not work is a maths question. Those were solved long ago and only inconvenience people. How to Set Up Forms and Handle Submissions explains the same measures for contact forms.
Turn off the things spam is aiming at
Two settings that change the incentive rather than the volume.
The website field. Most automated comments exist to place a link. Removing the field removes the reason, and it removes nothing a genuine commenter needs.
Trackbacks and pingbacks. Almost entirely abused now, and rarely used legitimately. Turn them off in Settings for new posts, and disable them on existing ones in bulk.
Pingbacks also let your site be used to send requests elsewhere, so switching them off is worth doing on the security side as well. There is more on the interface behind them in Securing the WordPress REST API and XML-RPC.
What spam costs beyond the mess
Each submission runs PHP, writes to the database, and often sends you an email. On a busy target that is real load spent on nothing.
The comments table also grows, and a table with tens of thousands of spam rows slows every query that touches it: including the admin screens you use.
Empty the spam folder rather than letting it accumulate. Most filters keep entries for a period; there is no reason to keep them longer. How to Clean Up and Optimize the WordPress Database goes over reclaiming the space afterwards.
Turn off the email notifications
A site receiving hundreds of comments a day and emailing you about each one produces a mailbox that is useless and, on some accounts, an outbound sending problem.
Review the queue in the admin instead. If you want a signal, a daily summary is more useful than a message per comment.
If comments are already out of control
Bulk-delete the spam queue first, then empty trash, then optimize the table to reclaim the space.
Then apply the settings above before re-opening anything: close on old posts, remove the website field, disable pingbacks, add a filter and a honeypot.
Re-opening a site to comments without changing the settings produces the same result within weeks, which is the usual reason people conclude comment spam is unfixable.
Fake user accounts are a separate door with a simpler answer, and most sites collecting them never wanted registration at all. See How to Stop Spam Registrations and Fake Accounts.
Measure whether the change worked
Comment spam is fought with several measures at once and nobody records which one helped. Count the spam caught per week before making a change and again a fortnight afterwards. A count that has not moved means the measure is not doing anything and can be removed, which matters because each one costs something on every page load. The figure worth watching is not the volume caught but the volume reaching moderation, since that is the part that consumes somebody's attention rather than the server's.
Tell the two kinds of spam apart
Comments left by a person and comments generated in bulk arrive through different routes, and the volume tells you which you are dealing with. A steady trickle that gets past every filter is usually somebody paid to write plausible text, and no automated measure stops that. A flood arriving in minutes is automated, and it is stopped at the request rather than at the comment form. Reading the pattern before adding another plugin is what determines whether the answer is a filter, a rate limit or simply closing comments on older posts where almost all of it lands.