Every day, my server logs fill with thousands of automated vulnerability scans. The requests look dramatic:
/wp-admin/wp.php/111.php/code.php/.git/config/i.php/admin/api/.env/kal.php
What surprised me was not the volume. It was how little the server seemed to care. While I was watching this traffic, the CPU load did not visibly move.
That observation is real, but my original explanation was too absolute. Static delivery is not a magic shield, and a 404 is not free. What my setup does well is much narrower and more useful: it makes a large class of opportunistic probes very cheap because there is almost no application logic for them to reach.
These requests are probes, not proof of a compromise
It is tempting to look at paths like /wp-admin/wp.php or /111.php and call every request an “exploit.” That is not quite accurate. Most of what I see is automated probing: bots try common filenames and endpoints and wait to see what responds.
Some paths clearly target WordPress or PHP installations. Others, such as /.git/config and /api/.env, are attempts to find accidentally exposed configuration or secrets. /admin is even more generic; on some sites it is a legitimate route. A suspicious request tells me what the scanner is looking for, not that the vulnerability exists.
In my case, the important fact is architectural: the public site is pre-rendered static HTML generated with Next.js and served directly by Nginx.
Why this traffic is cheap on my stack
For the pages I am talking about here, there is no PHP runtime and no database sitting behind every request. Nginx serves files that already exist. If a scanner asks for /111.php and that file does not exist, there is no PHP application to boot, no WordPress code to execute, and no database query to run. The request simply misses and ends as a 404.
That changes the cost model. A dynamic application can turn a request into routing, framework startup, authentication checks, template rendering, database work, or calls to other services. My static path has far fewer moving parts. The server still has to accept the connection, process HTTP, look up the requested resource, write logs, and send a response, but the amount of application work is small.
I also use aggressive caching for the site, which helps normal static delivery. I would not credit caching for every random scanner miss, though. A request for a never-seen bogus path may still require normal Nginx request processing and a filesystem lookup before the 404 is returned.
The important correction: static does not mean “secure by definition”
This is the part I would phrase differently now. A static site removes many server-side application components from the request path, but it does not remove security work.
- An exposed file is still exposed. If
.git, an.envfile, a backup, or another secret is accidentally placed under a publicly served directory, Nginx can serve it just as efficiently as an HTML file unless the configuration prevents that. - Nginx, TLS, the operating system, and the network still exist. They remain part of the attack surface and need patching and sane configuration.
- Client-side code can still have vulnerabilities. Static HTML does not make JavaScript, browser-side authentication logic, or third-party scripts automatically safe.
- Resource exhaustion is still possible. Connections, bandwidth, TLS handshakes, worker capacity, log I/O, and disk space are finite. Enough traffic can hurt a static site too.
So the conclusion is not “these requests do not matter.” The better conclusion is: many application-specific probes have nothing useful to execute on this architecture.
Thousands of scans per day can sound scarier than they are
The logs make background Internet noise look intense because every failed probe is visible. But a daily count by itself does not tell me whether the traffic is operationally significant. Distribution matters: a few thousand requests spread across a day are very different from the same number arriving in a short burst.
CPU is also only one signal. In my case it stayed flat, which is useful evidence that this traffic was not creating meaningful compute pressure at the time I observed it. It does not prove there was no cost elsewhere. If I wanted to evaluate the impact properly, I would also look at request rate, bandwidth, active connections, Nginx worker utilization, response latency, log volume, and disk usage.
What I learned from watching the noise
The biggest lesson for me is that architecture can make whole categories of automated attacks irrelevant without needing a special rule for every scanner signature. A bot can spend all day looking for WordPress and PHP backdoors; if the public request path contains neither WordPress nor PHP, those particular probes have very little to work with.
But I do not want to confuse “irrelevant to this stack” with “harmless traffic.” My current mental checklist is simpler:
- Know which runtimes and services are actually reachable from the public request path.
- Make sure secrets, repository metadata, backups, and build artifacts are outside the public web root or explicitly blocked.
- Treat repeated 404 probes as normal Internet background noise unless other evidence suggests targeting or impact.
- Measure more than CPU before deciding that abusive traffic is free.
- Keep Nginx, the OS, TLS libraries, and dependencies patched even when the application itself is static.
What this experience does not prove
I did not run a controlled benchmark, and I did not test a denial-of-service attack. I only observed my production logs and the server load while thousands of scanner requests were arriving each day. That is enough for a practical conclusion about my setup, but not for a universal rule that static sites “win every time.”
What I can say confidently is more specific: on my Next.js static export served by Nginx, the scanner traffic I saw mostly collapsed into cheap file misses and 404s instead of reaching a PHP runtime or database-backed application. The CPU load stayed unchanged while I watched it.
That is the resilience advantage I actually care about. Fewer moving parts do not make a system invulnerable. They simply give random Internet noise fewer places to turn into real application work.