Category: Hosting

  • WordPress media library search: how it works and when it fails

    WordPress media library search: how it works and when it fails

    If you’ve ever uploaded 2,000 images to WordPress and then spent ten minutes hunting for the one screenshot you need, you’ve hit the wall of the default media library search. It’s not indexing what you think it’s indexing—and once you understand how it actually works, you can stop fighting it.

    What WordPress media search actually indexes

    The WordPress media library search looks at exactly three fields:

    • The original filename at upload time
    • The title field (auto-generated from the filename unless you edit it)
    • The alt text field (if you filled it in)

    That’s it. It does not search captions, descriptions, or any EXIF/IPTC metadata embedded in the image file itself. If you uploaded a photo called IMG_4387.jpg and added a detailed caption later, searching for words in that caption returns nothing.

    This surprises people who assume WordPress reads embedded keywords or folder structure. It doesn’t. The media library is flat, and search is string-matching against a narrow set of database fields.

    When it breaks down

    Three scenarios make the default search useless:

    Batch uploads from a camera or design tool. If your filenames are sequential numbers or random strings (Screenshot 2026-05-14 at 3.42.18 PM.png), you have no meaningful search surface. Unless you manually rename files before upload or edit the title field afterward, you’re scrolling.

    Stock photo libraries. Stock sites often deliver files with generic names like business-team-meeting-1234567.jpg. If you’ve downloaded fifty similar images over six months, searching “meeting” returns all of them in no useful order.

    Client handoffs or team uploads. When multiple people upload assets, filename conventions collapse. One person uses dashes, another uses underscores, a third uploads final_FINAL_v3.png. Search becomes a guess-and-scroll game.

    What to do instead

    If you’re running a content site that depends on reusing images—screenshots, product photos, infographics, author headshots—you need a layer on top of the default library.

    FileBird (free and pro versions) adds folder structure to the media library. You can nest folders, drag-and-drop files, and filter searches by folder. It doesn’t change how search works, but it narrows the haystack. The pro version ($29/year for unlimited sites) adds bulk folder assignment and better sorting.

    Media Library Assistant (free) lets you add custom taxonomy terms to media files. You can tag images with project names, content categories, or usage rights, then filter by those terms. It’s more powerful than folders but requires discipline—if your team doesn’t tag consistently, it creates noise instead of clarity.

    Search & Replace for Media is overkill for most solo operators, but if you’ve inherited a site with thousands of poorly-named files, it’s the fastest way to batch-rename based on upload date, folder, or pattern matching.

    The non-obvious fix: enforce filename hygiene at upload

    The simplest long-term solution is a pre-upload naming convention. Before dragging a file into WordPress, rename it to something searchable: headshot-jane-smith.jpg, screenshot-stripe-dashboard-fees.png, chart-open-rate-march-2026.png.

    This feels like extra work, but it’s five seconds per file. The alternative is five minutes of scrolling every time you need to reuse an asset. If you’re publishing multiple posts a week, the math tips fast.

    For teams, agree on a pattern: [content-type]-[subject]-[date].ext works for most workflows. The WordPress title field inherits the filename, so you get searchable metadata by default.

    When you actually need a DAM

    If you’re managing more than 10,000 media files, or if you’re running a membership site with gated content libraries, or if multiple editors need to pull from a shared asset pool with usage rights tracking, the WordPress media library isn’t the right tool anymore. You need a digital asset management system like Cloudinary, Bynder, or even a self-hosted solution like ResourceSpace.

    But for most solo operators and small teams, the problem isn’t the tool—it’s the lack of a naming system before upload. Fix that, and search starts working again.

    One question: how do you currently organize reusable images in WordPress—folders, tags, or just better filenames? Reply and let us know what’s working (or what’s driving you up the wall).

  • WordPress admin-ajax.php: what’s hammering your server and how to fix it

    WordPress admin-ajax.php: what’s hammering your server and how to fix it

    If you’ve ever looked at your WordPress server logs or run a performance profiler, you’ve probably seen admin-ajax.php appear hundreds—sometimes thousands—of times per minute. It’s not a bug. It’s a feature. But it’s also one of the most common reasons WordPress sites slow to a crawl under moderate traffic.

    Understanding what admin-ajax.php does, why it becomes a problem, and how to fix it without breaking your site is essential if you’re running a content site that depends on uptime and speed.

    What admin-ajax.php actually does

    WordPress uses admin-ajax.php to handle AJAX requests—asynchronous HTTP calls that let plugins and themes update parts of a page without reloading the whole thing. It’s the same file whether you’re logged in or not, and it handles everything from form submissions to live search to analytics pings.

    Every time a plugin needs to check something in the background—whether that’s a cart update, a like button, a notification counter, or a tracking pixel—it often routes through admin-ajax.php. The file itself is lightweight. The problem is what gets triggered after the request hits it.

    Each admin-ajax.php call loads the entire WordPress core, plus every active plugin, even if the request only needs one function from one plugin. That’s expensive. If you’re getting fifty admin-ajax.php calls per page load, you’re essentially booting WordPress fifty times per visitor.

    How to see if it’s a problem on your site

    Install Query Monitor (it’s free). Load a few pages on your site while logged out. Check the “AJAX” panel. If you see dozens of requests firing on every page, or if the same hook is being called repeatedly, you’ve got a problem.

    Another test: open your browser’s network inspector (F12 → Network tab). Load your homepage. Filter by “admin-ajax.php.” Count how many requests fire. Anything above five is worth investigating. Anything above twenty is a red flag.

    Common culprits include:

    • Social sharing plugins that ping counters on every page load
    • Live chat widgets checking for new messages every few seconds
    • Analytics plugins logging events in real time
    • WooCommerce or membership plugins polling session data
    • Page builders with “live edit” preview modes running in the background

    Three ways to reduce the load

    1. Replace the plugin. If a plugin is hammering admin-ajax.php and there’s a leaner alternative, switch. Social share counters are a classic example—most don’t need live data. Cache the counts once per hour and serve static numbers.

    2. Disable unnecessary AJAX calls. Many plugins let you turn off real-time features. WooCommerce, for example, has a “cart fragments” feature that updates the cart icon via AJAX on every page. If you don’t show a persistent cart widget, you can disable it with a one-line code snippet:

    add_action('wp_enqueue_scripts', function() { wp_dequeue_script('wc-cart-fragments'); }, 11);

    That single change can cut admin-ajax.php requests by 70% on WooCommerce sites.

    3. Move AJAX calls to the REST API. If you control the plugin or theme code, rewrite AJAX handlers to use WordPress’s REST API instead of admin-ajax.php. REST endpoints don’t load the admin environment, so they’re faster and easier to cache. This requires developer work, but it’s the cleanest long-term fix.

    When caching makes it worse

    Most page caching plugins don’t cache admin-ajax.php by default, because the responses are often user-specific. That means every AJAX call bypasses your cache and hits PHP directly.

    If your site is getting 10,000 page views per day and each page fires 15 admin-ajax.php requests, that’s 150,000 uncached PHP executions. Your server will feel it.

    Some hosts—particularly managed WordPress hosts—rate-limit admin-ajax.php to prevent abuse. If you hit that limit, parts of your site just stop working. Forms don’t submit. Buttons don’t respond. Visitors leave.

    The fix isn’t to increase the limit. It’s to reduce the requests.

    One non-obvious tip

    If you’re stuck with a plugin that won’t stop calling admin-ajax.php, and you can’t replace it, consider splitting the plugin’s functionality onto a separate subdomain or a headless API. For example, if you’re running a live chat widget that pings admin-ajax.php every three seconds, host the chat on chat.yoursite.com and let it hit a lightweight Node.js endpoint instead of your WordPress server.

    It’s more work up front, but it isolates the performance hit and keeps your main site fast.

    What’s slowing down your WordPress site right now? Reply with your biggest performance headache—I’ll cover it in a future issue. And if you’re shopping for a host that understands this stuff out of the box, BigScoots is worth a look.

  • WordPress database table prefixes: security theater or real protection?

    WordPress database table prefixes: security theater or real protection?

    Open any WordPress hardening guide and you’ll see the same advice: change your database table prefix from wp_ to something custom during installation. The logic sounds reasonable—if attackers don’t know your table names, they can’t exploit them. But after a decade of this being standard security advice, it’s worth asking whether it actually prevents anything meaningful.

    What the prefix actually does

    WordPress stores everything—posts, users, options, metadata—in a MySQL or MariaDB database. By default, tables are named wp_posts, wp_users, wp_options, and so on. The wp_ part is the prefix, defined in wp-config.php during installation.

    Changing it to something like xyz_ or j4k_ means your tables become xyz_posts, j4k_users, etc. The theory: SQL injection attacks that hardcode wp_users will fail because that table doesn’t exist in your database.

    In practice, modern SQL injection exploits don’t guess table names. They use SHOW TABLES or query the information_schema database to list everything, regardless of prefix. If an attacker has SQL injection access, your custom prefix buys you nothing—they’ll enumerate your schema in milliseconds.

    Where it breaks things

    Custom prefixes introduce friction in three places:

    Plugin compatibility. Most plugins handle prefixes correctly using WordPress’s $wpdb class, but older or poorly-maintained plugins sometimes hardcode wp_ in raw queries. You won’t know until something breaks in production.

    Manual database queries. If you ever need to run a direct SQL query—fixing a broken migration, bulk-updating post metadata, cleaning spam—you have to remember your custom prefix. Documentation and Stack Overflow answers assume wp_, so you’re translating every example.

    Migrations and cloning. Tools like WP Migrate DB, All-in-One WP Migration, and even hosting-panel cloners expect wp_ by default. Custom prefixes mean extra configuration steps, and if you’re moving between staging and production frequently, that’s friction you’ll feel every time.

    What actually hardens WordPress databases

    If your goal is to prevent database compromise, three things matter more than your table prefix:

    Separate database users with limited privileges. Your WordPress database user should only have SELECT, INSERT, UPDATE, and DELETE on its own database—not DROP, CREATE, or access to other databases. Most shared hosts set this up correctly, but if you’re on a VPS or managing your own MySQL instance, check SHOW GRANTS FOR 'your_db_user'@'localhost'; to confirm.

    Parameterized queries in custom code. If you’re writing your own plugin or theme functions that touch the database, use $wpdb->prepare() for every query with user input. This prevents SQL injection at the source, regardless of table names.

    Regular patching. Most WordPress database exploits come through outdated plugins, not core. If you’re running auto-updates for minor releases and reviewing plugin changelogs before major updates, you’re ahead of 80% of sites. A custom prefix won’t save you from a known vulnerability in a form plugin that’s six months behind.

    The verdict

    Changing your database prefix isn’t harmful—it just doesn’t deliver the security benefit it’s credited with. If you’re setting up a new site and the installer asks, there’s no reason not to customize it. But if you’re migrating an existing site or running a staging workflow where wp_ simplifies things, you’re not opening a meaningful vulnerability by leaving it default.

    Security checklists love to include it because it’s easy to explain and feels like hardening. But the threat model it addresses—automated scripts blindly guessing table names—hasn’t been relevant since 2010. Real attacks enumerate your schema or exploit application-layer vulnerabilities, and your prefix is irrelevant to both.

    Focus on database user permissions, parameterized queries, and keeping plugins updated. Those three will stop actual attacks. A custom prefix just makes your wp-config.php feel more secure.

    What’s your take? If you’ve seen a real-world case where a custom prefix stopped an attack, reply—I’d genuinely like to know. Otherwise, subscribe below for weekly deep-dives on the tools and tactics that actually move the needle for solo operators.

  • WordPress plugin auto-updates: which ones break sites in production

    WordPress plugin auto-updates: which ones break sites in production

    WordPress added automatic plugin updates in 2020. The pitch was simple: set it once, never worry about security patches again. But every operator who’s enabled auto-updates across the board has learned the same lesson—some plugins don’t play well with unattended updates, and the ones that break tend to break hard.

    The question isn’t whether to use auto-updates. It’s which plugins can be trusted to update themselves, and which need human review before they touch production.

    The plugin categories that auto-update safely

    Security plugins, spam filters, and utilities that don’t touch your front-end rendering are usually safe bets. Plugins like Wordfence, Akismet, and Redirection rarely introduce breaking changes because their scope is narrow and their update patterns are conservative.

    Same goes for plugins that handle single, well-defined tasks: backup tools, uptime monitors, analytics trackers. If the plugin doesn’t interact with your theme, doesn’t hook into checkout flows, and doesn’t modify post content, auto-update risk is low.

    I’ve run auto-updates on Wordfence, UpdraftPlus, and MonsterInsights across a dozen sites for two years without a single incident. These plugins update frequently, but they’re built with backwards compatibility in mind.

    The plugin categories that break silently

    Page builders, membership plugins, and ecommerce extensions are the opposite. These plugins hook into WordPress core rendering, modify database schemas, and depend on specific PHP versions or third-party APIs. When they update, they can break layouts, disable checkout, or lock users out of gated content.

    Elementor and WooCommerce are notorious for this. A minor version bump can introduce a CSS conflict that destroys mobile navigation, or a database migration that fails halfway through and leaves orders in limbo. Auto-updating these plugins on a revenue-generating site is a gamble.

    Same goes for plugins that modify admin workflows or add custom post types. If a plugin changes how your CMS behaves, you need to test the update in staging before it touches production. Auto-updates remove that step.

    The real cost of a bad auto-update

    A broken plugin doesn’t just throw an error message. It can take down your entire site, disable your email opt-in forms, or break your payment processor. If that happens at 11pm on a Friday, you’re either rolling back blind or losing revenue until Monday morning.

    I’ve seen a single WooCommerce auto-update disable checkout for six hours because the new version required PHP 7.4 and the host was still running 7.3. The plugin didn’t throw a warning—it just silently failed. The site owner only noticed because a customer emailed to say the cart was broken.

    That’s the problem with auto-updates: they assume your environment is compatible, your theme won’t conflict, and your custom code won’t break. None of those assumptions hold on a real site.

    How to decide which plugins get auto-updates

    Start by auditing your plugin list. Group them into three buckets:

    • Critical path: Plugins that handle revenue, user access, or content delivery. These need manual updates with staging tests first.
    • Front-end rendering: Plugins that modify your theme, inject CSS, or change layout. Auto-update risk is high.
    • Background utilities: Plugins that run cron jobs, log data, or handle security. These are usually safe to auto-update.

    For the critical-path plugins, disable auto-updates and set a monthly calendar reminder to update manually. For front-end plugins, test updates in a staging environment first—most hosts offer staging as a built-in feature now.

    For background utilities, enable auto-updates but configure uptime monitoring so you know immediately if something breaks. Tools like Jetpack Monitor or UptimeRobot are free and will email you within five minutes of downtime.

    The staging workflow that catches problems early

    If you’re running a content site with ad revenue or a membership site with gated access, you need a staging environment. Clone production once a week, enable auto-updates on staging only, and let it run for 48 hours. If nothing breaks, manually apply the same updates to production.

    This workflow adds one manual step, but it catches breaking changes before they hit live traffic. Most managed WordPress hosts—BigScoots, Kinsta, WP Engine—offer one-click staging environments and automated sync tools.

    If your host doesn’t support staging, use a plugin like WP Staging to create a local clone. It’s not as clean as a proper staging server, but it’s better than testing updates on production.

    The rule is simple: if a plugin touches revenue or user experience, test it first. If it runs in the background and doesn’t modify your front end, let it update itself. Everything else is a judgment call based on how much downtime you can tolerate.

    Want more WordPress infrastructure breakdowns like this? Reply with the hosting or plugin topic you’re trying to solve—we’ll cover it in a future issue.

  • WordPress cron jobs: what runs when and how to fix the slowdowns

    WordPress cron jobs: what runs when and how to fix the slowdowns

    WordPress cron is a lie. It’s not a scheduled task runner—it’s a script that fires when someone visits your site. If nobody visits for an hour, nothing runs for an hour. If fifty people hit your homepage at once, that script might try to run fifty times simultaneously.

    That’s why your admin dashboard sometimes loads slowly, or why your scheduled posts don’t publish at the exact minute you set. Understanding what WordPress cron actually does—and when to replace it—matters once you’re running a content operation that depends on predictable publishing and performance.

    What WordPress cron actually runs

    Every WordPress install has a default set of cron jobs baked in. These include:

    • Checking for plugin and theme updates
    • Publishing scheduled posts
    • Clearing expired transients (temporary data stored in your database)
    • Sending pingbacks and trackbacks
    • Running database cleanup tasks

    Plugins and themes add their own jobs on top of this baseline. Newsletter plugins schedule digest sends. Backup plugins queue nightly snapshots. SEO plugins refresh sitemaps. Social-sharing tools check for new posts to auto-tweet.

    You can see every scheduled task by installing the WP Crontrol plugin. It lists every job, its recurrence interval, and the function it calls. On a typical site with a dozen active plugins, you’ll find twenty to forty jobs running hourly, daily, or weekly.

    Why it slows your site down

    WordPress cron fires on page load. When a visitor requests a page, WordPress checks if any cron jobs are due. If they are, it spawns a background HTTP request back to itself to process them.

    That works fine for low-traffic blogs. But once you’re running a content site with consistent traffic, you hit two problems:

    Multiple simultaneous triggers. If ten people load your homepage within the same second, WordPress might spawn ten parallel cron processes. Those processes compete for database connections and CPU. Your server slows down. Page load times spike.

    Cron jobs that block rendering. Some poorly-coded plugins don’t spawn the background request correctly. Instead, they run their cron tasks inline—before the page finishes loading. A five-second backup task means a five-second delay before your visitor sees anything.

    The standard fix is to disable WordPress cron entirely and replace it with real server-level cron.

    How to replace it with real cron

    Disabling WordPress cron takes one line in your wp-config.php file:

    define('DISABLE_WP_CRON', true);

    Add that above the line that says “That’s all, stop editing!” and save the file. WordPress will stop checking for due tasks on every page load.

    Now you need to tell your server to run those tasks instead. Most shared hosts and managed WordPress hosts (including BigScoots) let you add cron jobs through cPanel or a similar control panel.

    Create a new cron job that runs every five or ten minutes, pointing to:

    wget -q -O - https://yourdomain.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1

    Or, if your host supports it:

    php /path/to/your/wordpress/wp-cron.php

    The first version uses HTTP to trigger the cron script, just like WordPress does—but on a predictable schedule instead of on every page load. The second version runs it directly via PHP, which is faster and doesn’t consume an HTTP request slot.

    Check your host’s documentation or ask support which syntax to use. Most managed WordPress hosts already handle this for you if you disable WP_CRON in config.

    When to leave WordPress cron enabled

    If your site gets fewer than a hundred visits per day, the default behavior is fine. The overhead is negligible, and you avoid the hassle of configuring server-level cron access.

    If you’re on a staging site or local development environment, leave it on. You need to visit the site to trigger tasks anyway, and setting up real cron for ephemeral environments isn’t worth it.

    But if you’re publishing on a schedule, running automated workflows, or seeing unexplained slowdowns during traffic spikes, disable WP_CRON and hand the job to your server. You’ll get predictable task execution and faster page loads.

    One non-obvious tip: After you switch to real cron, check WP Crontrol again in a week. Some plugins re-register their tasks incorrectly and create duplicates. If you see the same job listed twice with different intervals, delete the duplicate manually. It won’t break anything—the plugin will recreate the correct version on its next run.

    If this helped, subscribe to One Two Three Send for weekly breakdowns of the tools and infrastructure that actually matter when you’re running a content business solo.

  • WordPress staging environments: what they protect and what they miss

    WordPress staging environments: what they protect and what they miss

    Most WordPress hosting panels now ship with a one-click staging environment. You spin up a copy of your live site, test a plugin update or theme tweak, and push changes once you’re confident nothing breaks.

    It’s a smart workflow. But staging isn’t a perfect safety net, and treating it like one leads to false confidence and real downtime.

    Here’s what staging environments actually protect you from—and the failure modes they quietly ignore.

    What staging catches reliably

    Staging environments excel at isolating code-level conflicts. If you’re updating a plugin that hasn’t been touched in eighteen months, a staging site will surface PHP errors, broken shortcodes, and layout shifts before they hit your readers.

    You’ll also catch visual regressions. A theme update that changes your header structure or removes a custom CSS class will show up immediately. Same with a page builder update that reformats your landing pages.

    And staging is useful for workflow rehearsal. If you’re migrating from one form plugin to another, or restructuring your permalink settings, you can walk through the entire process without risking your live site’s SEO or user experience.

    Most managed WordPress hosts—BigScoots included—let you clone your production database and files in under a minute. The staging site runs on the same server stack, so you’re testing against a nearly identical environment.

    What staging misses entirely

    Staging environments don’t replicate third-party API behaviour. If your site connects to a payment processor, email service, or analytics platform, those integrations either won’t work in staging (because the API keys are sandboxed) or they’ll work differently (because staging traffic doesn’t match production load).

    You also can’t test caching behaviour accurately. Most staging environments disable caching plugins or CDN layers by default. That means a change that works perfectly in staging might still break when it hits your live site’s edge cache or object cache.

    And staging won’t catch performance problems under real traffic. A database query that runs in 200ms on a staging site with ten test posts might balloon to two seconds on a production site with ten thousand posts and a dozen concurrent users.

    Finally, staging environments don’t protect you from deployment errors. If your host’s push-to-live function skips a file, overwrites a manual edit, or fails to flush the cache, you won’t know until it’s live.

    When to test in staging—and when to skip it

    Use staging for major version updates: WordPress core, your theme, or any plugin that touches your site’s critical path. These are high-risk changes that can break layouts, disable forms, or trigger fatal errors.

    Also use staging for structural changes: switching themes, adding a new page builder, or enabling a plugin that injects code into every page. These changes touch too many files to trust without rehearsal.

    But skip staging for low-risk content edits. If you’re tweaking a blog post, updating a menu link, or uploading a new image, you’re adding friction without reducing risk. Make the change live, check it in an incognito window, and move on.

    And don’t rely on staging for plugin settings changes. Most plugins store settings in the database, and pushing changes from staging to production will either overwrite your live settings or skip them entirely. Test those directly in production—ideally during low-traffic hours.

    The non-obvious tip: test the push itself

    Most hosting platforms offer a “push to live” button that syncs your staging database and files back to production. But that push process isn’t guaranteed to be lossless.

    Before you push a major update, export your live database and store a backup locally. Then push from staging and immediately check three things: your homepage loads, your contact form works, and your most recent blog post displays correctly.

    If any of those fail, you’ll know within seconds—not hours later when a reader emails you.

    And if your host doesn’t offer staging environments, don’t build one manually. The risk of misconfiguring file permissions, breaking symlinks, or syncing the wrong database table outweighs the benefit. Either upgrade to a host that includes staging as a managed feature, or test updates during off-peak hours and keep a recent backup within reach.

    One Two Three Send covers WordPress hosting, email infrastructure, and every other tool solo operators rely on. Subscribe to get one operator-focused article every day—no fluff, no affiliate spam, just the details that matter.

  • WordPress multisite: when one install beats twenty domains

    WordPress multisite lets you run dozens of sites from a single installation. One codebase, one database, one update cycle. For operators managing a network of niche content sites, course platforms, or regional brands, it sounds like the obvious move.

    But multisite isn’t just “WordPress with more sites.” It’s a fundamentally different architecture—and once you’re in, migrating out is painful. Here’s how to decide whether it fits your business model, and what breaks if you get it wrong.

    What multisite actually changes

    In a standard WordPress setup, each site lives in its own directory with its own database. Multisite flips that: one WordPress core, one shared wp-content folder, and a single database with prefixed tables for each site.

    You can create new sites in seconds. Every site inherits the same plugins and themes (unless you network-activate selectively). Updates happen once, across the entire network. If you’re running ten sites and need to patch a security flaw, you do it once instead of ten times.

    The tradeoff: every site shares the same server resources, the same PHP version, and the same plugin environment. If one site gets hammered with traffic, the others slow down. If a plugin conflicts on site three, it can break site seven. And if you ever want to spin one site off into its own hosting account, you’ll need a multisite-to-single-site migration tool and a few hours of downtime.

    When multisite makes financial sense

    Multisite shines when your sites are similar in purpose and traffic profile. If you’re running a portfolio of niche affiliate blogs—say, five sites covering different hobbies, all using the same theme and monetisation stack—multisite cuts hosting costs and eliminates redundant maintenance.

    A single VPS at BigScoots can comfortably handle a multisite network of ten low-to-mid-traffic sites for around $50/month. Running those same sites on individual shared hosting accounts would cost $10–15 each, or $100–150 total. You also skip the pain of logging into ten dashboards to update plugins every week.

    Multisite also works well for franchise models or regional content networks. If you’re publishing city-specific restaurant guides and every site needs the same review template, event calendar, and ad slots, multisite keeps everything in sync without custom deployment scripts.

    When it becomes a liability

    Multisite falls apart when sites diverge. If site A needs WooCommerce, site B runs a membership plugin, and site C is a static brochure, you’re stuck managing plugin compatibility across three different use cases on one shared stack.

    Performance isolation is another problem. Multisite has no built-in resource limits per site. If one site goes viral or gets scraped by a bad bot, it can starve the others of CPU and memory. You’d need server-level controls (like cgroups or container isolation) to prevent one site from taking down the network.

    And if you ever want to sell a site, multisite complicates the deal. Buyers expect a standalone WordPress install they can move to their own hosting. Extracting a single site from a multisite network requires exporting the database tables, remapping file paths, and reconfiguring domain settings—doable, but not trivial.

    One non-obvious tip: subdirectory vs. subdomain structure

    When you create a multisite network, WordPress asks whether new sites should use subdomains (site1.example.com) or subdirectories (example.com/site1). This decision is permanent without a full reinstall.

    Subdirectories are simpler—no DNS changes, no wildcard SSL setup. But they limit you to one root domain. If you want each site to eventually have its own domain, start with subdomains (or use domain mapping from day one). Most managed hosts, including BigScoots, support wildcard SSL out of the box, so subdomain setup is usually friction-free.

    If you’re running a true multi-brand network where each site needs its own identity, map custom domains from the start using the built-in domain mapping feature (or the WordPress MU Domain Mapping plugin on older installs). Don’t rely on subdirectories and assume you’ll migrate later—it’s messier than it sounds.

    The breakpoint

    Multisite makes sense when your sites share DNA: same theme, same plugins, similar traffic, and a long-term plan to keep them together. It saves money and time at scale.

    But if you’re experimenting with different business models, expect uneven growth, or might sell individual properties, the operational flexibility of separate installs is worth the extra cost.

    The worst outcome is committing to multisite for cost savings, then realising two years in that you need to split everything apart. Run the numbers on hosting and maintenance time, and decide which architecture matches where your business is heading—not just where it is today.

    What’s your experience with multisite? Hit reply and let us know whether it simplified your workflow or became a bottleneck. We read every response.

  • The host that fixed our site at 11pm on a Sunday

    The host that fixed our site at 11pm on a Sunday

    TL;DR. BigScoots is a managed-WordPress host with the kind of proactive support most hosts only put in their marketing copy. We use them on every site we run.

    What is BigScoots?

    BigScoots is a US-based managed WordPress and managed VPS host. They’ve been around since 2010 — old enough to know what they’re doing, small enough that the support team actually knows your site by name.

    The pitch is simple: hosting that’s genuinely fast, with a 24/7 team that fixes problems you didn’t even know you had.

    What makes them different from every other “managed WordPress” host?

    Most managed hosts compete on a feature checklist — sites, storage, CDN, staging, backups. BigScoots checks those boxes too, but the real differentiator is proactive support. They watch your site, push performance fixes you didn’t ask for, and respond to problems before you notice them.

    Real things they’ve done for us without being asked:

    • Pushed a server-side caching tweak that took a slow page from 1.6 s to 280 ms.
    • Migrated a site from another host overnight, end-to-end on their side, zero downtime.
    • Fixed a broken plugin update at 11 pm on a Sunday — within 12 minutes of the alert firing.

    Why we recommend it for newsletter operators

    If you’re sending a newsletter from WordPress, every minute the site is down is a minute your subscribers see a broken signup form, a dead referral link, or an empty archive. The cost of bad hosting isn’t the $10 you save — it’s lost trust with the audience you spent years building.

    BigScoots is more expensive than budget hosts. It’s worth it.

    Bottom line

    If you’re new to WordPress and wondering where to host your first newsletter site, BigScoots is the easy answer. If you’re tired of fighting with cheap hosting that breaks every other week, it’s the upgrade. One of those decisions you make once and never have to revisit.

    Heads up — some links in this article are affiliate links. If you sign up through them, we may earn a small commission at no extra cost to you. We only recommend tools we use ourselves.

  • WordPress CDN settings: what actually needs to be cached

    WordPress CDN settings: what actually needs to be cached

    Content delivery networks promise faster page loads and lower server bills. But most WordPress operators flip the switch and trust the defaults—only to find checkout pages breaking, comment forms failing, or member dashboards showing stale data.

    The problem isn’t the CDN. It’s that most presets treat every WordPress site like a static blog. If you run anything interactive—memberships, WooCommerce, course platforms, paywalled content—you need to explicitly tell your CDN what not to cache.

    What should always be cached

    Start with the easy wins. These asset types are static, rarely change, and benefit most from edge caching:

    • Images, CSS, JavaScript — anything in /wp-content/uploads/, /wp-content/themes/, and /wp-content/plugins/ with file extensions like .jpg, .png, .css, .js, .woff2.
    • Publicly visible post and page content — the rendered HTML of non-logged-in pages. Cache for 1–4 hours if you publish frequently, 24 hours if you don’t.
    • RSS and Atom feeds — most readers poll these hourly. Cache for 30–60 minutes.

    Set a Cache-Control: public, max-age=3600 header for these. Most managed WordPress hosts and CDN plugins handle this automatically.

    What should never be cached

    These paths and query strings serve user-specific or time-sensitive data. Caching them breaks functionality or leaks private information:

    • /wp-admin/ and /wp-login.php — the dashboard and login screen. Always bypass.
    • Any URL with a query string containing ?add-to-cart=, ?edd_action=, ?nocache, or session tokens — these trigger actions or personalised views.
    • Checkout, cart, account, and membership pages — if you’re using WooCommerce, Easy Digital Downloads, MemberPress, or similar, create explicit CDN rules to bypass these slugs.
    • Comment forms and AJAX endpoints/wp-comments-post.php and /wp-admin/admin-ajax.php must be dynamic.
    • Any page that reads cookies for logged-in state — if a page checks wordpress_logged_in_* cookies to show different content, don’t cache it.

    Most CDNs let you define cache bypass rules by URL path, query string, or cookie name. Use all three.

    The logged-in user problem

    WordPress sets a wordpress_logged_in_* cookie when someone signs in. If your CDN caches pages that check this cookie, logged-in users see cached, logged-out content—or worse, other users’ dashboards.

    The fix: configure your CDN to bypass cache entirely when any wordpress_logged_in_ cookie is present. Most managed hosts (Kinsta, WP Engine, Flywheel) do this by default. If you’re on a VPS or using Cloudflare, you’ll need to add this rule manually.

    If you run a membership site or paywalled newsletter archive, test this before launch. Log in, visit a member-only page, then open an incognito window and visit the same URL. If you see the same content, your CDN is leaking.

    The one setting that fixes most problems

    Most CDN misconfigurations come down to query strings. By default, many CDNs treat example.com/page and example.com/page?utm_source=twitter as different URLs—and cache both separately.

    This fragments your cache, wastes memory, and reduces hit rates. The fix: strip query strings before caching, unless the query string affects content (like ?p=123 or ?s=search).

    In Cloudflare, this is called “Query String Sort.” In Fastly, it’s “query string handling.” In WP Rocket or W3 Total Cache, it’s “ignore query strings.”

    Whitelist the query strings that do matter—typically p, page_id, s, and preview_id—and strip everything else.

    Testing your config

    After you set cache rules, test three scenarios:

    • Logged-out visitor — Pages should load from cache. Check response headers for X-Cache: HIT or CF-Cache-Status: HIT.
    • Logged-in user — Pages should not cache. Look for X-Cache: BYPASS or CF-Cache-Status: DYNAMIC.
    • Checkout or form submission — These must always be dynamic. If they cache, payments and signups will fail.

    Use your browser’s network inspector or a tool like WebPageTest to inspect headers. If you see HIT on a logged-in page, tighten your cookie rules.

    Most CDN problems aren’t speed problems—they’re config problems. Get these rules right once, and your site will be both faster and more reliable.

    Want more infrastructure deep-dives like this? Subscribe to One Two Three Send and get one operator-focused article every day—no fluff, no filler.

  • WordPress Heartbeat API: what it costs you and how to tame it

    WordPress Heartbeat API: what it costs you and how to tame it

    If you’ve ever watched your WordPress hosting dashboard and wondered why your server CPU spikes every few seconds even when nobody’s actively editing a post, you’re looking at the Heartbeat API in action.

    The Heartbeat API is a core WordPress feature that creates a persistent connection between your browser and the server. It’s what lets you see “User X is currently editing this post” warnings, autosaves your draft every 15 seconds, and keeps your session alive when you leave a tab open for hours.

    It’s useful. It’s also chatty. And for solo operators running lean hosting setups, that chattiness has a real cost.

    What the Heartbeat API actually does

    Every 15 seconds by default, the Heartbeat API sends a request from your browser to your WordPress server. The server responds with any updates: post lock status, comment counts, plugin notifications, whatever’s changed since the last ping.

    That 15-second interval runs constantly while you have the WordPress admin open. If you’re editing a post, it’s checking for conflicts. If you’re on the dashboard, it’s refreshing widget data. If you have three tabs open and forgot about two of them, all three are pinging your server every 15 seconds.

    On a VPS with 2GB of RAM and a handful of plugins, this usually isn’t catastrophic. But it’s not free, either. Each heartbeat request consumes a PHP worker thread. If you’re running a lean hosting setup—shared hosting, a small cloud instance, or a server that’s already near capacity during traffic spikes—those threads add up.

    I’ve seen operators blame their cache plugin or their theme when the real culprit was eight browser tabs hammering the Heartbeat API while they edited a landing page.

    When to throttle it

    You don’t need to kill the Heartbeat API entirely. You just need to decide where the tradeoff between real-time updates and server load makes sense for your workflow.

    Throttle on the front end. The Heartbeat API can run on public-facing pages if a plugin or theme calls it. Most solo operators don’t need this at all. Disable it entirely for logged-out visitors.

    Slow it down in the admin. If you’re not collaborating in real time with another editor, you don’t need 15-second intervals. Stretching it to 60 seconds in the WordPress admin still gives you autosave protection and session continuity without the constant polling.

    Keep it active in the post editor. If you write long-form content or frequently step away mid-draft, autosave is worth the overhead. A 30-second interval here is a reasonable compromise.

    How to control it without a plugin

    The cleanest way to manage Heartbeat is with a small snippet in your theme’s functions.php or a custom plugin. Here’s what I use:

    add_action('init', 'custom_heartbeat_settings');
    function custom_heartbeat_settings() {
      // Disable on front end
      if (!is_admin()) {
        wp_deregister_script('heartbeat');
      }
    }

    add_filter('heartbeat_settings', 'adjust_heartbeat_interval');
    function adjust_heartbeat_interval($settings) {
      // Slow to 60 seconds in admin, 30 in post editor
      $settings['interval'] = is_admin() ? 60 : 30;
      return $settings;
    }

    This disables Heartbeat for all logged-out users, slows the admin dashboard polling to once per minute, and keeps the post editor at 30 seconds. Adjust the numbers based on your workflow.

    If you’d rather use a plugin, Heartbeat Control (free, in the WordPress repo) gives you a settings panel with the same options. It’s lightweight and doesn’t add cruft.

    What you’ll actually notice

    Throttling Heartbeat won’t magically make your site twice as fast. It’s a marginal win, not a transformation. But marginal wins compound, especially on shared hosting or small VPS plans where every bit of overhead matters.

    What you will notice: fewer unexplained PHP worker exhaustion errors during traffic spikes, slightly lower baseline CPU usage, and fewer “server busy” messages when you’re editing posts while a newsletter sends.

    If you’re running WordPress on a tight resource budget—single-core VPS, entry-level managed hosting, or a shared plan you haven’t outgrown yet—Heartbeat throttling is one of the first optimizations worth making. It costs you almost nothing in workflow convenience and buys back real server capacity when you need it.

    Got a hosting or performance question? Reply to this email or share what’s slowing your site down. We’ll cover it in a future issue.