We measured Wordfence. The cost is not negligible.
We measured Wordfence 9.0.0 on a Raspberry Pi 5. On our test site, a registered install reduced homepage throughput by 23%; an unregistered install fetched no rules; and a directory-scoped Apache rule stopped an uploaded webshell from executing.
18 minute read
lordtime

Wordfence reports five million active WordPress installations. It promises a firewall, malware scanning and threat intelligence. The dashboard also shows attack counts and alerts, which makes it easy to mistake activity for protection.
We built a controlled WordPress site on a Raspberry Pi 5, running Apache, PHP-FPM and MariaDB, then installed Wordfence 9.0.0 and measured it. We tested response times under load, the request shapes its firewall blocked, and the difference a free licence key made.
Wordfence is a competent product with a strong vulnerability-research team. Our test also shows a clear boundary: it is primarily a request-inspecting virtual-patch feed, not a control that prevents every dangerous outcome. An uploaded PHP file still executed in our test until a directory-scoped Apache rule denied it.
These are our results, their limits, and the controls they support.
How we tested
A fresh WordPress 7.1 site with 61 posts and 37 comments, the default theme and no cache plugin, on a Raspberry Pi 5 running Debian 12: Apache 2.4.68, PHP 8.4.23 via PHP-FPM, MariaDB 10.11.18, opcache on. Wordfence 9.0.0 came straight from the plugin directory. We measured throughput with ab and used a small must-use plugin to record PHP time, memory, database queries and included files on every request.
Each scenario had 15 warm-up requests. The homepage figures below are ab -n 150 -c 1; the login figures are ab -n 100 -c 1. We ran the registered homepage case three times (9.40, 9.35 and 9.28 requests/sec). This is a controlled comparison of one uncached stack, not a prediction of the percentage cost on every host.
One control matters. After every Wordfence run we deactivated the plugin and measured the bare site again. It came back within 0.3% of where it started. The differences below are the plugin, not the Raspberry Pi warming up or drifting.
Everything here was run on that machine. Where a number comes from Wordfence’s own documentation or Cloudflare’s, it says so.
On our Pi 5, a registered install reduced homepage throughput by 23%
Here is the homepage, one request at a time. The registered row has the 688-rule set used for the firewall tests below. The Live Traffic row is an unregistered installation with all traffic logging enabled; it is shown separately because it has a distinct cost.
| Configuration | Requests/sec | Median page | Queries | Peak memory |
|---|---|---|---|---|
| No Wordfence | 12.11 | 81 ms | 22 | 8 MB |
| Deactivated again (control) | 12.07 | 81 ms | 22 | 8 MB |
| Unregistered, firewall blocking (0 rules) | 11.05 | 89 ms | 44 | 8 MB |
| Unregistered + Live Traffic logging | 9.66 | 103 ms | 47 | 8 MB |
| Registered, 688 rules | 9.34 | 106 ms | 41 | 12 MB |
From 12.11 to 9.34 requests a second is a 23% drop in this fixture. Peak memory went from 8 MB to 12 MB. The result is large enough that it is worth measuring on the actual hosting stack before assuming the impact is negligible.
Three separate registered runs gave 9.40, 9.35 and 9.28 requests a second. This is a stable measurement, not a bad afternoon.
The login page is where it hurts
| Configuration | Requests/sec | Median | Queries |
|---|---|---|---|
| No Wordfence | 47.80 | 20 ms | 7 |
| Unregistered | 24.97 | 39 ms | 37 |
| Registered, 688 rules | 17.72 | 56 ms | 33 |
The login page goes from 7 database queries to 33. Median response time rises from 20 ms to 56 ms (2.8×), while throughput falls 63%. Wordfence may stop some hostile requests before WordPress handles them, so this is a trade rather than a pure loss. The measurement does show that requests reaching PHP become more expensive for this server to absorb.
The hidden tax on every PHP file
On this PHP-FPM test host, Wordfence’s “Extended Protection” mode set auto_prepend_file through .user.ini before WordPress loads. That applies to every PHP file under that document-root directory, including files that have nothing to do with WordPress.
We put a one-line hello.php next to WordPress and measured it with and without the prepend, rules loaded:
| Configuration | Requests/sec |
|---|---|
| Without the firewall | 3,016 |
| With firewall + 688 rules | 55.7 |
In this document root, the prepend added 17.6 milliseconds to the one-line PHP response. A repeat with an empty ruleset added 0.77 ms, so about 96% of that added delay was rule evaluation. Against WordPress’s own 90 ms it is a fifth of the request and roughly explains the 23% fixture result. Against a small API endpoint or image handler sharing the folder, it was a 54-times slowdown for code that was not WordPress attack surface. If you use Extended Protection, move unrelated PHP outside that tree first.
Our unregistered test installation did not fetch rules or scan
This is a version- and configuration-specific result, but it is important because a newly installed plugin can look configured before it has downloaded any protection rules.
We installed Wordfence 9.0.0, activated it, and set the firewall to block. Then we sent six basic test request shapes:
/?s=<script>alert(1)</script> -> 200 served
/?p=1 UNION SELECT user_pass FROM wp_users -> 200 served
/?file=../../../../../../etc/passwd -> 200 served
/?t=<?php system('id'); ?> -> 200 served
/?q=' OR 1=1-- -> 200 served
User-Agent: sqlmap/1.7.2 -> 200 served
Nothing blocked. The plugin state on this installation showed why: wp-content/wflogs/rules.php was 0 bytes and the firewall had one placeholder rule. We called the plugin’s own rule-fetch routine directly; it returned false. This installation did not receive rules before it had a licence key.
The scanner was the same story. We started a real scan through the plugin’s own scan engine. It ran for two seconds and stopped:
Scan terminated with error: Wordfence API error:
Your site did not send an API key when contacting the Wordfence servers
On this fresh, unregistered installation, the firewall blocked none of the six test requests and the scanner did not run. It still reduced homepage throughput by 9% and added 129 file includes to every page. Registration is free, but verify that the rule file has arrived and that the scanner can start; do not assume activation alone did it.
Registration is free and needs only an email. We do not know how many active installations are registered, so this result is a configuration check, not a claim about the whole installed base.
What registration actually buys
We registered a free licence. rules.php went from 0 bytes to 908 KB, and the rule count from 1 to 688. Now the same attacks:
| Request shape | Result |
|---|---|
| XSS: <script>alert(1)</script> | blocked |
| XSS: <img src=x onerror=alert(1)> | blocked |
| SQLi: 1 UNION SELECT user_pass FROM wp_users | blocked |
| SQLi: time-based, ...SLEEP(5) | blocked |
| LFI: ../../../../etc/passwd | blocked |
| LFI: ../../wp-config.php | blocked |
| SQLi: ' OR 1=1-- | served |
| RCE marker: <?php system('id'); ?> | served |
| RCE: ;cat /etc/passwd | served |
| SSRF: http://169.254.169.254/latest/meta-data/ | served |
| PHP object injection | served |
| REST user enumeration | served |
| Webshell in a POST body | served |
| SQLi in a POST body (quote-space prefix) | served |
Six of fourteen. Read that fairly — several served strings are harmless unless a vulnerable application passes them to a dangerous operation, and a firewall that blocked every suspicious-looking string would break legitimate sites. A WAF’s job is not to match frightening text.
And two results are genuinely good, so we will say so plainly:
- POST bodies are inspected. The three payloads that blocked as a URL also blocked when sent in a POST body. The POST misses above are gaps in coverage, not a blind spot in parsing.
- The rules are not brittle. We tried case changes (
union select), inline comments (UNION/**/SELECT), doubled spaces,<ScRiPt>,<svg/onload=>,<body onload=>. Every variation was still blocked. That is better evasion resistance than most hand-written firewall rules manage.
The bypass
While testing variations we found a stable hole. Same parameter, same attack, same site:
x=1 UNION SELECT user_pass FROM wp_users -> 403 blocked
x=1' UNION SELECT 1,user_pass FROM wp_users-- -> 403 blocked
x=' UNION SELECT user_pass FROM wp_users -> 200 SERVED
x=a' UNION SELECT 1,user_pass FROM wp_users -> 200 SERVED
A value that starts with a quote followed by a space slips past the SQL-injection rule, while the same payload with a numeric or 1' prefix is caught. Five runs each: 200, 200, 200, 200, 200 and 403, 403, 403, 403, 403. Consistent, not a fluke.
A leading quote is a realistic way to break out of a quoted SQL string. This does not mean the test site, or another WordPress site, is exploitable. It shows a detection gap in a pattern-matching WAF and is a reason not to treat the firewall as the main defence against a vulnerable application.
The webshell Wordfence let run
The next test checks a boundary the firewall does not claim to cover: whether a PHP file already planted in a web-accessible upload directory can execute.
We put a webshell in the uploads folder — with all 688 rules loaded and the firewall blocking — and requested it:
$ cat wp-content/uploads/evil.php
<?php echo "EXEC uid="; echo trim(shell_exec("id -u")); ?>
$ curl https://site/wp-content/uploads/evil.php
EXEC uid=1000
It executed. Wordfence’s firewall inspects incoming requests for known exploit patterns; it is not an execution-control layer for a PHP file already on disk. Its scanner can detect suspicious files after a scan, but direct execution is a separate server-configuration concern.
Put a directory-scoped denial in the Apache virtual-host configuration. Adjust the filesystem path to the site; repeat it for every writable, web-accessible directory that must never run PHP:
<Directory "/var/www/site/wp-content/uploads">
AllowOverride None
<FilesMatch "\.(?i:php|phar|phtml|php[0-9]|inc)$">
Require all denied
</FilesMatch>
</Directory>
Measured:
uploaded evil.php, no rule -> 200 (executes, uid=1000)
same file, rule in place -> 403 (blocked)
legitimate image.gif -> 200 (still served)
WordPress index.php -> 200 (still served)
This stops direct HTTP execution of PHP-family files from that directory, including a file planted through an unknown upload flaw. It does not patch the flaw, protect other writable paths, or stop code execution through an already-vulnerable PHP endpoint. It is a high-value preventive layer, not a replacement for updates or a WAF.
The scanner, to be fair, is decent at what it does. Of four webshells we planted, it flagged three. But it missed evil.php — the one above — because it keys on the pattern of attacker input flowing into code execution ($_POST or $_REQUEST into eval or system), not on the mere presence of a dangerous function. A shell that runs a fixed command, or reads its instructions from a file instead of a request, walks past it. That is normal for signature scanners. It makes the scanner a good tripwire, not a guarantee — and a tripwire is detective, after the fact, where the Apache rule is preventive.
What you are actually paying for
We pulled apart all 688 rules to see what the product really is.
- 85% of them inspect the POST body — they match on submitted data, not on the URL.
- About 63% are patches for a specific, named, already-fixed plugin bug — “Abandoned Cart Lite for WooCommerce ≤ 5.14.2 — Authentication Bypass”, “Ultimate Member ≤ 2.1.11 — Unauthenticated Privilege Escalation”, and 428 more like them.
- Only 2% is non-WordPress noise (log4j, Fortinet, VMware — evaluated on your WordPress site on every request, for no reason).
The ruleset is primarily a virtual-patch feed: blocks for known holes in specific plugin versions. That is the central value of Premium’s real-time updates; the paid plans also add an IP blocklist, country blocking, audit retention and support.
Now put the price next to Wordfence’s own numbers. From their Q1 2026 threat report: 2,738 vulnerabilities published that quarter, and 22 firewall rules released. From their pricing page:
| Plan | Price/year | What it adds |
|---|---|---|
| Free | $0 | Rules delayed 30 days, scans every 3 days |
| Premium | $149 | Real-time rules, IP blocklist, country blocking |
| Care | $590 | They install and monitor it for you |
| Response | $1,250 | One-hour incident response, 24/7 |
The Q1 report recorded 22 new WAF rules in that quarter. It is one quarter, not a reliable annual forecast. Premium buys real-time access to new rules rather than the Free tier’s 30-day delay, alongside the other paid features in the table. Updating an affected plugin is still the complete fix once it is available; a virtual patch is most valuable in the interval before an update can be applied.
Give them their due: the research is real
It would be easy to leave it there, but that would be unfair, and it would miss where Wordfence is genuinely going. The vulnerability research behind that virtual-patch feed is the best-funded in the WordPress world, and it is good work.
Wordfence runs a bug bounty program that, by their own account, pays out mid-six figures a year to researchers. In March 2026 alone it processed 318 in-scope submissions and paid $62,174 in bounties. That money buys the disclosures that become the 430 virtual patches — and, crucially, the disclosures are public. When Wordfence finds and reports a hole in a plugin you run, the vendor ships a fix, and everyone benefits, whether or not they pay Wordfence a cent.
And they are pointing serious AI at it. Their PRISM project — an autonomous AI vulnerability hunter — found 202 vulnerabilities across WordPress plugins and themes in a single month, and in one case flagged a backdoored plugin within two hours of the malicious code being committed. By Wordfence’s own tracking, AI-assisted submissions to their bounty program went from 16% to about 66% in a few months. This is real capability, and it is accelerating.
Premium customers receive new firewall rules in real time; Free customers receive them after the documented 30-day delay. The research gets better and faster and more automated, but that delay remains part of the product split.
For a site owner who tracks the disclosures and can deploy updates promptly, the free information is valuable: it identifies a plugin to update and the update removes the underlying flaw. The real-time feed still has a meaningful role when an update cannot be deployed immediately or when a vulnerability is being actively exploited.
The practical free-tier lesson is simple: read the disclosures, keep plugins current and use the alerts as a prompt to act. That does not duplicate the real-time rule feed, but it removes the root cause when an update exists.
You already own most of the defence
Here is the replacement, category by category, using nothing but Apache configuration and Cloudflare’s free tier. The verdict is blunter than we expected.
| Wordfence category | Rules | Free replacement |
|---|---|---|
| File upload (the impact) | 75 | Better — server-config PHP-exec deny in write folders |
| Probing (readme, wp-config backups) | 3 | Yes — Apache file/path deny |
| Scanner user-agents | 1 | Yes — one Apache or Cloudflare rule |
| Brute force / login | 1+ | Crudely — Cloudflare free rate limit, or fail2ban, plus 2FA |
| Generic XSS / SQLi / log4j-class RCE | some | Partly — Cloudflare's free managed ruleset |
| Version-specific plugin patches (auth-bypass, priv-esc, etc.) | ~430 | No — needs Wordfence, a paid regex WAF, or the plugin update |
By rule count, the categories that free controls can directly replace or impact-mitigate account for roughly 15–20% of this ruleset. About 63% are version-specific virtual patches that Apache configuration and Cloudflare’s free tier cannot duplicate because they do not inspect the same request content. Counts are not a measure of risk: one rule can matter far more than another.
A couple of facts keep the free side honest. Cloudflare’s free tier gives you 5 custom rules but no regular expressions (regex starts on Business), one IP-based rate-limiting rule with a fixed 10-second period, and only the Free Managed Ruleset for high-impact, widely exploited vulnerabilities—not plugin-specific coverage. It can provide geo and IP controls, basic rate limiting and an outer managed-rules layer. It does not replicate a plugin-specific virtual-patch feed.
The one place free wins outright: brute-force bots
Brute-force and credential-stuffing are common threats for small WordPress sites, and an edge control has an architectural advantage here. In our test, wp-login.php had a 2.8× higher median response time with registered Wordfence. Requests blocked or challenged before origin do not incur that PHP cost, although a rate limit can allow some excess requests through before enforcement.
Cloudflare’s free tier offers three relevant controls at the edge, with limits:
- Bot Fight Mode issues computational challenges to traffic matching known-bot patterns. It protects the whole domain and can affect API or mobile-app traffic, so test it before enabling it.
- One rate-limiting rule can protect
POST /wp-login.phpby source IP. On Free it has a 10-second counting period, so it is one useful layer rather than a complete credential-stuffing defence. - A Managed Challenge custom rule can protect the login and
xmlrpc.phppaths. Test legitimate integrations such as remote publishing and Jetpack before enforcing it.
Those controls cover an important edge-facing part of login defence without adding a per-request PHP cost to requests that Cloudflare blocks or challenges. They are not feature-equivalent to Wordfence’s login-security features and do not replace its virtual patches.
The first row of the table remains high value: a server-configured denial of PHP execution in upload directories can prevent a planted upload from running, including when the delivery flaw is unknown. It complements, rather than replaces, request filtering and timely patching.
What we would actually do
Wordfence is not a con. Its research team is real, its vulnerability database is useful and free to query, and its scanner has a legitimate detective role. The choice is whether its real-time virtual patches and operational features justify their cost for the site’s update discipline, hosting stack and risk tolerance.
- If you install it, register it and verify it. On our fresh 9.0.0 installation, rules did not arrive and the scan did not run before registration. Check the rule file and start a scan rather than assuming activation was enough.
- Measure on your own stack. Our registered installation changed the homepage from 81 ms to 106 ms and reduced single-request throughput 23%. Your workload, caching and hardware may differ.
- Deny PHP execution in each writable web directory. Put a directory-scoped block in server configuration, with
AllowOverride Nonefor that directory. It prevents one dangerous outcome—direct execution of an uploaded PHP file—without replacing updates or request filtering. - Use Live Traffic deliberately. Our unregistered Live Traffic test was slower than the unregistered firewall-only case. Kinsta also disables Traffic Logging on its platform because of high IOPS; use security-events-only logging unless you need the fuller record.
- Do not buy Premium reflexively. Its real-time patches can matter while an update is unavailable or cannot be deployed. If you update promptly, its value may be lower; if you cannot, reducing that delay remains the first improvement.
- Update, use 2FA, use strong passwords and run fewer plugins. These controls reduce the underlying exposure whether or not you use Wordfence.
Security is configuration, maintenance and layered controls—not a subscription alone. Wordfence can be one layer, particularly during the window before a patch can be deployed. It should not substitute for updating plugins, hardening writable directories or protecting login endpoints. We wrote separately about what a real security review looks at.
Questions people ask
So is Wordfence bad?
No. It is a competent security product with useful research, a virtual-patch feed and a scanner. The question is whether its real-time protection and operational features justify the measured cost on your own stack.
Does the free version really do nothing?
Our fresh Wordfence 9.0.0 installation had no downloaded rules and would not scan until it received a free licence key. Do not generalise that test to every installation; register it, then verify the rule file and scanner yourself.
Is the 23% slowdown real on a normal server?
It is real on our uncached Raspberry Pi 5 test site: 12.11 to 9.34 requests a second, with a 81 ms to 106 ms median page time. Measure your own workload and hosting stack before making a capacity decision.
Can Cloudflare's free tier replace it?
Partly. It provides limited edge rate limiting, custom rules and a Free Managed Ruleset, but not regular expressions or WordPress-plugin-specific virtual patches. It is a useful outer layer, not a full replacement.
What is the single most useful thing I can do for free?
Deny PHP execution in every writable, web-accessible directory using server configuration. Scope the block to the directory, set AllowOverride None there, and verify that uploads are blocked while WordPress itself still runs. It complements patching; it does not replace it.
Should I pay for Premium?
Consider Premium when you need real-time virtual patches during the period before an update can be deployed, or value its other paid features and support. If you patch promptly, measure its cost and decide whether that remaining gap justifies the subscription.
Sources
- Wordfence — WordPress Plugin Directory — Plugin listing, active-install count and release information. Read 22 August 2026.
- Wordfence pricing — Free, Premium ($149), Care ($590) and Response ($1,250), all per site; Free-tier rules are delayed 30 days. Read 22 August 2026.
- Wordfence Q1 2026 threat report — 2,738 vulnerabilities published and 22 WAF rules released in Q1 2026. Wordfence's own figures; one quarter is not an annual forecast.
- The increasing role of AI in vulnerability research — Wordfence — Wordfence's bug bounty pays "mid-six figures per year"; AI-assisted submissions rose from 16% to ~66%. Read 22 August 2026.
- Cloudflare Bot Fight Mode — A free, domain-wide bot defence that may affect API or mobile-app traffic and cannot be bypassed with custom rules.
- Cloudflare WAF custom rules — availability — Free: 5 rules and no regex. Regex requires the Business plan. Read 22 August 2026.
- Cloudflare rate-limiting rules — availability — Free: one IP-based rule and a 10-second counting period; enforcement can allow some excess requests through before mitigation.
- Cloudflare WAF managed rules — availability — Free plan gets the Free Managed Ruleset; the wider Cloudflare Managed and OWASP rulesets need Pro or above.
- Kinsta — banned and incompatible plugins — Kinsta supports Wordfence but disables Traffic Logging because it causes high IOPS.
- Apache mod_authz_core — Require directive — Access-control directive used in the directory-scoped upload-execution block.
Paying for a security plugin that might be doing nothing?
Send us what you run and what you pay for it. We will measure what it actually costs you, test what it actually blocks, and tell you what a free configuration would cover instead. The same way we tested Wordfence here.