This is the last part. We measured server time, separated the query problems, and stacked caches by layer. What remains is what the browser downloads and executes — and it behaves differently, because it gets heavy through accumulation rather than a single mistake.
Every time a new feature adds one more script, that decision is individually reasonable. The total is the problem, and if nobody is watching the total the page gets heavy without anyone doing anything wrong. A budget is simply the device that gives that total a name.
What to put a ceiling on
The specific figures differ per site. What matters is not the value but whether a value exists. Without one, “that only added a little” repeats indefinitely.
Measure it on the initial view. Counting images far below the fold only inflates the number and makes judgement harder. And the same rules as the earlier parts apply: same URL, same conditions, three runs, median.
The WordPress-specific leak: global assets
The most common way a budget leaks here is plugins that register assets on every page. Contact form scripts load on blog posts; slider CSS loads on the contact page. No plugin knows where its feature will be placed, so registering globally is the safe default — and those safe defaults add up until the budget is gone.
Start by finding out what is actually loading.
add_action( 'wp_print_footer_scripts', function () {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
global $wp_scripts, $wp_styles;
error_log( 'JS : ' . implode( ', ', $wp_scripts->done ) );
error_log( 'CSS: ' . implode( ', ', $wp_styles->done ) );
}, 99 );
From that list, pick the handles this page does not need and drop them conditionally. The condition is the important half — removing a script from the screens that genuinely use it is not an optimisation, it is a bug.
add_action( 'wp_enqueue_scripts', function () {
if ( is_singular( 'post' ) ) {
wp_dequeue_script( 'acme-contact-form' );
wp_dequeue_style( 'acme-contact-form' );
}
}, 100 );
A budget only exists if it is checked
A ceiling written in a document is forgotten within a month. It survives only when the measurement sits inside the deployment path. If you can automate it, measure during the build and fail when the ceiling is exceeded; if you cannot, make it one line on the pre-release checklist.
And the point of a budget is not refusal but exchange. When a new feature would exceed the ceiling, the question is not “no” but “what comes out to make room?”. Once that conversation starts happening, the asset list tidies itself.
Closing the series
One principle ran through all eight parts: measure, fix, then measure again. Split the request into segments, tell slow queries from duplicated ones, prime away the N+1, put each cache at the layer where it belongs, name the events that must invalidate it, watch what rides on every request, and finally cap the total weight of what you ship.
WordPress supports all of this well. Sites do not get slow because the tool runs out of room; they get slow when one of these layers is left unattended, which is why there is usually improvement available.
For the parts that are hard to take on alone — version upgrades, introducing Redis, configuring an nginx cache, security review — the scope and pricing are set out in our optimization program, and the order in which we measure and fix is published step by step on the process page.