Beskrivelse
WordPress prioritises backwards compatibility.
That’s a feature. It also means every install ships with things you didn’t ask for.
An emoji CDN script. An oEmbed script. A Windows Live Writer manifest (discontinued 2017).
Dashicons loaded for logged-out visitors. Heartbeat polling every 15 seconds.
A version tag that tells the world exactly which WordPress you’re running.
None of these are bugs. They’re just not needed on most sites.
The Off Switch lets you disable each one, individually.
The Off Switches
- Emoji script – ~15 KB + 1 HTTP request. Browsers handle emoji natively.
- Embed script – ~4 KB + oEmbed discovery links in
<head>. - RSD link – Really Simple Discovery. Only needed for legacy XML-RPC clients.
- WLW manifest – Windows Live Writer has been discontinued since 2017.
- WP version tag – Stops advertising your WordPress version to the world.
- Shortlink – Removes
<link rel="shortlink">from<head>and HTTP headers. Search engines ignore it. - Asset query strings – Strips
?ver=from scripts, styles, and WP 6.5+ Script Modules so CDNs and proxies cache correctly. - XML-RPC – Closes a common brute-force attack vector.
- Heartbeat API – Reduces admin polling from every 15 s to every 60 s.
- Dashicons (frontend) – ~35 KB (CSS + font) saved for every logged-out visitor.
- REST API Discovery Link – Removes
<link rel="https://api.w.org/">from<head>. Safe to remove on standard sites. - RSS Feed Links – Removes feed autodiscovery
<link>tags from<head>. Modern browsers no longer act on them. Leave enabled if you publish an RSS feed. - Speculation Rules (WP 6.8+) – Disables the WP 6.8+ Speculation Rules API that prefetches links before users click. Can inflate analytics, increase server bandwidth, and trigger consent flows on unfetched pages.
- Disable All Feeds – Redirects all RSS and Atom feed URLs to the homepage. For sites with no RSS subscribers.
- Comment Auto-Links – Stops WordPress from converting plain-text URLs in comments into clickable links.
- Editor Autosave – Deregisters the autosave script that POSTs editor content to the server every 60 seconds. For teams that prefer explicit saves.
- DNS Prefetch – Removes all
<link rel="dns-prefetch">hints from<head>. Redundant when Emojis and Embeds are already disabled. - Recent Comments Inline CSS – WordPress outputs a small inline
<style>block in<head>whenever the Recent Comments widget is active. Remove it if your theme already styles the widget.
Script & Style Control
- jQuery Migrate – ~30 KB. Modern themes don’t need it.
- Block Library CSS – ~7 KB loaded on every page, even with no Gutenberg blocks.
- Global Styles (theme.json CSS) – 10-50 KB inline CSS from block themes.
- SVG Duotone Filters – Hidden SVG blob injected on every page, even with no duotone images.
- Script/Style type attributes –
type="text/javascript"andtype="text/css"are redundant in HTML5. - Defer non-critical JavaScript – Adds
deferso scripts don’t block HTML parsing. jQuery is never deferred. - Move scripts to footer – Relocates enqueued scripts from
<head>to just before</body>. jQuery is never moved.
WordPress Behaviour Tweaks
- Self-pingbacks – WordPress pings your own posts when you link between them – a wasted HTTP request that creates an unwanted comment on the target post.
- Capital P filter – WordPress corrects “WordPress” to “WordPress” on every rendered string. Remove if you don’t need the autocorrect.
- Limit post revisions – WordPress stores unlimited revisions per post. Caps revisions at 3 to prevent silent database growth on active editorial sites.
- Attachment pages – WordPress creates a full template page for every uploaded file. These waste crawl budget on most sites. Sends a 301 redirect to the parent post instead.
Database & Query
- Expired Transients – Schedules a daily cleanup of expired transient rows in wp_options. Useful on low-traffic sites where WP-Cron can go days without firing.
- Abandoned Auto-Drafts – WordPress creates an auto-draft every time the post editor opens. Abandoned sessions leave these rows permanently. Runs a daily sweep to delete auto-drafts older than 30 days.
- Skip Row Count on Singles – On every single post or page, MySQL runs SQL_CALC_FOUND_ROWS to count total matching rows – a full index scan only needed for paginated archives. Removes that sub-query on all singular views.
- Adjacent Post Links – WordPress queries the previous and next post on every single post page to output
<link rel="prev/next">in<head>. Two extra DB queries per page load. Google dropped support for these SEO hints in 2019. - Reduce Trash Retention – WordPress keeps trashed items for 30 days before permanent deletion. Reducing to 7 days keeps wp_posts leaner on active editorial sites without affecting normal recovery workflows.
Image Performance
- Google Fonts display:swap – Without
font-display:swap, the browser hides text while your Google Font downloads (FOIT). Addsdisplay=swapto every Google Fonts URL so visitors see text immediately. - Add missing image dimensions – Images without
widthandheightattributes cause layout shifts (CLS). Reads dimensions from attachment metadata and injects them automatically. - LCP image priority – Adds
fetchpriority="high"to the first content image so the browser loads it before lower-priority resources. Addsfetchpriority="low"anddecoding="async"to all others. - Lazy load images – Adds
loading="lazy"to images below the fold. The first image is never lazy-loaded – it is the LCP candidate and must load immediately. - Disable PDF thumbnails – WordPress generates thumbnail previews for every uploaded PDF when ImageMagick is available. Rarely used on the frontend; adds significant upload processing time.
Admin Hardening
- Block User Enumeration – WordPress redirects
?author=1to/author/username/, exposing registered usernames. Intercepts those requests and redirects to the homepage before the username is revealed. - Disable Author Archives – Redirects all
/author/username/pages to the homepage. For sites with no author profile pages. - Disable File Editor – Defines
DISALLOW_FILE_EDITto remove the plugin and theme code editor from wp-admin. Eliminates a code-injection surface a compromised admin account could exploit. - Disable Application Passwords – Removes the Application Passwords UI and stops all tokens from being accepted. For sites that don’t use REST API or XML-RPC integrations.
- Suppress Admin Email Check – Disables the periodic full-screen prompt asking admins to confirm their email address. One less interruption, no functional change.
- Remove X-Pingback Header – Strips
X-Pingback:from every HTTP response, stopping the site from advertising its XML-RPC endpoint URL to scanners. - Clean Admin Bar – Removes the WordPress logo dropdown, the duplicate “Visit Site” link, and the admin bar search for a less cluttered editing environment.
- Hide Update Nag for Non-Admins – Hides the core update notice from editors and contributors who cannot action it. Administrators still see it normally.
- Restrict REST API to Logged-In Users – The REST API is publicly accessible by default, allowing unauthenticated enumeration of posts, users, and other data. Restricting access to authenticated users reduces the attack surface. Will break public REST consumers such as headless frontends.
- Redirect Unauthenticated Admin Access – By default, visiting /wp-admin/ without being logged in redirects to the login page, confirming a WordPress admin area exists. This redirects unauthenticated requests to the homepage instead, reducing information disclosure to scanners. AJAX, Cron, WP-CLI, and admin-post.php requests are never affected.
Block Editor
- Remote Block Patterns – WordPress fetches patterns from api.wordpress.org on every editor load. An outbound HTTP request that adds latency even if editors never use the Pattern inserter. Local patterns from themes and plugins are unaffected.
- Core Block Patterns – Removes WordPress’s built-in block patterns (headers, galleries, CTAs) from the Pattern inserter. For sites using custom patterns or none at all.
- Block Directory – The editor includes a live search of wordpress.org that lets users install new blocks without leaving the editor. Remove it to keep block installation under your control.
- Font Library (WP 6.5+) – WordPress 6.5 added a Font Library panel for uploading custom fonts and browsing Google Fonts in the Site Editor. Remove it if fonts are managed through your theme or code.
- Widget Block Editor (WP 5.8+) – WordPress 5.8 replaced the classic Widgets screen with a block-based editor. Restores the classic screen for classic themes, sidebar widgets, and page builders.
WooCommerce
These toggles are only shown when WooCommerce is active.
- Cart Fragments – wc-cart-fragments.js fires an AJAX request to keep mini-cart counts accurate when the Cart Widget is rendered (~3 KB + 1 request). Disable on stores where the Cart Widget is not used, or where real-time cart accuracy across tabs is not needed.
- WooCommerce Generator Tag – Removes
<meta name="generator" content="WooCommerce x.x.x">from<head>. Same reason as the WordPress version tag: stops advertising which version of WooCommerce you’re running. - WC Scripts on Non-WC Pages – WooCommerce loads ~114 KB of CSS and JS on every page (woocommerce-general, woocommerce-layout, woocommerce-smallscreen, woocommerce.js, wc-add-to-cart.js, and woocommerce-blocktheme on block themes). Dequeues them all on non-shop, non-cart, non-checkout, and non-account pages. Up to ~30 KB gzipped saved per non-WooCommerce page.
- Password Strength Meter – WooCommerce already restricts wc-password-strength-meter to checkout and My Account pages where a password is required. This toggle is a secondary safety net for themes or plugins that enqueue the script more broadly, removing zxcvbn (~80 KB gzipped) wherever it loads unnecessarily.
- Status Dashboard Widget – Removes the WooCommerce Status meta box from the WordPress admin dashboard. For stores managed from the WooCommerce screens directly.
- WC Block Patterns – WooCommerce registers its own block patterns in the editor inserter. Remove them if your store does not use WooCommerce-provided patterns for page design – declutters the inserter and removes a small init overhead.
- WC Legacy Widgets – WooCommerce registers 12 legacy widgets on every page load even on block-based themes. Unregistering them removes the initialisation overhead and hides them from Appearance -> Widgets.
- WC Version Header – Removes the X-WooCommerce-Version HTTP response header that some WooCommerce extensions inject, closing the same version-leakage vector as the generator tag toggle.
- Stripe Gateway Scripts – Prevents the WooCommerce Stripe Gateway from loading Stripe.js on product and cart pages when the Payment Request Button (Apple Pay / Google Pay) is disabled in the Stripe settings.
Login Page
- Hide Login Error Details – WordPress returns different errors for “unknown username” vs “incorrect password”, letting attackers confirm which usernames exist. Replaces all messages with a single generic response. Enabled by default.
- Disable Email Login – WordPress 4.5+ allows login with an email address. On sites where emails are publicly visible this widens the brute-force surface. Enforces username-only login.
- Remove Register Link – Removes the “Register” link from the login page without disabling registration itself. Useful for invite-only setups with a direct registration URL.
- Remove Language Switcher – WordPress 5.9+ adds a locale switcher to the login form. Removes it on single-language sites.
A nod to YSlow
In 2007 Yahoo! released YSlow – a browser tool that graded pages against a checklist of performance rules: fewer HTTP requests, smaller payloads, nothing the browser didn’t ask for. Steve Souders and the Yahoo! Exceptional Performance team gave the whole industry a shared vocabulary for why pages were slow, and a practical list of things to fix.
Browsers got faster. Servers got faster. Bandwidth got cheaper. The fundamentals didn’t change.
The Off Switch is, in spirit, a YSlow checklist applied to what WordPress ships by default. The fastest request is still the one that never happens.
What it doesn’t do
- No caching – use a dedicated caching plugin for that.
- No CDN – use Cloudflare, BunnyCDN, or your host’s CDN.
- No .htaccess writes – pure PHP hooks, works on any host including managed hosting.
- No upsell. No Pro version. No phone-home.
How it works
Every toggle is a named WordPress hook removal or filter.
You can read the entire logic in one file per module.
No compiled assets. No build step. No obfuscation.
Who it’s for
Developers and agencies who know what these features do – and know their site doesn’t need them.
Not sure what a toggle does? Leave it off. Each one is independent.
Installation
- Upload
wp-avoid-slowto/wp-content/plugins/ - Activate through the Plugins menu
- Go to Settings -> Off Switch
- Turn off what you don’t need
FAQ
-
Will this break my site?
-
Each toggle is independent. Safe defaults are on. Risky ones (jQuery Migrate, defer JS, scripts to footer) are off by default.
If something breaks – turn that toggle off. Nothing is written to disk. -
Does it work on managed hosting (WP Engine, Kinsta, Pressable)?
-
Yes. Pure PHP hooks, no .htaccess required.
-
Should I disable XML-RPC?
-
Only if you don’t use Jetpack, the WordPress mobile app, or any XML-RPC client.
When in doubt, leave it off. -
Test on staging first. These two are the most likely to cause issues on complex sites – some themes and plugins rely on scripts being available synchronously in
<head>. -
Does it cache pages?
-
No. This plugin removes unused WordPress features. For page caching, use a dedicated plugin.
-
Does it work on WordPress Multisite?
-
Not currently. The plugin is designed and tested for single-site WordPress installs. Multisite support is planned for a future release.
-
Does it work with WooCommerce?
-
Yes. When WooCommerce is active, a WooCommerce section appears in Settings -> Off Switch with 9 dedicated toggles for removing WooCommerce frontend overhead. None of the core toggles touch WooCommerce – each module is independent.
-
How is this different from other performance plugins?
-
Most performance plugins add things – caching layers, CDN routing, minification pipelines.
This one removes things. It’s a different job.
Anmeldelser
Bidragsydere & udviklere
“The Off Switch (formerly WP Avoid Slow)” er open source-software. Følgende personer har bidraget til dette plugin.
BidragsydereOversæt “The Off Switch (formerly WP Avoid Slow)” til dit eget sprog.
Interesseret i udvikling?
Gennemse koden, tjek SVN repository, eller abonner på udviklerloggen via RSS.
Ændringslog
1.9.1
- New: Redirect Unauthenticated Admin Access – redirect unauthenticated /wp-admin/ requests to the homepage instead of the login page; AJAX, Cron, WP-CLI, and admin-post.php unaffected (default OFF)
- Total: 67 independent toggles across 9 modules (58 core + 9 WooCommerce)
1.9.0
- New module: Login Page – 4 toggles for hardening the WordPress login page (Module 9)
- New: Hide Login Error Details – replace specific error messages with a generic response to prevent username enumeration (default ON)
- New: Disable Email Login – enforce username-only login, reject email addresses as login identifiers (default OFF)
- New: Remove Register Link – remove the “Register” link from the login page without disabling registration (default OFF)
- New: Remove Language Switcher – remove the locale dropdown from the login form on single-language sites (WP 5.9+, default OFF)
- Total: 66 independent toggles across 9 modules (57 core + 9 WooCommerce)
1.8.0
- New: Recent Comments Inline CSS – remove the inline
<style>block the Recent Comments widget outputs in<head>(default OFF) - New: Reduce Trash Retention – reduce trash retention from 30 days to 7 via the empty_trash_days filter (default OFF)
- New: Restrict REST API to Logged-In Users – block unauthenticated REST API access; third-party auth methods unaffected (default OFF)
- Total: 62 independent toggles across 8 modules (53 core + 9 WooCommerce)
1.7.0
- New: WC Block Patterns – unregister WooCommerce block patterns from the editor inserter (default OFF)
- New: WC Legacy Widgets – unregister 12 default WooCommerce legacy widgets on every page load (default OFF)
- New: WC Version Header – remove X-WooCommerce-Version from HTTP response headers (default ON)
- New: Stripe Gateway Scripts – prevent Stripe.js loading when Payment Request Button is disabled (default OFF)
- Total: 59 independent toggles across 8 modules (50 core + 9 WooCommerce)
1.6.0
- New module: WooCommerce – 5 toggles for removing WooCommerce frontend overhead (only visible when WooCommerce is active)
- New: Cart Fragments – removes wc-cart-fragments when the Cart Widget renders (default OFF)
- New: WooCommerce Generator Tag – removes WooCommerce version from <meta name=”generator”> via correct get_the_generator_html filter (default ON)
- New: WC Scripts on Non-WC Pages – dequeues WooCommerce CSS/JS including wc-add-to-cart and woocommerce-blocktheme (block themes) on non-shop pages (default OFF)
- New: Password Strength Meter – secondary safety net removing wc-password-strength-meter outside checkout and My Account (default OFF)
- New: Status Dashboard Widget – removes WooCommerce Status widget from wp-admin dashboard (default OFF)
- Improvement: plugin boot now runs at plugins_loaded priority 20 so WooCommerce is always loaded before the boot function fires
- Total: 55 independent toggles across 8 modules (50 core + 5 WooCommerce)
1.5.0
- New module: Block Editor – 5 toggles for controlling what Gutenberg loads
- New: Remote Block Patterns – disables api.wordpress.org pattern fetch on editor load (default ON)
- New: Core Block Patterns – removes built-in patterns from the Pattern inserter (default OFF)
- New: Block Directory – removes block search and install from the editor (default ON)
- New: Font Library – disables Font Library panel in Site Editor (WP 6.5+, default OFF)
- New: Widget Block Editor – restores classic Widgets screen instead of block-based editor (WP 5.8+, default OFF)
- Total: 50 independent toggles across 7 modules
1.4.0
- New module: Admin Hardening – 8 security and admin cleanup toggles across a new dedicated section
- New: Block User Enumeration – intercepts ?author=N redirects that expose usernames (default ON)
- New: Disable Author Archives – redirects /author/username/ pages to homepage (default OFF)
- New: Disable File Editor – defines DISALLOW_FILE_EDIT to remove plugin/theme code editor (default OFF)
- New: Disable Application Passwords – removes Application Passwords UI and token acceptance (default OFF)
- New: Suppress Admin Email Check – disables the periodic admin email confirmation nag (default ON)
- New: Remove X-Pingback Header – strips X-Pingback from all HTTP responses (default ON)
- New: Clean Admin Bar – removes WP logo, Visit Site link, and admin bar search (default OFF)
- New: Hide Update Nag for Non-Admins – hides core update notices from editors and contributors (default OFF)
- Total: 45 independent toggles across 6 modules
1.3.0
- New: Disable All Feeds toggle – redirects /feed/ and all feed URLs to homepage (default OFF)
- New: Comment Auto-Links toggle – removes make_clickable() pass on every comment (default OFF)
- New: Editor Autosave toggle – deregisters autosave script in post editor (default OFF)
- New: DNS Prefetch toggle – removes all wp_resource_hints from <head> (default OFF)
- Total: 37 independent toggles across 5 modules
1.2.1
- Rebrand: plugin display name changed to “The Off Switch” (slug, code, and all settings are unchanged – no migration needed for existing installs)
- New: live search / filter box on the settings page – type to instantly filter toggles across all modules
- New: “NEW” badge on the 3 toggles added in 1.2.0 (REST API Discovery Link, RSS Feed Links, Speculation Rules)
- New: WordPress version gating – the Speculation Rules toggle is automatically disabled with a notice on WordPress older than 6.8
- Total: 33 independent toggles across 5 modules
1.2.0
- New: REST API Discovery Link toggle – removes
<link rel="https://api.w.org/">from<head>(default ON) - New: RSS Feed Links toggle – removes RSS autodiscovery
<link>tags from<head>(default OFF) - New: Speculation Rules toggle – disables WP 6.8+ prefetch/prerender JSON output (default OFF)
- Improvement: Asset Query Strings now also covers WP 6.5+ Script Modules (
script_module_loader_srcfilter) – no new toggle needed - Fix:
customize-supportscript handle added to protected list – was incorrectly deferred or moved to footer when Defer JS or Move Scripts to Footer were enabled - Reviewed against WordPress 6.9.1 source – all new default frontend outputs assessed; no other unaddressed bloat found
- Total: 33 independent toggles across 5 modules
1.1.1
- Fix: new toggles introduced in 1.1.0 were showing as off after upgrading from an older version instead of their correct defaults
- Fix: activation hook now merges new option keys into existing settings on upgrade – existing user choices are never overwritten
- Fix: settings page now merges with defaults before rendering so new toggles always display their intended state even if the stored option row is from an older version
- Fix: active switch counter in the page header now counts correctly after an upgrade
1.1.0
- New module: WordPress Behaviour Tweaks – disable self-pingbacks, remove Capital P filter, limit post revisions to 3, redirect attachment pages to parent post
- New module: Image Performance – Google Fonts display:swap, auto-add missing image dimensions (fixes CLS), LCP fetchpriority, lazy load images, disable PDF thumbnail generation
- readme: added multisite FAQ (not yet supported)
- readme: added tribute to YSlow philosophy
- Tested up to WordPress 6.9.1
- Total: 26 independent toggles across 4 modules
1.0.0
- Complete rewrite – no longer depends on .htaccess
- 17 independent toggles across two modules, pure PHP hooks
- Module 1: The Off Switches – emoji, embeds, RSD, WLW manifest, version tag, shortlink, query strings, XML-RPC, Heartbeat, Dashicons
- Module 2: Script & Style Control – jQuery Migrate, Block Library CSS, Global Styles, SVG Duotone, type attributes, defer JS, move scripts to footer
- Admin UI: CSS toggle switches replacing checkboxes
- Works on any host including managed hosting
- Ships with safe defaults – risky toggles are off until you opt in
- Settings -> Avoid Slow admin page
0.4
- Minor fixes
0.3
- Minor fixes
0.2
- Expire cache fix
0.1
- Initial release – .htaccess Expires headers + ETags
