Welcome to HowToShipIt — practical how-to guides for developers: code, AI tools, and servers, explained step by step.

How to Speed Up WordPress Without Plugins: 9 Manual Fixes That Actually Work

Speed plugins are not magic. They are mostly a convenient wrapper around a handful of things you can do yourself: caching headers, removing scripts you never asked for, shrinking images, and cleaning up a messy database. If you want to speed up WordPress without plugins, this guide walks you through nine manual fixes — each with the exact code and the exact clicks — that together can shave seconds off your load time and lift your Core Web Vitals scores.

You need nothing installed. You need an FTP client or your host’s file manager, five minutes of patience, and the willingness to back things up before touching code. Everything here is verified against current WordPress behavior as of October 2026.

1. Switch to a lightweight theme

This is the single biggest lever most sites ignore. A bloated multipurpose theme can add 200KB of CSS and a dozen JavaScript files before you have written a single word. No caching plugin fixes that — it just caches the bloat.

Before switching, test any theme candidate on PageSpeed Insights using its live demo. If the demo scores badly, your site will too. Lightweight, performance-first options include GeneratePress, Astra, Blocksy, and the default block themes like Twenty Twenty-Four. Avoid themes that bundle sliders, animation libraries, and page builders you will never use.

2. Optimize images before you upload them

Images are usually 60–80% of a page’s weight, and they are the easiest win. You don’t need an optimization plugin — you need a habit:

  • Resize before uploading. If your content column is 760px wide, don’t upload a 4000px photo. Most themes cap the content container around 1200px, so anything wider is wasted bandwidth.
  • Convert to WebP. WebP images are typically 25–35% smaller than JPEG or PNG at the same visual quality. Use Squoosh (free, runs in the browser) or ImageMagick: convert input.jpg -quality 85 output.webp.
  • Let lazy loading do its job. WordPress has added loading="lazy" to images automatically since version 5.5. Off-screen images no longer block the initial render — just don’t fight it by forcing all images above the fold.
  • Set width and height attributes. This reserves space so images don’t shove text around while loading, which directly improves your Cumulative Layout Shift score.

A 400KB PNG frequently becomes a 70KB WebP. Do that to ten images and you just deleted half a megabyte from every page load.

3. Remove the scripts and styles you never asked for

WordPress ships with features you probably don’t use, and each one costs an HTTP request or a render-blocking script:

  • Emoji detection script — loads on every page so emojis render in old browsers.
  • Dashicons — the admin icon font, often loaded on the frontend for logged-out visitors who never see it.
  • oEmbed discovery — auto-embed support you can skip if you rarely paste URLs into posts.
  • RSD and WLW manifest links — legacy leftovers for long-dead desktop blogging clients.

Add this to your child theme’s functions.php (never the parent theme — updates will wipe it):

// Disable emojis
function hs_disable_emojis() {
    remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
    remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
    remove_action( 'wp_print_styles', 'print_emoji_styles' );
    remove_action( 'admin_print_styles', 'print_emoji_styles' );
    remove_filter( 'the_content_feed', 'wp_staticize_emoji' );
    remove_filter( 'comment_text_rss', 'wp_staticize_emoji' );
    remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' );
    add_filter( 'emoji_svg_url', '__return_false' );
}
add_action( 'init', 'hs_disable_emojis' );

// Drop Dashicons for logged-out visitors
function hs_no_dashicons_frontend() {
    if ( ! is_admin() && ! is_user_logged_in() ) {
        wp_deregister_style( 'dashicons' );
    }
}
add_action( 'wp_enqueue_scripts', 'hs_no_dashicons_frontend', 100 );

// Remove header junk
remove_action( 'wp_head', 'rsd_link' );
remove_action( 'wp_head', 'wlwmanifest_link' );
remove_action( 'wp_head', 'wp_generator' );
remove_action( 'wp_head', 'wp_oembed_add_discovery_links' );

One note: disabling emojis means old browsers fall back to text smileys. On any modern browser, you will notice zero difference.

4. Tame the Heartbeat API

The WordPress Heartbeat API pings your server every 15–60 seconds while you have the admin open — autosave checks, post locking, login expiry. On the frontend it mostly adds noise, and on shared hosting those AJAX requests add up. Slow it down instead of killing it outright (disabling it entirely breaks autosave):

// Slow the Heartbeat API to one request per minute
add_filter( 'heartbeat_settings', function( $settings ) {
    $settings['interval'] = 60;
    return $settings;
} );

If you never write long posts, you can go further and disable Heartbeat on the frontend only — but the 60-second interval is the safe default.

5. Defer non-essential JavaScript

Render-blocking JavaScript is one of the biggest Core Web Vitals killers. A script with the defer attribute downloads in the background and executes after the HTML is parsed — the page renders first, scripts run second.

You can add defer to your theme’s scripts from functions.php:

// Defer non-essential frontend scripts
add_filter( 'script_loader_tag', function( $tag, $handle ) {
    if ( is_admin() ) {
        return $tag;
    }
    // Never defer jQuery or the admin bar — things break
    $skip = array( 'jquery-core', 'jquery-migrate', 'admin-bar' );
    if ( in_array( $handle, $skip, true ) ) {
        return $tag;
    }
    return str_replace( ' src', ' defer src', $tag );
}, 10, 2 );

Test your site thoroughly after this one — especially contact forms, sliders, and anything interactive. If something breaks, add its script handle to the $skip array.

6. Add browser caching with .htaccess

If your host runs Apache (most shared hosts do), add these rules above the # BEGIN WordPress line in your site’s root .htaccess file. Back the file up first — a typo here can take your site down:

# BEGIN Browser Caching
<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresByType image/jpg "access plus 1 year"
    ExpiresByType image/jpeg "access plus 1 year"
    ExpiresByType image/png "access plus 1 year"
    ExpiresByType image/gif "access plus 1 year"
    ExpiresByType image/webp "access plus 1 year"
    ExpiresByType text/css "access plus 1 month"
    ExpiresByType application/javascript "access plus 1 month"
    ExpiresByType font/woff "access plus 1 year"
    ExpiresByType font/woff2 "access plus 1 year"
    ExpiresByType image/x-icon "access plus 1 year"
    ExpiresByType application/pdf "access plus 1 month"
</IfModule>
# END Browser Caching

This tells returning visitors’ browsers to reuse static files instead of re-downloading them. Run PageSpeed Insights again — the “use efficient cache lifetimes” warning should shrink or disappear. If your site 500-errors after saving, restore the backup immediately; you likely have a syntax error.

7. Clean up the database manually

Over time your database fills with post revisions, spam comments, and expired transients. Every query WordPress runs gets a little slower. You can clean this with three queries in phpMyAdmin — back up your database first, and replace wp_ with your actual table prefix:

DELETE FROM wp_posts WHERE post_type = 'revision';
DELETE FROM wp_comments WHERE comment_approved = 'spam';
DELETE FROM wp_options WHERE option_name LIKE '_transient_%';

Then use phpMyAdmin’s “Optimize table” on the big tables to reclaim space. Going forward, limit revision buildup in wp-config.php:

define( 'WP_POST_REVISIONS', 3 );

8. Put a CDN in front of everything

A content delivery network serves your static files from servers near your visitors. It is the single biggest speedup for international traffic, and it requires zero plugins — just a DNS change at your registrar.

Cloudflare’s free plan gives you a global CDN, shared SSL, and basic DDoS protection at no cost. Sign up, add your site, change your nameservers to Cloudflare’s, and turn on “Auto Minify” and a browser cache TTL in the Caching tab. Bunny.net is a strong paid alternative if you want a pure CDN without the proxy layer.

9. Keep PHP current

Each major PHP release gets measurably faster at executing WordPress. If your host still defaults you to PHP 7.x, you are leaving free performance on the table. Check your version under Tools → Site Health → Info → Server, and switch to the newest version your host offers that your theme and plugins support. This one change can cut server response time by 20–30% with zero code changes.

Measure before and after

Don’t optimize blind. Before changing anything, run PageSpeed Insights and note your mobile score, Largest Contentful Paint, and Cumulative Layout Shift. Then apply the fixes one at a time and re-test. That way you know which change earned which improvement — and you can roll back anything that didn’t help.

Verified October 1, 2026. All code snippets tested against current WordPress behavior; always back up your site and database before editing theme files, .htaccess, or running SQL.

Further Reading & References

Leave a Comment