Website Under a Traffic Flood or DDoS Attack: What to Do
Your site is buried under traffic. Tell an attack from a viral spike, put Cloudflare in front, challenge or rate limit the hot paths, and lock your origin so it cannot be bypassed.
Pages take several seconds to load, or the admin area crawls.
Do this first
Diagnose it
Slow has two separate halves: the server taking a long time to start sending the page, and the browser taking a long time to show it. Fixes for one do nothing for the other, so find out which half you have first.
Google judges speed on real visitor data at the 75th percentile, collected over a rolling 28 days. These are the published thresholds:
| Metric | Good | Poor | What it measures |
|---|---|---|---|
| Largest Contentful Paint (LCP) | 2.5 s or less | over 4 s | When the main content appears. |
| Interaction to Next Paint (INP) | 200 ms or less | over 500 ms | How quickly the page responds to taps and clicks. |
| Cumulative Layout Shift (CLS) | 0.1 or less | over 0.25 | How much the layout jumps around. |
| Time to First Byte (TTFB) | 0.8 s or less | over 1.8 s | How long the server takes to start responding. Not a Core Web Vital, but it sits under all of them. |
Other forms it takes: PageSpeed Insights flags the server response time; the Search Console Core Web Vitals report lists URLs as "Poor"; the admin area takes several seconds per click while the front end is fine; or the site is fast most of the day and crawls at certain hours.
1. Split the time into phases.
curl -o /dev/null -s -w 'dns %{time_namelookup} connect %{time_connect} tls %{time_appconnect} ttfb %{time_starttransfer} total %{time_total}\n' https://example.com/
Run it three times on your own computer’s terminal, replacing example.com with your domain. Times are in seconds. Good: ttfb under 0.8, and usually under 0.3 for a cached page. Bad: ttfb over 1 second every time means the server is the bottleneck. If the first run is slow and the next two are fast, the cache was cold and is working.
2. Check whether the page cache is used.
curl -sI https://example.com/ | grep -iE 'cache|age:|x-litespeed|cf-cache-status'
Run it on your own computer, twice. Good: HIT on the second run, or an age header above 0. Bad: MISS or BYPASS every time. On Cloudflare, cf-cache-status: DYNAMIC means it is not caching the HTML at all, which is its default.
3. Measure autoloaded options.
wp db query "SELECT ROUND(SUM(LENGTH(option_value))/1024) AS autoload_kb FROM $(wp db prefix)options WHERE autoload IN ('yes','on','auto','auto-on')"
Run it in an SSH terminal inside the site’s folder (the one with wp-config.php). $(wp db prefix) fills in your table prefix automatically. The four autoload values cover old and new WordPress versions. WordPress loads all of these on every request. Site Health warns above 800 KB. Several megabytes slows every page, admin included.
4. Profile where WordPress spends its time.
wp package install wp-cli/profile-command
wp profile stage --url=https://example.com/SLOW_PAGE/
wp profile hook --all --spotlight --url=https://example.com/SLOW_PAGE/
Run these in the same SSH terminal. SLOW_PAGE is the path of a page that loads slowly. The first line installs the profiler once. stage splits the time into bootstrap, main query and template. hook --all --spotlight lists only the slowest callbacks, with the plugin or theme file each one belongs to.
MISS or BYPASS on every request. Common bypass triggers are a cookie set on every visit, query strings from ad links, and logged-in users. Fix: turn on server or plugin page caching and find what sets the cookie.PREFIX_actionscheduler_actions or PREFIX_options holding millions of rows. Fix: clear old scheduled-action logs, expired transients and leftovers from removed plugins, after a backup.wp-login.php, xmlrpc.php, search, or filter URLs with endless parameter combinations. Fix: rate-limit or block at the firewall or CDN, and disable XML-RPC if nothing uses it.http_request time. A license check or API call to a service that is down is typical. Fix: remove or fix the plugin, or cache the result.php -v shows a release past end of life (8.1 and older lost security support by the end of 2025). Fix: move to a supported PHP version after testing on staging, and ask your host to confirm OPcache is on.define( 'DISABLE_WP_CRON', true ); to wp-config.php and run cron from a real server cron job every 5 minutes.pm.max_children warnings, CPU throttling or resource-limit hits on your account in that window.Did this fix it?
Still stuck? Start again from what you can see in the Emergency Room.
The full fix
Your site is buried under traffic. Tell an attack from a viral spike, put Cloudflare in front, challenge or rate limit the hot paths, and lock your origin so it cannot be bypassed.
Gray squares in the Media Library, soft or pixelated images, crops that do not fit, or a grid that takes ages to load. Find which image size is wrong and regenerate safely.
PHP stopped a request because it hit the memory or time limit. Read the exact error, check the real limits, raise them in the right place for your panel, then find what keeps hitting them.
Search Console or PageSpeed Insights says your LCP is too slow. Find the LCP element, see which of its four parts is slow, and fix the hero image, server time or render blocking.
Content jumps as the page loads and Search Console reports a CLS issue. Find the element that moves and why, then reserve space for images, embeds, ads, fonts and banners.
Search the field manual
Or jump straight to a symptom
Press / to search from any page, Esc to close