How to Keep Your Website Fast on Black Friday 2026

Guide15 min read
How to Keep Your Website Fast on Black Friday 2026: a peak traffic chart with page cache and Redis object cache on

On Cyber Monday 2025, shoppers spent $16 million every minute between 8 and 10pm, according to Adobe Analytics. Paddle says its customers saw up to 20x normal traffic over BFCM. A store that loads in two seconds on a quiet Tuesday can time out at checkout when that wave hits, and Black Friday website performance decides whether those shoppers buy.

Black Friday website performance is a capacity problem you can plan for. The everyday WordPress speed tips still apply, but peak traffic exposes uncached cart requests, too few PHP workers and a bloated options table. With Black Friday on November 27 and Cyber Monday on November 30, you still have time to find them first.

This guide walks WordPress, WooCommerce and web app owners from baseline to rollback plan. For offers, emails and support, pair it with our Black Friday checklist.

TL;DR: Key Takeaways

  • Measure first: Core Web Vitals, uncached response times and your busiest hour of traffic.
  • Plan for concurrent users. A simple formula turns last year’s peak hour into a load test target and a PHP worker count.
  • Load test a staging copy with k6, ramping in stages, and abort when errors pass 1%.
  • Cache in layers and exclude cart, checkout, my-account and the WooCommerce session cookies.
  • Clean the database and move background jobs to a server cron, including Action Scheduler.
  • Upsize before the freeze if tests show CPU or RAM pinned, then freeze changes with a tested backup ready.

Why Black Friday Breaks Sites That Feel Fast

Most WordPress sites feel fast because a page cache serves the same HTML to everyone. Once shoppers add items to a cart, every cart view, checkout step and AJAX call skips that cache and lands on PHP and the database.

Think of the page cache as a supermarket express lane. The full-service lanes are your PHP workers, and when every one is busy, requests queue until they return 502 or 504 errors. So cache everything you can, and give the rest enough workers and a fast database.

What You’ll Need

Item Why it matters
A staging copy of the site You test and change settings here, never on production
SSH or WP-CLI access Database checks, cron changes and queue runners
k6 installed locally Scripted, repeatable load tests
Hourly analytics and a fresh backup Your peak-hour number and your rollback point

Step 1: Measure Your Baseline

You cannot judge a fix without a before number. Google’s web.dev guidance on Core Web Vitals sets these “good” thresholds at the 75th percentile of page loads:

Metric What it measures Good threshold
LCP (Largest Contentful Paint) When the main content appears 2.5 seconds or less
INP (Interaction to Next Paint) Response to taps and clicks 200 milliseconds or less
CLS (Cumulative Layout Shift) Visual stability 0.1 or less

Run your homepage, sale page, top products, cart and checkout through PageSpeed Insights. Field data reflects real Chrome users over the previous 28-day collection period; lab data comes from one simulated load, so use it to check changes quickly.

GTmetrix adds a waterfall chart showing which request blocks rendering. Also record uncached TTFB (time to first byte) on the cart and checkout.

Step 2: Estimate Your Peak Concurrent Users

What matters on Black Friday is how many people use the site at the same moment. A standard queueing rule (Little’s Law) gives you a workable estimate.

Example only (replace every number with your own data):

  1. Busiest hour last year: 2,000 sessions.
  2. Growth multiplier: 10x, from this year’s list size and ad budget (Paddle’s “up to 20x” is a ceiling).
  3. Average session length: 5 minutes (300 seconds).
  4. Peak concurrent users = (2,000 × 10 × 300) ÷ 3,600 = about 1,667 users online at once.

If each shopper loads a page every 30 seconds, that is about 56 requests per second. If 25% skip the cache (carts, checkout, AJAX), PHP handles about 14 requests per second.

Workers needed = dynamic requests per second × average PHP response time. At 0.5 seconds, 14 × 0.5 = 7 busy workers on average; double it for bursts and you land at 14 to 16 workers, the number Step 3 validates.

Step 3: Load Test on Staging (Safely)

Run the test on a staging copy with the same server size, plugins and cache settings as production. Our staging site guide covers the setup.

If staging shares a server with production, the test slows your live store, so clone it to a separate same-size server or test in quiet hours. Put payments in test mode, pause transactional emails and tell your host first.

Save this as bf-test.js:

import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  scenarios: {
    shoppers: {
      executor: 'ramping-vus',
      startVUs: 0,
      stages: [
        { duration: '5m', target: 50 },   // warm up
        { duration: '10m', target: 50 },
        { duration: '5m', target: 200 },  // expected peak
        { duration: '10m', target: 200 },
        { duration: '5m', target: 400 },  // 2x peak
        { duration: '10m', target: 400 },
        { duration: '5m', target: 0 },    // ramp down
      ],
      gracefulRampDown: '30s',
    },
  },
  thresholds: {
    http_req_failed: [{ threshold: 'rate<0.01', abortOnFail: true }],
    http_req_duration: ['p(95)<800'],
  },
};

const BASE = __ENV.BASE_URL;
const think = (min, max) => sleep(min + Math.random() * (max - min));

export default function () {
  check(http.get(`${BASE}/`), { 'home 200': (r) => r.status === 200 });
  think(3, 8);
  check(http.get(`${BASE}/product/sample-product/`), { 'product 200': (r) => r.status === 200 });
  think(3, 8);
  const add = http.post(`${BASE}/?wc-ajax=add_to_cart`, { product_id: '123', quantity: '1' });
  check(add, { 'add to cart 200': (r) => r.status === 200 });
  think(3, 8);
  check(http.get(`${BASE}/cart/`), { 'cart 200': (r) => r.status === 200 });
  think(5, 15);
}

Swap in a real product slug and product_id, then run k6 run -e BASE_URL=https://staging.yourstore.com bf-test.js. Each virtual user keeps its own cookies, so carts behave like real sessions, and abortOnFail stops the run once failures pass 1%.

The VU targets are placeholders: scale the stages until the request rate k6 reports matches your Step 2 forecast. At each hold, watch p95 response time, CPU, RAM and database load; at 2x peak, note what fails first, and after ramp down, check that response times recover.

Hosted tools such as Loader.io suit simple URL tests. Fix the first bottleneck, then test again.

Step 4: Layer Your Caching

Each cache layer answers some requests before they reach PHP, which leaves your workers free for carts and checkout.

Layer What it caches Black Friday job
Edge / CDN cache Static files, plus HTML with edge page caching Serves anonymous shoppers from a nearby location
Full-page cache Rendered HTML on your server Skips PHP for repeat page views
Object cache (Redis) Database query results Speeds up carts, checkout and wp-admin
OPcache Compiled PHP code Cuts CPU time on uncached requests
Browser cache CSS, JS, fonts, images Makes the second page view nearly free

On WordPress, WPDeveloper’s xSpeed Cache plugin covers page caching, Redis object caching, minification, a cache preloader and Cloudflare purging in one place, and its site says /cart and /checkout stay uncached by default. Our guides to Redis object caching and edge page caching go deeper on those layers.

WooCommerce exclusions are not optional. The WooCommerce caching docs say to exclude the Cart, Checkout and My Account pages and the cookies woocommerce_cart_hash, woocommerce_items_in_cart, wp_woocommerce_session_, woocommerce_recently_viewed and store_notice[notice id]. Skip this and one shopper’s cart can appear for another.

Warm the cache before each email send, because a full purge just before thousands of clicks sends everyone to PHP. Learn how to clear your website cache layer by layer, so a price change purges one page, not the site.

Step 5: Optimize Images and Assets

Mobile carried 57.5% of Cyber Monday 2025 sales in Adobe’s data, so test on a mid-range phone. On most product pages, the LCP element is the hero or product image.

  • Serve WebP or AVIF at the displayed size, and never lazy-load the LCP image.
  • Set width and height on images and embeds to keep CLS under 0.1.
  • Compress text assets with Brotli and defer non-critical JavaScript.

Step 6: Clean Up the Database

A slow database hurts the requests you cannot cache. Start with autoloaded options, which WordPress loads on every request; since WordPress 6.6, Site Health flags a critical issue when the total passes 800 KB.

Check your total and the largest entries (change wp_ if your prefix differs):

SELECT ROUND(SUM(LENGTH(option_value)) / 1024) AS autoload_kb
FROM wp_options WHERE autoload IN ('yes', 'on', 'auto-on', 'auto');

SELECT option_name, ROUND(LENGTH(option_value) / 1024) AS kb
FROM wp_options WHERE autoload IN ('yes', 'on', 'auto-on', 'auto')
ORDER BY LENGTH(option_value) DESC LIMIT 20;

Leftovers from deleted plugins are the usual culprits; set them to off on staging and confirm nothing breaks.

Stores should also check HPOS (High-Performance Order Storage), which keeps orders in dedicated tables instead of posts and post meta. WooCommerce enables it by default for new stores since 8.2; older stores switch under WooCommerce → Settings → Advanced → Features, and should do it on staging well before sale week.

Run wp action-scheduler clean to remove completed and canceled jobs older than 31 days. Add an index only when the slow query log or EXPLAIN shows a full table scan.

Step 7: Tune PHP Workers and the PHP Version

Size PHP-FPM workers (pm.max_children) from your Step 2 number, then check the RAM. Measure average worker size with ps -eo rss,cmd | grep php-fpm, reserve memory for MySQL, Redis and the OS, and divide what is left by that average.

Example only: a 4 GB server with 1.5 GB reserved leaves 2.5 GB, which fits about 31 workers at 80 MB each. If your math lands below target, a higher config value won’t help: you need a bigger server (Step 11).

Per php.net, PHP 8.2 security support ends on December 31, 2026, so target PHP 8.3 or 8.4. Upgrade on staging, rerun the load test, and give OPcache enough memory to hold your whole codebase.

Step 8: Move Cron and Background Jobs Off Page Loads

WP-Cron fires on visitor page loads by default, so during a spike random shoppers pay for your scheduled tasks. Add define( 'DISABLE_WP_CRON', true ); to wp-config.php and run a real server cron every minute; our cron jobs guide shows how.

WooCommerce runs order emails, webhooks and renewals through Action Scheduler, whose docs call WP-CLI a much better choice than WP-Cron for large sites. Add a server cron for wp action-scheduler run and watch WooCommerce → Status → Scheduled Actions: a growing pending count means emails and webhooks are falling behind.

Step 9: Audit Third-Party Scripts

Chat widgets, heatmaps, A/B tests, review badges and stacked ad pixels all compete for the same phone CPU. List every external domain your sale page loads in the browser’s network tab.

Remove what nobody can justify, delay the rest until user interaction, and leave payment, fraud and tax scripts alone. Also check whether your theme fires the uncached wc-ajax=get_refreshed_fragments request on every page.

Step 10: Put a CDN and Bot Protection in Front

A CDN moves static files, and with edge page caching even HTML, off your origin. Cloudflare also filters scrapers and credential-stuffing bots, which show up for sale week too.

  • Rate limit /wp-login.php, /xmlrpc.php and the cart AJAX endpoints.
  • Use WAF rules, and keep Under Attack Mode ready for a flood.
  • Test payment webhooks with protection on, since a JavaScript challenge can block server-to-server requests.

Our guide to preventing DDoS attacks covers the security side.

Step 11: Choose Vertical or Horizontal Scaling

Vertical scaling means a bigger server. Horizontal scaling means more servers behind a load balancer, which for WordPress also requires a shared database, object cache and file storage before a second app server helps.

Approach Best for Trade-off
Vertical (upsize) WordPress, WooCommerce, most PHP apps Simple, but still one point of failure
Horizontal (add servers) Stateless web apps and SaaS APIs More capacity and redundancy, more moving parts
Offload (CDN, managed DB, queues) Any stack Often the cheapest first step

Upsize when the test says so: CPU stays above 80% at expected peak with a warm cache, the Step 7 math doesn’t fit in RAM, or database CPU pins first. Treat 80% as a starting point rather than a strict rule, and resize before the freeze.

Step 12: Set Up Monitoring and Alerts

Hear about problems from an alert before a customer emails you. Point an external uptime check at the homepage, a product page and the cart with a keyword match, so a cached error page doesn’t count as “up”.

Starting-point thresholds (tune to your baseline): CPU above 80% for 5 minutes, RAM above 90%, disk above 85%, p95 above 1 second, errors above 1%. Watch the gateway dashboard and WooCommerce → Status → Logs, and put one person on each peak window.

Step 13: Freeze Changes and Write the Rollback Plan

A change freeze means no plugin, theme, core or server updates unless a security patch forces one (and it still goes through staging). Example window: Friday, November 20 through Wednesday, December 2, the same window our Black Friday checklist uses.

Your rollback plan fits on one page:

  1. Take a full backup before the freeze and another right before the sale goes live.
  2. Restore one to staging and time it, so you know your real recovery time.
  3. Note how to roll back a plugin, for example wp plugin install plugin-slug --version=1.2.3 --force.
  4. Name who decides, and the trigger (say, checkout errors above 2% for 10 minutes).

Troubleshooting: Black Friday Performance Problems

Symptom Likely cause Fix
502 or 504 errors at peak All PHP workers busy Raise max children within RAM, cache more, or upsize
Fast homepage, slow cart and checkout Uncached requests on a slow database Redis object cache, HPOS, profile checkout plugins
Shoppers see the wrong cart Cart pages or WooCommerce cookies cached Add page and cookie exclusions, then purge
Every page slow after an email send Cold or purged cache Preload before sends; skip full purges at peak
High CPU without more traffic Bots, WP-Cron or a job backlog Rate limit, WAF rules, server cron
“Error establishing a database connection” Connection limit or slow queries Fix slow queries, trim autoload, upsize
Poor LCP on mobile only Oversized or lazy-loaded hero image Resize, WebP or AVIF, no lazy-load on LCP
Late order emails Action Scheduler backlog WP-CLI queue runner; dedicated email delivery
Missing payment confirmations WAF challenge blocking webhooks Allow the gateway’s webhook endpoint, retest

Run Your Black Friday Prep on xCloud

On xCloud, here is where each control lives, per our docs:

  • Caching: Sites → your site → WordPress → Caching lets you choose xSpeed Cache (the default on new WordPress sites) or built-in Full Page Caching and Redis Object Caching, with Purge Cache on hand.
  • PHP and workers: Site Settings → PHP Configurations → Manage opens the PHP, FPM (PM Max Children) and OPcache panels, and Auto Tune suggests values from your RAM.
  • Staging: click Deploy Staging, then ship tested changes with Staging Management → Push Data (staging docs).
  • Cloudflare Enterprise: pick Cloudflare Enterprise in the site sidebar and click Enable Cloudflare Enterprise. The add-on costs $5 per domain per month with 100 GB of bandwidth and includes edge page caching, WAF, rate limiting, Under Attack Mode and unmetered DDoS mitigation (setup guide).
  • Upsizing: All Servers → your server → Server Management → Choose Your Server Size → Upgrade Server. The upgrade guide covers xCloud and Vultr servers and warns of 2 to 3 minutes of downtime and no downgrade afterward, so back up and resize early.
  • Backups: schedule them in Site Backup → Backup Settings and take the pre-sale snapshot with Backup → Previous Backups → Backup Now (backup docs).
  • Monitoring and cron: Live Monitoring (Servers → your server → Monitoring) refreshes CPU, RAM and disk meters every 5 seconds; add server crons under Cron Jobs → Add Cron Job.

The Live Monitoring doc describes meters but not alerts, so keep an external uptime monitor running alongside it. For order emails at volume, the Email Delivery add-on takes sending off your web server.

If testing says you need more room, xCloud Managed Hosting runs from 4 GB / 2 vCPU (Growing, $30/mo) to 16 GB (Titanium, $100/mo), with free migrations, backups and 24/7 chat. This Black Friday we are offering an exclusive discount on Managed Server plans and a lifetime deal on the self-managed control panel: see xCloud’s Black Friday deals or the pricing page.

Ready for the rush? Grab xCloud’s Black Friday Managed Server deal and load test with room to spare.

Load Test This Week, Freeze by November 20

Caching and a clean database take most requests off PHP. Enough PHP workers handle what caching can’t, and a bigger server covers the rest when your load test calls for it.

This week, record your baseline and run the Step 2 math. Next week, load test staging, fix what breaks and test again, then freeze on November 20 with a tested backup. New to the event? Our guide to what Black Friday is covers the business side.

If you have found this blog helpful, feel free to subscribe to our blogs for valuable tutorials, guides, knowledge, and tips on web hosting and server management. You can also join our Facebook community to share insights and engage in discussions.

Frequently Asked Questions

How much traffic can my WooCommerce store handle on Black Friday?

Only a load test tells you. Ramp a k6 test on staging until errors pass 1% or response times climb; that breaking point, minus a safety margin, is your capacity.

Is it safe to load test my live website?

It is risky: a test can crash production, create real orders and email real customers. Test a same-size staging copy with payments in test mode.

Should I cache the WooCommerce cart and checkout pages?

No. WooCommerce says to exclude Cart, Checkout, My Account and its session cookies from page caching. Speed those pages up with Redis object caching, HPOS and enough PHP workers instead.

How many PHP workers do I need for Black Friday?

Multiply expected uncached requests per second by average PHP response time, then roughly double it for bursts, and confirm it fits in RAM. On xCloud, Auto Tune in the PHP settings suggests values from your server’s memory.

When should I upgrade my server before Black Friday?

As soon as a load test shows CPU or RAM pinned at expected peak, and before your change freeze. Resizing can mean a few minutes of downtime, and xCloud upgrades can’t be reversed, so size from test results.

Should I disable WP-Cron before Black Friday?

Yes, if you can add a server cron to replace it. Set DISABLE_WP_CRON to true in wp-config.php, run WP-Cron and the Action Scheduler queue from a server cron every minute, and test both on staging first.

← All articles