Most people who search for a WordPress database backup already assume the database is the site. It isn't. Rebuild a site from a database-only export as a deliberate test rather than waiting for a real emergency to find out, and the restored site comes back broken in a way the owner didn't expect — reliably.
The database holds your
posts, pages, comments, and settings. But your uploaded images, your active theme's code,
your custom plugins, your .htaccess rewrite rules, and the secret keys in
wp-config.php all live outside it, on disk. Grab only the database, and
you're backing up roughly half the website.
This guide walks through what the database does and doesn't hold. It covers what breaks when you restore from a database-only dump. It shows how to take a dump that won't quietly truncate itself mid-export. And it covers when a database-only backup is genuinely the right tool for the job, rather than a trap.
What Actually Lives in the Database — and What Doesn't
A WordPress database (almost always MySQL or MariaDB) stores roughly a dozen core
tables: wp_posts, wp_postmeta, wp_options,
wp_users, wp_usermeta, wp_terms, and a handful more
depending on which plugins add their own tables. That's where your post content, page
content, comments, menu structure, widget settings, and most plugin configuration live.
It is, genuinely, the most frequently changing part of a WordPress site — which is exactly
why so many people reach for a database backup first.
That table also holds something that isn't really "content" at all: every saved revision of every post and page, stacking up indefinitely unless a limit is set. See why WordPress revisions are not a backup for how that bloat affects the size of the dump you're about to take, and why trimming it is good database hygiene but still no substitute for the backup itself.
Here's what the database does not contain, according to the
WordPress.org database backup documentation:
the wp-content/uploads/ directory (every image, PDF, and video you've ever
uploaded), the active theme's PHP and CSS files in wp-content/themes/, every
installed plugin's code in wp-content/plugins/, any mu-plugins/
you or a host added, the site's .htaccess file (or nginx config) that controls
permalinks and redirects, and wp-config.php itself. That last file holds your
database credentials and your unique authentication salts.
We built a quick reference table from the WordPress.org Codex file-structure guide so you can check your own backup set against it in under a minute:
| Lives in the database | Lives on disk (files) |
|---|---|
| Posts, pages, comments | Uploaded media (wp-content/uploads/) |
Site settings (wp_options) | Theme code (wp-content/themes/) |
| User accounts and roles | Plugin code (wp-content/plugins/) |
| Menu structure, widgets | Site-level mu-plugins |
| Most plugin configuration | .htaccess / server rewrite rules |
| Comment metadata, taxonomies | wp-config.php (credentials + salts) |
The Symptom → Missing Artifact Table
This is the section most "how to back up WordPress database" guides skip, and it's the part that actually explains what you're looking at when a database-only restore goes wrong. These symptoms trace back to the same handful of missing files every time.
| Symptom after restore | What's actually missing |
|---|---|
| Every image on the site shows a broken-image icon | wp-content/uploads/ — the database only stored the URL path to each file, not the file itself |
| White screen or 500 error right after activation | The active theme or a plugin's PHP files — the database has a row saying "Twenty Twenty-Four is active," but not the theme's code |
| All your custom permalinks 404, pretty URLs stop working | .htaccess — WordPress can regenerate it from Settings > Permalinks, but only after you resave it manually |
| A plugin's custom fields or settings panel comes back empty | Any plugin table it created itself plus its uploaded assets — if the plugin's code wasn't reinstalled first, its database rows have nothing to attach to |
| Login works but every session gets logged out instantly | Fresh authentication salts in a new wp-config.php invalidate old session cookies — expected, but confusing if you weren't told |
| Site loads but every link points to the old domain | wp_options rows (siteurl, home) weren't updated for the new host — a database-only migration problem, not a missing-file one |
Notice that the last two rows are database problems, not file problems — which is the other side of this coin. A database-only backup restored onto the same server, same domain, same file structure, can genuinely work. The moment any of those three things change, you need the files too.
mysqldump vs. phpMyAdmin Export: Size Limits, Timeouts, and the Truncated.sql Nobody Notices
If you're exporting manually rather than through a backup plugin, you have two realistic options, and they fail differently.
phpMyAdmin's export tab is the most common path because every shared
host exposes it. The problem: it runs inside PHP's own request lifecycle. That means it's
bound by max_execution_time and upload_max_filesize. On a typical
shared host those caps sit around 30 to 60 seconds and 2–8 MB respectively. According to
the database backup guidance above, a database over roughly 50 MB routinely times out or
produces a truncated file. That size is not unusual once you've got a few years of
comments and revisions. The export file looks fine in a file browser. It opens fine in a
text editor. It only fails when you try to restore it, and MySQL throws a syntax error on
the truncated last line. Some site owners install a dedicated export plugin instead — the
WP Database Backup plugin on WordPress.org
is one example — specifically to sidestep this PHP timeout problem.
mysqldump, run from the command line or SSH, isn't bound by PHP's limits at all. It's a native MySQL client talking directly to the server process. A 2 GB database dumps the same way a 20 MB one does — it just takes longer. The command most guides give you is incomplete, though:
mysqldump -u username -p database_name > backup.sql
That works for a quiet site. For anything receiving live traffic — checkout flows, comment submissions, logged-in editors — you want one more flag.
Consistency: --single-transaction on InnoDB, and Why a Dump Taken Mid-Checkout Can Tear
Most WordPress tables run on the InnoDB storage engine, which supports transactions.
Without --single-transaction, mysqldump reads your tables one at a time, in
sequence, while the site keeps writing to all of them. Say an order comes in halfway
through the dump. wp_posts has already been read, but the related
wp_postmeta row for that order hasn't landed yet. Your backup now captures a
database that never actually existed — half of a transaction, with the other half missing.
This isn't a rare edge case on a store that takes orders continuously — without the flag,
dumps taken during active writes can regularly produce an orphaned postmeta row. With it,
the dump is a consistent snapshot and the problem goes away.
mysqldump -u username -p --single-transaction --quick database_name > backup.sql
--single-transaction takes a consistent snapshot at the instant the dump
starts — every table reads as it looked at that exact moment, not as it evolves during the
(potentially multi-minute) export. --quick streams rows instead of buffering
the whole result set in memory first, which matters once a table passes a few hundred
thousand rows.
Restoring a.sql File: DROP vs. Merge, Collation Match, and the wp_options Gotcha
Restoring is where most of the remaining failures happen, and they're almost always one of three things.
DROP vs. merge. A straight mysql -u user -p database_name <
backup.sql assumes the target database is either empty or you want the dump's
tables to fully overwrite anything with the same name — it does not merge rows. If you're
restoring onto a database that already has content you want to keep, you'll end up with
duplicate or conflicting primary keys unless you first drop the existing tables or restore
into a clean schema.
Collation match. Say the source site was created years ago under
utf8_general_ci. Now you're restoring into a fresher MySQL instance that
defaults to utf8mb4_unicode_520_ci. Certain joins and comparisons can silently
behave differently. The most visible sign is mangled emoji or multi-byte characters in
older posts. Match the collation on the target database to what the dump file specifies,
before importing.
The wp_options gotcha. Two rows in wp_options —
siteurl and home — hard-code the domain the backup was taken
from. Restore that dump onto a staging subdomain or a new production domain without
updating those two rows, and every internal link, every image src, and the admin login
redirect will all point back at the original domain. The same applies to serialized data
inside wp_posts and wp_postmeta, which needs its own
search-and-replace pass.
wp-config.php and Salts: What You Must Keep, What You Must Never Publish
The wp-config.php file is not stored in the database, and it's not
optional. It holds your database name, username, password, and host — the credentials the
site uses to even reach the database you just backed up. It also holds eight unique
authentication salts (AUTH_KEY, SECURE_AUTH_KEY,
LOGGED_IN_KEY, NONCE_KEY, and their _SALT pairs)
that encrypt session cookies. Lose this file with no copy anywhere, and a database-only
backup is nearly useless on its own. You'd be rebuilding the connection details from
scratch. Every logged-in session invalidates the moment the salts change.
Keep a secured copy of wp-config.php alongside your database dumps, in the
same backup set. Never store it in a public repository or an unprotected cloud folder —
the credentials and salts inside it are exactly what an attacker would want. If you
regenerate salts for a fresh install, expect every currently logged-in user, including
you, to be signed out immediately. That's expected behavior, not a bug.
When a Database-Only Backup Genuinely Is Enough
None of this means you should abandon database exports. They're fast, they're small, and for one specific job they're exactly the right tool: refreshing a staging copy of a site you already have the files for. Say your staging environment already has the current theme and plugin code installed, and you just want it to reflect this morning's content changes. A database-only sync is the quickest way to get there, since the files already match and there's nothing on disk to touch. That's the workflow our guide on backing up WordPress without plugins over SSH covers for the no-plugin case specifically.
The rule of thumb: if the destination's files already match the source, a database-only backup is sufficient. If they don't — a new server, a new host, a disaster recovery scenario, or you genuinely don't know — you need the files too, every time.
What a Complete Backup Actually Covers
A full WordPress backup, as opposed to a database-only one, needs to capture four things
together, kept as one recoverable set: the database, the wp-content/uploads/
directory, the active theme and all installed plugins, and a secured copy of
wp-config.php plus any server-level redirect rules. BackupYourSite's own
automated backups package all four into a single scheduled job, including on hosts like WP Engine where the SSH Gateway handles direct access. Handling any one of those four pieces separately, on its own schedule, is exactly how a restore ends up with one of the missing-artifact symptoms in the table earlier in this piece.
Our full feature set page walks through the scheduling, storage, and one-click restore pieces if you want to see how that's structured end to end, rather than piecing it together by hand. Our how it works page covers the mechanics in more depth. And if "what even counts as a backup" is still the open question, start with what is a WordPress backup, exactly.
How Often Should the Database Actually Be Dumped?
This depends entirely on how fast your content changes, not on a fixed industry number. A static brochure site with five pages and no comments can run weekly and lose nothing meaningful between dumps. A WooCommerce store processing orders every few minutes cannot. A reasonable baseline for an active store is every six hours, tightened to hourly during sale periods when order volume spikes. A blog with daily posts and an active comment section sits comfortably on a once-a-day schedule.
The deeper question isn't "how often" — it's "how much am I willing to lose." Six hours between dumps means a worst-case loss window of six hours of orders, comments, and edits. Map that window against what a lost morning of sales actually costs your business, in rupees or dollars. The right frequency becomes obvious fairly quickly once you do that math. Automated scheduling removes the risk of simply forgetting — in practice, forgetting is the single most common cause of an unusable backup set. Not corruption, not a bad dump, just nobody having run one in the weeks before the site broke.
Retention matters as much as frequency. Keeping only the most recent dump means a corrupted or malicious change made two days ago gets faithfully "backed up" right over the good copy. A rolling window of at least 7 to 14 days gives you somewhere to go back to before the bad change, not just before the crash.
Frequently Asked Questions
Is a WordPress database backup enough on its own?
Only if you're restoring onto the exact same files — same theme, same plugins, same
server config — and just need the content to come back. For a new host, a new domain, or
disaster recovery, you also need wp-content/uploads/, your theme and plugin
code, and wp-config.php.
How do I back up my WordPress database without a plugin?
Run mysqldump over SSH with the --single-transaction and
--quick flags, which keeps the export consistent even while the site is
actively being written to. See our no-plugin backup guide
for the full SSH walkthrough.
Why does my site show broken images after a database restore?
Because the database only ever stored the path to each uploaded file, never the
file's binary data. The actual image files live in wp-content/uploads/ on
disk, and a database-only restore doesn't touch that directory at all.
Can I export a WordPress database using phpMyAdmin instead of the command line?
Yes, for small sites. But phpMyAdmin runs inside PHP's own execution limits, so
databases above roughly 50 MB routinely hit a timeout or file-size cap and produce a
truncated .sql file that looks complete but fails on restore.
What is --single-transaction in mysqldump and do I need it?
It takes a consistent snapshot of InnoDB tables at the instant the dump starts, instead of reading tables one by one while the live site keeps writing to them. You need it on any site that gets traffic or logged-in activity during the backup window — without it, a dump taken during active writes can come out torn, with some tables reflecting a later moment than others.
Why do all my links point to the old domain after I restore my database?
The siteurl and home rows in wp_options hard-code
the domain the backup was taken from, and serialized URLs are also embedded throughout
wp_posts and wp_postmeta. Moving to a new domain or host needs a
search-and-replace pass across the database, not just a straight restore.
Do I need to back up wp-config.php separately from the database?
Yes. It's a file on disk, not a database table, and it holds your database connection details plus the authentication salts WordPress uses to validate login sessions. Keep it in the same secured backup set as your database dump — never in a public location.
When is a database-only backup actually fine to rely on?
When you're refreshing a staging environment that already has the current theme and plugin files installed, and you only need this morning's content changes carried over. The destination's files already match the source, so there's nothing else to restore.