
You click “Regenerate Critical CSS.” The progress bar crawls forward: 20%, 30%, 40%. Then it drops to 20%. Climbs back to 50%. Drops to 35%. Eventually it hits 100%, and you exhale. Then it starts over from 0%.
This is not a fever dream. This is Jetpack Boost’s Critical CSS generator. Jetpack Boost is Automattic’s free WordPress performance plugin; its headline feature is generating and inlining Critical CSS to speed up page rendering. The behavior above is partially intentional, partially buggy, and entirely educational if you care about writing code comments that don’t lie.
I went spelunking through the source code to understand what’s actually happening. What I found is a case study in UX tradeoffs, concurrency bugs, and one code comment so perfectly ironic it deserves its own blog post.
Quick Context: What Critical CSS Does
Critical CSS is the minimal subset of your site’s stylesheets needed to render above-the-fold content. You inline it in the <head> so the browser can paint the page without waiting for external CSS files to download. Everything else loads asynchronously.
Jetpack Boost’s free tier generates this CSS in your browser. When you click “Regenerate,” the React admin UI launches hidden iframes, loads representative pages from your site, and extracts the CSS rules that affect visible elements. The server coordinates the process; the browser does the actual work.
The Provider System
Boost doesn’t generate one blob of CSS for your entire site. It generates separate CSS for each “provider” (page type):
|
|
Provider What it covers ---------------------- ---------------------------------------- Cornerstone_Provider Manually-designated important pages Post_ID_Provider Specific posts by ID WP_Core_Provider Homepage + Blog/Posts page Singular_Post_Provider Single posts by post type Archive_Provider Archive pages Taxonomy_Provider Category/tag/taxonomy archive pages |
For each provider, the generator loads the page in three viewport sizes (phone at 414×896, tablet at 1200×800, desktop at 1920×1080) and extracts the above-fold CSS for each. The progress bar reflects completion across all providers.
The progress formula is straightforward:
|
|
progress = 100 * (completed_providers / total_providers + current_provider_progress / total_providers) |
With 5 providers, each one contributes 20% when fully done, plus a fractional amount while in progress. Simple enough. So why does the bar go backwards?
The Comment That Lies
Here is the actual source code from generate-critical-css.ts, inside the loop that iterates through providers. This runs immediately after each provider finishes:
|
|
// Reset local progress whenever a provider is finished // to prevent progress bar jank. callbacks.setProviderProgress(0); |
Read that comment again. “To prevent progress bar jank.”
Here’s what actually happens at each provider boundary. Suppose we have 5 providers and provider #3 just finished:
|
|
Step Event Done SubProgress Bar Shows ---- --------------------------------- ---- ----------- --------- 1 Provider 3's last viewport done 2 ~1.0 60% 2 setProviderCss() resolves 3 ~1.0 80% 3 setProviderProgress(0) fires 3 0.0 60% ← DROPS 20 POINTS 4 Provider 4 starts, first viewport 3 ~0.1 62% |
The bar jumps from 80% to 60% because the code zeroes out the sub-progress after the completed provider count has incremented but before the next provider has made any progress. This happens at every provider boundary. With 5 providers, you see 4 backwards jumps.
The comment says this “prevents jank.” The users see jank. The comment is describing the developer’s intention, not the code’s behavior. These are not the same thing, and confusing them is one of the most common commenting mistakes in software.
What the Developer Was Actually Trying to Prevent
To be fair, there is a brief moment (step 2 above) where the bar shows 80% when arguably only 60% of the work is done (3 of 5 providers complete, with no sub-progress on the 4th). The developer saw this momentary overshoot and decided it was worse than a backwards jump.
They were wrong, but the reasoning was coherent. The problem is that the comment doesn’t explain the tradeoff. A better comment would be:
|
|
// Zero out sub-progress after completing a provider. // Without this, the bar briefly overshoots by one provider's // worth (~20%) before the next provider starts. The tradeoff // is a visible backward jump at each provider boundary. callbacks.setProviderProgress(0); |
That comment is honest. It tells you what the code does, why, and what you’ll observe. The original comment tells you what the developer wished the code did.
The 100%-Then-Restart Bug
The backwards progress is annoying but cosmetic. The restart-from-zero problem is a real bug, and it has multiple causes.
Cause 1: The Double-Click Race Condition
GitHub Issue #31543 documents this precisely. If you click the Regenerate button twice before the server responds, two generators start running in parallel. Both are writing to the same React state via setProviderProgress. The progress bar bounces between the two generators’ positions like a tennis ball.
The fix was to optimistically set the state to pending after the first click, which should disable the button. But the optimistic state uses an empty provider list:
|
|
const optimisticState: CriticalCssState = { status: 'pending', providers: [] }; |
An empty provider list means calculateCriticalCssProgress tries to divide by zero. The button may or may not disable in time, depending on connection speed. The fix has a bug.
Cause 2: The Auto-Regenerate Trigger
The React component watches for a not_generated state:
|
|
} else if (cssState.status === 'not_generated') { // If there is no css generated, request that the generator start. generateCriticalCssAction.mutate(); } |
If anything resets the state to not_generated during generation (a theme switch, for instance), the 2-second polling loop detects it and fires a brand new generation cycle. Progress drops to 0% with no warning or explanation.
Cause 3: The Effect Dependency Trap
The React effect that launches the generator depends on cssState.providers.length:
|
|
[cssState.status, cssState.providers.length] |
If the provider count changes mid-generation (someone adds a cornerstone page while CSS is generating), the effect re-fires and can spawn a second generator alongside the first. Same tennis ball problem as the double-click bug.
The Freemium Nag You Can Ignore
Every time you publish a post, Jetpack Boost sets a suggest_regenerate flag and increments a “problems” counter on the dashboard. The message implies your Critical CSS is stale and needs regenerating.
Here’s what actually happens when you publish a post:
|
|
CSS deleted? No. State cleared? No. Old CSS still served? Yes, exactly as before. Admin notice shown? No. Dashboard nag shown? Yes. Auto-regenerate? No. |
Your CSS is fine. The homepage layout is templated; post #347 renders in the same CSS structure as post #346. The only event that actually deletes your CSS is a theme switch (which makes sense, since a theme change genuinely invalidates all your CSS rules).
The paid tier (Cloud CSS) auto-regenerates seamlessly via Automattic’s servers. The free tier makes you do it manually in your browser while watching a progress bar that goes backwards. Draw your own conclusions about the incentive structure.
For the record, I checked the source. Here’s the complete list of what each event actually does:
|
|
Event CSS Deleted? Still Served? Nag Shown? ---------------------- ------------ ------------- ---------- Theme switch YES No Yes Post published No Yes Yes Plugin activated No Yes Yes Plugin deactivated No Yes Yes Boost plugin updated No Yes No |
Notice that “post published” and “theme switch” produce the same nag but wildly different actual behavior. The UI doesn’t distinguish between “your CSS is genuinely invalid” and “something changed and we thought you’d like to know.”
Lessons for the Rest of Us
This isn’t a “Jetpack is bad” post. Jetpack Boost is a free tool that provides real value, and the Critical CSS feature works correctly once it finishes generating. The generated CSS is fine. The UX around generation is where the wheels come off.
But the code comment is the part I can’t stop thinking about. “Reset local progress whenever a provider is finished to prevent progress bar jank” is a comment that has been read by every developer who has touched this code path, and none of them thought to check whether it was true.
Here’s the principle: A comment that describes what you intended the code to do, rather than what the code observably does, is worse than no comment at all. No comment leaves the reader uncertain. A wrong comment leaves the reader confident and wrong.
A few guidelines for comments that age well:
- Describe the tradeoff, not just the intent. “Prevents X at the cost of Y” is more useful than “Prevents X.”
- If your comment describes a user-visible behavior, verify it. Watch the actual UI. Click the actual button.
- If the behavior has changed since the comment was written, update the comment. Stale comments are technical debt that compounds invisibly.
- Comments should explain why, not what. The code already says what it does. The comment should say why that’s the right choice, including the alternatives that were considered and rejected.
The Known Issues
For anyone who wants to dig deeper, here are the confirmed GitHub issues in the Automattic/jetpack repository:
- #31543 – Double-click spawns parallel generators; progress bounces (closed, partially fixed)
- #22315 – Generation halts silently if module disabled during run (closed)
- #39092 – UI stuck forever when a provider returns 404 (closed)
- #40391 – Generation continues past critical provider failures (open)
Have you noticed the progress bar weirdness? Or do you just look away and wait for the notification? Let me know on Bluesky or LinkedIn.
Related
The Progress Bar That Goes Backwards: A Jetpack Boost Source Code Archaeology
You click “Regenerate Critical CSS.” The progress bar crawls forward: 20%, 30%, 40%. Then it drops to 20%. Climbs back to 50%. Drops to 35%. Eventually it hits 100%, and you exhale. Then it starts over from 0%.
This is not a fever dream. This is Jetpack Boost’s Critical CSS generator. Jetpack Boost is Automattic’s free WordPress performance plugin; its headline feature is generating and inlining Critical CSS to speed up page rendering. The behavior above is partially intentional, partially buggy, and entirely educational if you care about writing code comments that don’t lie.
I went spelunking through the source code to understand what’s actually happening. What I found is a case study in UX tradeoffs, concurrency bugs, and one code comment so perfectly ironic it deserves its own blog post.
Quick Context: What Critical CSS Does
Critical CSS is the minimal subset of your site’s stylesheets needed to render above-the-fold content. You inline it in the
<head>so the browser can paint the page without waiting for external CSS files to download. Everything else loads asynchronously.Jetpack Boost’s free tier generates this CSS in your browser. When you click “Regenerate,” the React admin UI launches hidden iframes, loads representative pages from your site, and extracts the CSS rules that affect visible elements. The server coordinates the process; the browser does the actual work.
The Provider System
Boost doesn’t generate one blob of CSS for your entire site. It generates separate CSS for each “provider” (page type):
For each provider, the generator loads the page in three viewport sizes (phone at 414×896, tablet at 1200×800, desktop at 1920×1080) and extracts the above-fold CSS for each. The progress bar reflects completion across all providers.
The progress formula is straightforward:
With 5 providers, each one contributes 20% when fully done, plus a fractional amount while in progress. Simple enough. So why does the bar go backwards?
The Comment That Lies
Here is the actual source code from
generate-critical-css.ts, inside the loop that iterates through providers. This runs immediately after each provider finishes:Read that comment again. “To prevent progress bar jank.”
Here’s what actually happens at each provider boundary. Suppose we have 5 providers and provider #3 just finished:
The bar jumps from 80% to 60% because the code zeroes out the sub-progress after the completed provider count has incremented but before the next provider has made any progress. This happens at every provider boundary. With 5 providers, you see 4 backwards jumps.
The comment says this “prevents jank.” The users see jank. The comment is describing the developer’s intention, not the code’s behavior. These are not the same thing, and confusing them is one of the most common commenting mistakes in software.
What the Developer Was Actually Trying to Prevent
To be fair, there is a brief moment (step 2 above) where the bar shows 80% when arguably only 60% of the work is done (3 of 5 providers complete, with no sub-progress on the 4th). The developer saw this momentary overshoot and decided it was worse than a backwards jump.
They were wrong, but the reasoning was coherent. The problem is that the comment doesn’t explain the tradeoff. A better comment would be:
That comment is honest. It tells you what the code does, why, and what you’ll observe. The original comment tells you what the developer wished the code did.
The 100%-Then-Restart Bug
The backwards progress is annoying but cosmetic. The restart-from-zero problem is a real bug, and it has multiple causes.
Cause 1: The Double-Click Race Condition
GitHub Issue #31543 documents this precisely. If you click the Regenerate button twice before the server responds, two generators start running in parallel. Both are writing to the same React state via
setProviderProgress. The progress bar bounces between the two generators’ positions like a tennis ball.The fix was to optimistically set the state to
pendingafter the first click, which should disable the button. But the optimistic state uses an empty provider list:An empty provider list means
calculateCriticalCssProgresstries to divide by zero. The button may or may not disable in time, depending on connection speed. The fix has a bug.Cause 2: The Auto-Regenerate Trigger
The React component watches for a
not_generatedstate:If anything resets the state to
not_generatedduring generation (a theme switch, for instance), the 2-second polling loop detects it and fires a brand new generation cycle. Progress drops to 0% with no warning or explanation.Cause 3: The Effect Dependency Trap
The React effect that launches the generator depends on
cssState.providers.length:If the provider count changes mid-generation (someone adds a cornerstone page while CSS is generating), the effect re-fires and can spawn a second generator alongside the first. Same tennis ball problem as the double-click bug.
The Freemium Nag You Can Ignore
Every time you publish a post, Jetpack Boost sets a
suggest_regenerateflag and increments a “problems” counter on the dashboard. The message implies your Critical CSS is stale and needs regenerating.Here’s what actually happens when you publish a post:
Your CSS is fine. The homepage layout is templated; post #347 renders in the same CSS structure as post #346. The only event that actually deletes your CSS is a theme switch (which makes sense, since a theme change genuinely invalidates all your CSS rules).
The paid tier (Cloud CSS) auto-regenerates seamlessly via Automattic’s servers. The free tier makes you do it manually in your browser while watching a progress bar that goes backwards. Draw your own conclusions about the incentive structure.
For the record, I checked the source. Here’s the complete list of what each event actually does:
Notice that “post published” and “theme switch” produce the same nag but wildly different actual behavior. The UI doesn’t distinguish between “your CSS is genuinely invalid” and “something changed and we thought you’d like to know.”
Lessons for the Rest of Us
This isn’t a “Jetpack is bad” post. Jetpack Boost is a free tool that provides real value, and the Critical CSS feature works correctly once it finishes generating. The generated CSS is fine. The UX around generation is where the wheels come off.
But the code comment is the part I can’t stop thinking about. “Reset local progress whenever a provider is finished to prevent progress bar jank” is a comment that has been read by every developer who has touched this code path, and none of them thought to check whether it was true.
Here’s the principle: A comment that describes what you intended the code to do, rather than what the code observably does, is worse than no comment at all. No comment leaves the reader uncertain. A wrong comment leaves the reader confident and wrong.
A few guidelines for comments that age well:
The Known Issues
For anyone who wants to dig deeper, here are the confirmed GitHub issues in the Automattic/jetpack repository:
Have you noticed the progress bar weirdness? Or do you just look away and wait for the notification? Let me know on Bluesky or LinkedIn.
Share this:
Related