Tools

Backups for a Static Site: What You Actually Need to Save

A static site has an attractive property: the output is generated. Delete every file on the CDN and a build recreates them. That makes people conclude backups are unnecessary, and the conclusion is half right in a way that hides exactly the things that are not recoverable.

The question to ask is not “can I rebuild the site?” It is “what would I need in order to rebuild it, and where does each of those things live?”

The four things, and where they live

AssetWhere it livesRebuildable from source?
Source and contentYour Git repository— that is the source
DNS zoneThe DNS provider’s dashboardNo
Platform config (headers, redirects, env vars)Some in the repo, some in a dashboardPartly
API tokens and secretsWherever you stored themNo
Build outputThe CDNYes, trivially

Read the middle three rows. Everything that is not in your repository is a single point of failure with no source of truth, and those are the components that actually need a backup.

The DNS zone, which is the most commonly missed

A DNS zone is configuration that exists in exactly one place. If the account is lost, or the provider has an incident that loses data, or you are locked out, there is no git clone that gets you back.

The good news is that exporting is a documented, first-class feature on at least one major provider: the dashboard’s import and export section produces a BIND-format zone file, and the same operation is available via API.

Two things make this worth doing rather than intending to do:

The format is an RFC standard. BIND zone files are defined in RFC 1035, which means an export is portable — you can hand it to another provider, read it yourself, and check it into version control as plain text.

The export preserves platform-specific settings. For a proxied record, the export includes provider-specific tags that record the proxy state and any flattened CNAME behaviour. So the export is not just the records; it is the records plus the intent.

Documented limitations to know before you rely on it: the zone-file import path has a size limit, the API has a low rate limit on import operations, and while $ORIGIN, $TTL and $GENERATE directives are supported, $INCLUDE is not. If your zone uses include directives, an export-and-reimport round trip will not be clean.

A zone file in your Git repository is one of the highest-value backups you can make, and it takes five minutes. Do it once, then again after any significant DNS change.

Platform configuration is split in two

The interesting property of a static site’s platform config is that it is half declarative and half not.

In the repository: _headers and _redirects files, the build command, and anything else committed to source. These are versioned, diffable, and restored by checking out the repository.

In the dashboard: environment variables, secrets, domain associations, build settings, and the project’s existence itself. None of these are in Git, and none are visible in a diff.

So the practical measure is a plain text inventory, held in the repository or a password manager, listing every environment variable name and every domain associated with the project — names, not values. Values go in a password manager.

The reason to record names is that an inventory without them is how you discover, six months into a migration, that a preview environment was reading a variable you had forgotten existed.

Secrets, and the one-way door

Here is a documented behaviour with no workaround: on one major platform, “the token secret is only shown once.” Create an API token, and if you do not copy it at that moment, you cannot retrieve it. You can only create a new one.

That means a secrets inventory is not a convenience. It is the only way to know which credentials exist, because the dashboard will tell you a token’s name and scope but not its value.

Token scoping is documented and worth using properly: permissions are assigned by permission group and level, and can be restricted to a specific resource rather than an entire account. Some platforms also support client IP filtering and an expiry. Scoping is a blast-radius control, and it is also documentation — a token named deploy-blog-production with Zone DNS Read on one zone tells future-you exactly what it was for.

The conventional rule, and an honest caveat

The widely repeated guidance is the 3-2-1 rule: three copies of your data, on two different media, with one copy offsite.

I tried to verify this against a primary government or standards source and could not reach one — the relevant agency pages were unavailable during this pass. So I am describing it as convention rather than citing an authority, and you should treat it that way. The principle is sound and the attribution usually given for it is not something I could confirm.

Applied to a static site, the sensible reading is: the repository is one copy, a local clone is a second, the platform’s copy is a third, and an exported zone file stored somewhere else is the offsite element for the part that is not in Git.

Git is a version history, not a backup schedule

The distinction is worth drawing explicitly, because “it is in Git” is the most common reason people skip this entire topic.

Git gives you history and distributed copies. What it does not give you is protection against the specific failure where the hosting provider’s account is unavailable. Two documented behaviours make the point:

Deletion is destructive and immediate. One major provider documents that deleting a repository “will permanently delete team permissions” and that the action “cannot be undone.”

There is a recovery window, and it is bounded. The same provider documents that a deleted repository “can be restored within 90 days.” That is a genuinely useful safety net and it is also a deadline — 90 days of somebody else’s retention policy, which is not the same as a backup you control.

I could not find any official statement from a Git host saying “we are not a backup.” The behaviour above is the evidence, and it is enough: a hosted repository has a deletion path with a retention window, and your backup should not depend on somebody else’s retention policy.

Restoring: what the documented path actually is

For a purely generated site, the restoration procedure is short and worth writing down once:

  1. Re-create the platform project.
  2. Set the environment variables from the inventory.
  3. Re-add the domains and update nameservers or records if the DNS provider changed.
  4. Re-create the deploy credential and store it in your CI secrets.
  5. Re-import the zone if DNS needs rebuilding, using the exported zone file.
  6. Deploy. The build regenerates the output.

Note that no step involves restoring build output. That is the part of a static site that genuinely does not need backing up — and it is worth noting that no vendor documents this as a recommended procedure, because it follows from the build model rather than from a policy. It is reasoning, and it is sound reasoning.

The one thing that does not fit this list is content that is not in the repository — user submissions, comments in a third-party system, form entries. Those are a separate backup problem with a separate owner.

A 20-minute setup

TaskWhere it goes
Export the DNS zone fileCommit it to the repository, under a clear path
List environment variable namesSame file, alongside the zone
List associated domainsSame file
Store secret valuesA password manager, not the repo
Confirm a local clone exists on a second machineAnywhere off the primary machine
Write the restore procedure above into the READMEThe repository
Set a calendar reminder to re-export the zoneQuarterly, and after DNS changes

Seven items. The one people skip is the last, and it is the one that makes the difference between a backup that exists and a backup that is current — an exported zone file from two years ago is a historical document, not a recovery asset.

When the whole exercise is overkill

If you maintain a personal site with no email on the domain, no commerce, and content that is genuinely reproducible from source, the exposure is limited to the effort of redoing the DNS setup. That is an hour, not a business continuity problem.

The moment any of these becomes true, the calculus changes and the zone export becomes mandatory rather than tidy:

  • Email is on the domain. MX and SPF records are load-bearing, and losing them stops mail.
  • The domain is used for anything beyond the site. Verification records for other services live in that zone.
  • The site earns revenue. Recovery time is directly measurable in money.

For everything else, a committed zone file and an inventory of variable names is about fifteen minutes of work with a disproportionate payoff. It is the cheapest insurance available on a static site, and it protects precisely the parts that a rebuild cannot recreate.


Written by TestedHost. Every recommendation on this site comes from running the setup described, on a live deployment — not from a vendor spec sheet. Spotted something out of date? Tell us.