Every owner eventually asks the same question about a platform: if something goes wrong, can we get back? On a mature WordPress host the answer is usually a nightly backup and a restore button. On emDash, the honest answer is "yes, if you prepare for it" — and preparing for it is cheaper and quicker than most teams expect.

This piece sets out how we made emdashnow.com recoverable before launch: how database changes reach production without surprises, what a real backup of an emDash site contains, and how the key that protects stored credentials can be changed without breaking anything. Each procedure was rehearsed before it was needed. The detail is here for the people who will run a site; the decisions are here for the people who pay for one.

What "recoverable" means on emDash

A WordPress backup plugin usually bundles the database and the uploads into one file. emDash separates the pieces, and each needs its own plan. If one is missing, a restore is incomplete.

PieceWhat it holdsHow we protect it
The databaseContent, users, settings, plugin data and subscriber recordsPoint-in-time recovery, plus a weekly encrypted copy stored outside Cloudflare
The mediaImages and files, stored separately from the databaseA copy of the storage bucket, restored only into an empty bucket
The encryption keyUnlocks credentials that plugins store, such as email and anti-spam keysHeld offline in two places; never inside any backup
The site's codeThe exact version that matches the databaseVersion control, with every production deploy tagged to its commit

Database changes without surprises

emDash upgrades its own database tables from time to time, through what it calls core migrations. By default, a newly deployed site applies any pending migration on the first request it receives. That is convenient, and it means the first visitor after an upgrade triggers a change to the live database, with no recovery point recorded beforehand.

emDash supports a more careful arrangement, and we adopted it in stages. Each deployment now runs a fixed sequence, and any failure stops it.

01Record a recovery point

The database's current point-in-time bookmark is written to the deployment record before anything changes.

02Inspect the target

The deployment confirms it is pointed at the production database, and lists pending and unexpected migrations. Anything unexpected stops it.

03Apply, only if needed

Pending migrations run as a deployment step, only when the recovery point exists and the database matches the one reviewed in advance.

04Deploy the new code

The new version of the site goes live only after its database is ready.

05Check the result

A request to the live site and a migration check confirm that nothing is pending. A failure here is reported at once.

The live site is set to check rather than apply: if a migration is somehow missing, it refuses to serve with a clear error instead of changing its database mid-request. We moved to that setting after five clean deployments with the new steps, which is the gradual path emDash's own documentation recommends.

The final check earns its place. On one deployment, a code change that expected a new content field reached production before the field itself had been added. The home page, which reads it, stopped loading. The post-deployment check flagged the failure immediately, the field was added, and a small fix made the code tolerate the gap in future. Without the check, the first report would have come from a reader.

Two related points matter for planning. Rolling back the site's code does not roll back its database, so a rollback after a migration means restoring both together. And changes to your own content model — new fields and collections — are separate from emDash's core migrations and need their own step in the deployment.

Backups that actually restore

On Cloudflare, emDash stores its database in D1, which keeps a rolling history called Time Travel. Any moment in the retention window can be restored: 30 days on the Workers Paid plan, 7 days on the free plan. It restores content, users, settings, plugin data and the migration records in one action, and it is the first thing to reach for.

Thirty days is not always enough, and a backup held by the same provider as the site does not protect against losing access to that provider. So we added a second layer: a weekly copy of the whole database, encrypted before it leaves the build server and stored with a separate provider, in a bucket that the backup job can write to but not read, list or delete. Old copies are kept for about twelve weeks.

LayerCoversRetentionRestores
Time TravelMistakes, failed migrations, accidental deletions30 days (Workers Paid)The database in place, in about 20 seconds in our rehearsal
Weekly encrypted dumpLonger look-back, and loss of the Cloudflare accountAbout 12 weeksInto a new, empty database, verified before switching
Media bucket copyLost or overwritten images and filesAs long as the copy is keptInto a new, empty bucket

Building the second layer surfaced a trap worth knowing. Cloudflare's standard database export refuses to run on an emDash site that uses search, because emDash keeps its search index in a kind of table the export cannot handle. The fix, which emDash's documentation now describes, is to export every other table and let the site rebuild its search index on the first search after a restore. A second trap: very long entries can produce single statements larger than D1 will accept on import, so each dump is checked for them when it is made.

Restores follow one rule without exception: never restore over the live database. A copy is restored into a new, empty database, checked, and only then connected to the site.

Changing the key that protects stored credentials

Plugins store credentials — the email provider's key, the anti-spam secret — encrypted in the database. The key that encrypts them lives outside the database, as a platform secret. That separation is good security, and it has two consequences an owner should understand. A database backup without the matching key cannot unlock those credentials. And changing the key, which good practice calls for periodically or after a suspected exposure, must be done in an order that never leaves a credential unreadable.

emDash makes this possible by accepting a list of keys. New values are encrypted with the first key in the list; older values are read with whichever key wrote them.

01Add the new key in front

The site now writes with the new key and can still read everything written with the old one.

02Re-save every stored credential

Each one is re-encrypted with the new key. emDash does not yet report which values still use an old key, so keep a list and work through it.

03Verify, then remove the old key

Run the site with the new key alone, check every integration that uses a stored credential, and only then retire the old key.

We rehearsed the full sequence on a preview deployment. Every stored credential moved to the new key, sign-ups and form protection kept working at each stage, and the procedure for production is written down step by step.

The rehearsals

21 sto restore the preview database from a point-in-time bookmark, with every table matching the baseline
23 sto restore a full dump into a new, empty database, with row counts and encrypted settings identical
3stored credentials moved to a new encryption key, with sign-ups working throughout

The rehearsals ran on the preview database, never on production. The numbers are small because the site is young; what matters is that each procedure was proven end to end, and that the written instructions are the ones that worked.

Make an emDash site recoverable0/7 done

The recommendation from user persona point of view

  • Running a WordPress site that works. Recovery is not a reason to stay, or to go. emDash's tools are sound, but they are not one button. Before any move, ask who will own the four pieces above and when they last tested a restore.
  • Commissioning a new site. Make recoverability a launch requirement: a recorded recovery point before each deployment, an off-platform copy, the key stored separately, and a rehearsal you can see. It adds a few days to a build and removes a category of risk.
  • Running an agency. A rehearsed recovery plan is a deliverable clients rarely ask for and always value after an incident. Package it as part of every launch, alongside the wider emDash security checklist. The rest of the build is described in what we learned running emDash in production.