Database Optimization for Bali Business Websites: Why Your Site Slows Down Over Time

database-optimization-for-bali-business-websites

A boutique villa in Canggu asked us to look at their site last year after it started “randomly” timing out during high season. Google PageSpeed showed decent scores. Images were optimized, hosting was solid, caching plugins were active. The culprit turned out to be something invisible in any front-end audit: a wp_posts table carrying 41,000 rows for a site with 180 published pages, and a wp_options table bloated with over 90,000 autoloaded transients that PHP had to pull into memory on every single page load. Nobody had ever looked inside the database in six years of the site being live.

This is the part of website maintenance that almost never gets discussed, because it isn’t visible. You can’t screenshot a bloated database. But for tourism and hospitality sites in Bali — where content gets updated constantly during season changes, where booking plugins write logs by the thousand, and where five years of “quick edits” pile up — the database is very often the real bottleneck, not the images or the hosting plan.

Why a Database Slows Down Even When Everything Else Looks Fine

WordPress stores almost everything in MySQL: every post, every revision of that post, every comment (including spam that never got deleted), every plugin setting, every cached calculation. None of this shows up when you test image compression or check your hosting’s CPU usage. But every single page load on a WordPress site triggers dozens, sometimes hundreds, of database queries — to fetch the post, its metadata, its taxonomy terms, widget data, menu items, and whatever a plugin decided it needed to check.

If those tables are lean, each query is fast. If a table has grown to hundreds of thousands of unnecessary rows, MySQL has to scan through more data to find what it needs, even with indexes in place. The effect is gradual — a query that took 5 milliseconds when the site launched can take 150 milliseconds three years later, and nobody notices because it happens one week at a time. It only becomes obvious when the whole site feels sluggish, admin dashboard included, and a speed audit focused on the front end comes back clean.

This is exactly why a site can pass every image and caching check and still feel slow to load, slow to save a post in wp-admin, or prone to timing out under traffic spikes — because the bottleneck sits below the layer those checks look at.

The Four Culprits That Quietly Fill Up a WordPress Database

In the maintenance audits we run for client sites — restaurants, villas, tour operators, dive shops — four types of accumulated data show up again and again as the main source of bloat:

  • Post revisions. By default WordPress saves a new revision every time a page or post is saved, with no limit. A homepage or price list that’s been edited weekly for four years can carry 200+ revisions of itself, each one a full duplicate row in wp_posts.
  • Spam and unapproved comments. Even with Akismet active, spam comments are usually marked, not deleted. We’ve seen hospitality sites with 15,000+ spam comments sitting in wp_comments, each with associated meta rows, never cleared out.
  • Expired transients. Transients are meant to be temporary cached values (exchange rates, API responses, booking availability) stored with an expiration time. When a plugin is coded carelessly, or a cron job that clears them stops running, thousands of expired transients sit permanently in wp_options and get auto-loaded into memory on every page request.
  • Orphaned data from removed plugins. Every booking plugin, page builder, or SEO tool a site has tried and later removed usually leaves its custom tables, postmeta entries, and options behind. We regularly find tables from plugins that were deactivated three redesigns ago, still being created, still holding data, still occasionally still being queried by leftover code.

None of these cause a dramatic failure. They cause a slow, compounding drag — which is why they’re so often missed until someone actually opens phpMyAdmin and looks at row counts.

A Real Example: What We Found on One Bali Hospitality Site

To make this concrete: on the villa site mentioned earlier, here’s what a database audit turned up after six years without a single cleanup:

  • 38,000 post revisions attached to fewer than 200 actual pages and posts
  • 12,400 spam comments, none ever purged, each with 3-4 associated meta rows
  • 91,000 rows in wp_options, of which roughly 60,000 were expired transients from a discontinued availability-calendar plugin
  • Three orphaned tables from a page builder that had been replaced two redesigns prior
  • A wp_postmeta table over 3x larger than it needed to be, largely from a form plugin that logged every submission attempt as post meta instead of using its own table

Total database size before cleanup: 1.9 GB. After cleanup: 240 MB. Admin dashboard load time dropped from around 4.5 seconds to under 1 second, and the front-end database query time — measured with Query Monitor — dropped by roughly 70%. No hosting change, no plugin swap, no new caching layer. Just removing data that shouldn’t have still been there.

How to Clean a Database Without Breaking Anything

The single biggest risk in database cleanup isn’t that it’s technically hard — it’s that people do it without a safety net and delete something a plugin still depends on. A safe process looks like this:

  • Take a full database backup first, and verify it restores. Not just “the backup ran” — actually confirm the file is complete and importable. This is the one step that’s non-negotiable.
  • Audit before deleting. Look at table sizes (phpMyAdmin’s database overview, or a query against information_schema.TABLES) to see which tables are disproportionately large relative to the site’s actual content volume.
  • Limit post revisions going forward, then clean the old ones. Set a revision cap (commonly 3-5 per post) in wp-config.php, then remove the excess historical revisions via a reputable cleanup plugin or a direct, carefully scoped SQL query.
  • Purge spam and trashed comments that are older than a reasonable window (30-90 days), not everything indiscriminately — some “spam” flags are false positives worth a quick glance first.
  • Delete only genuinely expired transients, using a tool that checks the expiration timestamp rather than wiping every transient blindly, since some are actively in use.
  • Identify and remove orphaned tables from long-uninstalled plugins — but confirm the plugin is truly gone and not just deactivated for a season, which is common with tourism sites that turn certain booking features on and off between high and low season.
  • Run OPTIMIZE TABLE on the affected tables afterward. Deleting rows doesn’t reclaim disk space or defragment the table on its own in most MySQL configurations — the optimize step is what actually shrinks the table and rebuilds its indexes efficiently.

Each of these steps is reversible up to the point of deletion, which is exactly why the backup step comes first and gets verified, not assumed.

How Often a Busy Tourism Site Actually Needs This

The honest answer depends on how active the site is, not on a fixed calendar date. A few practical benchmarks we use:

  • High-traffic booking or tour sites with daily content or price updates: a light database check every 1-2 months, full cleanup and optimization every 6 months.
  • Restaurant, villa, or spa sites updated weekly (menus, offers, gallery): full cleanup every 6-9 months is usually sufficient.
  • Brochure-style business sites updated a few times a year: once a year is generally enough, though it’s worth checking after any major plugin change or redesign, since those are exactly the events that leave orphaned tables behind.

A useful trigger that applies regardless of schedule: any time a plugin is uninstalled, any time a page builder or booking system is switched out, or any time the admin dashboard starts feeling noticeably slower than it used to — that’s worth a database check regardless of when the last one happened, because that’s precisely when orphaned data gets created.

Why This Gets Missed So Often

Most website maintenance conversations understandably focus on what’s visible and urgent: is the site online, is it secure, is it backed up, does it load reasonably fast on mobile. Database health doesn’t announce itself with an error message or a security warning. It just makes everything marginally slower, year after year, until a business owner assumes their site has simply “gotten old” and needs a full rebuild — when in many cases a rebuild wasn’t needed at all, just a few hours of cleanup on the layer nobody had been looking at.

It’s also a task that genuinely requires care: knowing which tables are safe to touch, which plugins store data in nonstandard ways, and how to verify a backup before running anything destructive isn’t something most business owners want to gamble on with a one-click plugin and no rollback plan.

If your site has been running for a few years without anyone ever opening the database itself, it’s worth having someone check — not because something is necessarily broken, but because this is exactly the kind of slow accumulation that’s easy to fix once you know it’s there and easy to ignore forever if you don’t. It’s part of the ongoing maintenance work our team at Bali Web Design does for hospitality and tourism clients across Bali, alongside the backups, updates, and monitoring that keep a site healthy well past its launch year.