Backups, migration and recovery: a backup you have not restored is a rumor.

Five things to protect, four recovery paths, and a timed drill using this site's data. See what came back, what was measured, and what still needs an application-level test.

A backup you have not restored is a rumor Two shelves. The upper shelf holds the four live stores of a WordPress site - git, database, media bucket and config - as small isometric objects. A fainter dashed ghost shelf below holds their restored twins directly underneath, joined by dotted drop lines. A stopwatch labelled RESTORE DRILL stands beside the lower shelf, with labels for an observed code fetch, an eight-minute database clone, a 6.6-second media sequence and untested configuration under the four twins, and a green check by the restored database. An amber backup.zip sits struck through inside the live database's footprint. RESTORE DRILL boot fetch 8 min 6.6 s not tested GIT DATABASE MEDIA CONFIG backup.zip
Database and media recovery were timed. Code fetch was observed during boot; configuration recovery remains untested here.

Five stores to protect. Caches to rebuild.

A WordPress site is five stores and a pile of caches. A backup is a copy of the five. A restore drill is proof that each copy comes back. Here is the inventory for the site you are reading, with what has been proven and what has not.

StoreWhat it holdsHow it is protectedHow it comes back
Codeobserved at bootCore, theme, plugins, mu-plugins, layout manifests, infrastructure YAML. 20,077 filesA git repository with a protected production branchEvery pod boot fetches the branch. A rollback is a revert and a push
Database✓ component testedPosts, options, users, the page layouts. 456 MB, 49 tablesNightly Cloud SQL backup, seven retained, seven days of transaction logs, and a regional standbyA point-in-time clone within the available recovery window, or a backup restore
Media✓ component tested863 items, 1.4 GB with every generated sizeObject versioning plus a seven-day soft delete on the bucketCopy the previous generation back over the object
Configuration○ not drilled hereThe deployment, autoscaler, CDN distribution and database instance as YAMLChecked into the repository, applied by a workflow on pushRe-apply from the repository. 22 distributions were once rebuilt this way on client sites
Secrets○ not drilled hereDatabase credentials, deploy keys, API tokensVersioned secrets in Secret Manager, with access managed separatelyResolve available versions at boot. Rebuilding after loss of the secret store or its access policy needs a separate recovery plan
Rebuildable state– by designObject and page caches, plus disposable container filesExcluded only when they contain no unique dataWarm caches through traffic. Inventory sessions, queues and plugin files first; anything irreplaceable needs protection

Status distinguishes component tests from observations during normal operation. Neither proves a complete site recovery. The drill ran on October 12, 2026 (UTC).

Seventeen minutes, timed, on this site.

Run on October 12, 2026, 01:26 to 01:44 UTC (October 11 evening in New York). A separate database clone and a scratch media object kept the live application untouched. This is a component recovery drill, not a measured site recovery time.

On-demand backup of the production instance requested

Completed 01:28:24. The nightly backup is automatic; this one was taken before a content change, the way every layout write on this site is preceded by one.

91 smeasured
Point-in-time clone to 01:10:47, twenty minutes earlier

The clone reached RUNNABLE at 01:38:50 and its databases were listed. That establishes provisioning and recovery to one selected point, not application correctness or every point in the retention window.

8 min 3 smeasured
Scratch media object: delete, list versions, copy the saved generation back

The 6.6 seconds include deletion, version listing and copying back a 56.1 KB test object. This used Object Versioning, not soft-delete recovery; restoring the full media library was not timed.

6.6 smeasured
Logical export of the cloned production database to a bucket

47.9 MB compressed from 456 MB on disk. A portable copy you can load anywhere, including a laptop.

34 smeasured
Deletion protection removed from the clone

The clone inherited the production instance's deletion protection. A drill that cannot clean up after itself is a drill nobody repeats.

6 smeasured
Clone deleted

Gone at 01:43:58. Total wall time for the drill, from first backup to last cleanup: 17 minutes.

77 smeasured

What the drill proved

  • A clone restored to one selected point twenty minutes earlier reached RUNNABLE in 8 min 3 s, and its databases could be listed.
  • A scratch media object was deleted and copied back from its saved generation in a 6.6-second sequence.
  • A logical export of the cloned production database completed in 34 seconds and produced a 47.9 MB compressed file. Importing that export was not tested.

What it did not prove

  • That WordPress works against the restored database. No application was connected to the clone and no regression suite ran against it.
  • That configuration and secrets can be rebuilt from scratch into an empty project. The evidence for that lives in the client record, not in this drill.
  • That anyone on the team can do it from the runbook alone, without the person who wrote it.
  • A full media restore, recovery from soft deletion, or the total time and data loss involved in returning the site to service.

Four failures, four clocks.

Recovery is not one procedure. It is four, and they have very different clocks. Match the failure to the store before anyone touches a backup.

CodeA bad deploy

Revert the incompatible code and roll out the replacement. Check database compatibility first. Deployment rollout settings and readiness govern traffic; a disruption budget does not control a rolling update.

62 to 74 secondsobserved per-pod readiness, not total rollback time
DatabaseA bad content change

Restore a separate clone, compare the affected data and choose a repair or a controlled cutover. Reconcile valid writes made after the recovery point before replacing live data.

8 minutes to the clonemeasured, plus the switch
MediaA deleted or overwritten file

Copy the saved object generation to a live path, verify it, then purge affected CDN variants. The drill covered one scratch object.

6.6 secondsdelete, list and copy-back sequence, CDN purge not timed
EverythingA lost instance or cluster

Rebuild infrastructure and access, restore the data and media, deploy code, then verify application behavior and traffic routing.

Hours, not minutesestimated, not drilled here, the gap this chapter exists to close

Reference: Cloud SQL point-in-time recovery and Kubernetes disruption and rollout behavior. Check the available recovery window before choosing a timestamp.

Six steps, with writes accounted for.

A migration is a restore plus a cutover plan. The source and destination diverge as soon as new writes arrive. The plan must account for that gap before anyone changes a connection string.

Build an isolated destination

Create the target database and storage, restore a recent copy, and connect an isolated test environment. Block outbound email, payments and scheduled jobs that could affect real users.

Test the restored application

Run the regression suite and editorial checks. Verify uploads, logins, scheduled jobs and critical transactions. Confirm engine, plugin and schema compatibility.

Choose how writes cross the gap

Use supported replication or change capture to catch up, or schedule a write freeze and take a final consistent export and media sync. A quiet hour is not a synchronization strategy.

Cut over one source of truth

Pause writers for the final handoff, verify replication lag or the final import, then switch the application. Clear environment caches and affected CDN paths. Verify critical reads and writes before reopening traffic.

Define rollback before reopening writes

Keep the old source protected and read-only for the agreed retention period. Once the destination accepts writes, switching back requires reconciliation; the old copy is no longer a lossless undo button.

Verify, observe, then retire

Check record counts, media access, errors and real application flows. Remove old credentials and infrastructure only after acceptance and the rollback window. Record the actual disruption and data-loss window.

Two incidents from the operating record.

01

Moving a media bucket

A bucket move left old absolute URLs in thousands of posts.

The correctionRewrite the URLs at render time, then purge the CDN. This incident was resolved without a database search-and-replace.

02

Sharing a database across environments

A development environment connected to the live database wrote its own hostname into 57 rows.

The correctionRestore the affected data from a backup. Content environments may share a database; anything that runs migrations gets a clone first.

You are reading the example.

This handbook is served by the system it describes, so the drill above is also a review of our own setup.

01 / Database

Nightly, plus seven days of log.

Automated backups at 06:00 UTC with seven retained, binary logging on, seven days of transaction log, a regional standby. A clone to one chosen point in the available window took eight minutes. A regional standby addresses availability; it does not undo an accidental data change.

02 / Media

Versioned and soft-deleted.

Object versioning has been on since the bucket was created in 2019; the seven-day soft delete arrived with the platform default in 2024. The delete, version-list and copy-back sequence for one scratch object took 6.6 seconds. Soft-delete restoration was not tested.

03 / Code and configuration

Git, applied by a workflow.

Every pod fetches the production branch at boot. The deployment, autoscaler, CDN distribution and database instance are YAML in the same repository. Page layouts are kept as manifests next to them.

04 / What is missing

A drill that includes the application.

No environment was pointed at the clone. The regression suite was not run against restored data. Configuration and secrets were not rebuilt into an empty project.

Asked after the first scare.

How often should a WordPress database be backed up?

Set the schedule from your recovery point objective: how much valid data you can afford to lose. Daily backups may suit a low-change publication, but orders or frequent edits need a smaller window. Point-in-time recovery can bridge backups while logs remain available. Verify the actual recoverable window and test the restore.

Is a backup plugin enough?

A well-configured plugin can make useful off-site backups. It still needs independent recovery instructions and access if WordPress will not start. This site protects the database and media at their storage layers, keeps code in git, and treats configuration and secrets as separate recovery dependencies.

What should a WordPress backup include besides the database?

Protect media, versioned code, infrastructure definitions, DNS and the secrets needed to reconnect the application. Keep recovery access separate from the failed environment. Exclude caches only after confirming that sessions, queues and plugin files contain no unique state.

How do I test a restore without touching production?

Restore to a new instance or scratch storage, then connect an isolated non-production application. Disable outbound email, payments and jobs, run checks, and record elapsed time and data loss. This drill timed a database clone and one object recovery; the application verification step is still outstanding.

How do I migrate a WordPress site without downtime?

Use a tested destination and a defined write-transfer method. Supported replication can minimize the handoff; otherwise a write freeze and final consistent export create a deliberate interruption. Verify the destination before reopening writes. Keeping the old source helps rollback only if you also plan how to reconcile writes accepted after cutover.

Never timed a restore on your own site?

Tell us where the database, media and code live and how much disruption the business can tolerate. We can scope a recovery exercise, test the application against restored data and document a runbook your team can use.