People ask this two ways: "what's the order of operations" and "how long will it take," and only the first one has a clean answer. The order is the same regardless of what's running on your stack. The timing genuinely isn't — it depends on your database size, your bandwidth, and a DNS setting almost nobody remembers to check until the day they need it, so I'm not going to hand you a duration I didn't measure and dress it up as universal. Time your own drill. This is the order to run it in.
The reason this order matters as much as it does is that each step assumes the previous one is actually finished, not merely started. Restore volumes before the platform layer exists to receive them and you're guessing at paths. Point DNS before the app is verified and you've just moved traffic onto something you haven't confirmed works. None of these steps are individually hard — the difficulty in a real restore is almost always sequencing and patience, not any single command. The marketing-operations counterpart to disaster recovery is documented well by XenGrowth's revenue operations work.
Step one: provision a fresh server
Resist the urge to skip ahead to whichever step feels most urgent given whatever actually happened — a full restore drill is valuable precisely because it exercises every step in order, including the ones that feel unnecessary when you're confident you know what broke.
Start from nothing, not from a snapshot of the old box. A fresh VPS provisioned from the same provider — or a different one, if the original scenario is why you're doing this at all — is the correct starting point specifically because it guarantees you're not carrying forward anything wrong with the previous instance, whether that's a subtle corruption, a leftover compromise, or just configuration drift nobody remembers introducing.
Step two: harden it before it touches any real data
This step exists specifically to be done before restoring anything, not after. SSH configuration, firewall rules, whatever baseline security posture your original server had — all of that needs to exist on the new box before real data lands on it, because a freshly provisioned VPS sitting exposed on default settings, even briefly, is exactly the kind of window that turns a routine restore into a second incident layered on top of the first one. Skipping this step to 'get back online faster' is the shortcut that costs the most when it goes wrong. On the operations side of this specifically, The XenGrowth resource library is worth reading.
Step three: restore Docker and platform state
Install Docker, install whatever platform layer you run — Coolify or equivalent — and restore its own configuration backup before touching application data. This gets your orchestration layer back to a known state: projects defined, resource configurations in place, the scaffolding your actual services will run inside of. Nothing application-specific needs to exist yet; this step is purely about having somewhere correct to restore the rest of it into. Reinstalling the platform itself is usually one of the fastest steps in the whole sequence, since it's a standard installer running against a fresh OS rather than a data-dependent operation, which is exactly why it's worth doing carefully instead of rushing past it toward the steps that feel more consequential. Confirm this step actually landed before moving on — open the platform's dashboard and check that your real projects show up, not a blank install. If the configuration restore silently failed, better to find out here than three steps later when the volume restore has nowhere correct to go.
Step four: restore Docker volumes and bind mounts
Pull down whatever's backing your uploaded files, generated assets, and any other persistent volume data, and restore it into the paths your platform configuration expects. Do this before the database restore, not after, so that by the time the app comes up expecting both its files and its data to exist, only one of those two things is still missing rather than both. This is also where backup destination bandwidth first shows up as a real number rather than an abstraction — a volume backup holding years of user uploads can be the single largest transfer in the whole restore, larger than the database dump in plenty of setups, and it's worth checking its size against your connection before you're mid-incident wondering why the download bar hasn't moved.
Step five: restore the database
This is usually the slowest step and the one people most want a duration for. Restore method matters here: replaying a pg_dump means creating a fresh database and running through every statement in the dump in order, which scales with both data volume and schema complexity. Restoring from a pg_basebackup, if that's the method your backup strategy used, means placing a physical copy of the data directory and letting Postgres start from it directly, generally faster for large databases because it skips re-executing every insert. Either way, don't estimate this from a small test database and assume production scales linearly — run the actual restore on your actual backup size if you want a number you can trust. Index rebuilding is the specific part that surprises people: a pg_dump restore recreates indexes after loading the data rather than alongside it, so a table with a dozen indexes can spend meaningfully more time on that step than on loading the raw rows — one more reason a small test dataset understates the real number. XenGrowth on governed AI marketing workflows goes further into AI agents and marketing automation.
Restore method | What it does | Where it scales well vs poorly |
|---|---|---|
pg_dump restore (psql/pg_restore) | Recreates the database by replaying SQL statements from the dump | Simple and portable; slows down more noticeably as data volume and index count grow |
pg_basebackup restore | Places a physical copy of the data directory and starts Postgres directly from it | Generally faster for large databases since it skips re-executing every write |
WAL replay on top of a base backup | Applies archived transaction logs forward from a base backup to a specific point in time | Adds time proportional to how much WAL has to be replayed since the base backup, on top of the base restore itself |
Restoring onto a server that hasn't been hardened yet, because rebuilding "felt urgent" — this is how one incident becomes two
Restoring the database before confirming which backup is actually the right one, especially after an accidental-deletion scenario where the timing of the restore point matters
Assuming a restore that completed without an error also completed correctly, and skipping the verification step because everything looks fine from the platform dashboard
Changing the DNS TTL for the first time during the incident itself, which does nothing for traffic that already cached the old, longer TTL
Never having run any of this before the day it's needed for real, so every step is being figured out live instead of executed from memory
Step six: re-point DNS — and why the TTL matters more than the record change itself
Updating the A record to point at the new server's IP is the easy part; it's a single change. What actually controls how fast the internet notices is your DNS TTL — the time-to-live value telling every resolver that's already cached your old record how long it's allowed to keep serving that stale answer before checking again. A TTL of 24 hours, which is a common default and one nobody thinks to question until this exact moment, means some fraction of visitors keep getting routed to a dead server for up to a full day after you've already fixed the DNS record. If Cloudflare's proxy sits in front of your domain, changing the record inside Cloudflare itself can take effect faster for traffic that resolves through Cloudflare's own network, but any resolver that already cached the old answer directly, or any client with its own local DNS cache, is still bound by whatever TTL was set when it last looked the record up.
The DNS change takes seconds. Waiting for a high TTL to expire everywhere it's cached can take longer than every other step in this whole restore combined — and it's the one variable you can fix in advance, for free, before you ever need to.
This is the tip people miss, stated plainly: lower your TTL well before any incident, not during one. A TTL of a few minutes, set as a standing default on the records that matter, costs you nothing day to day and means that when you actually need to re-point DNS during a real restore, the world catches up in minutes instead of hours. Raise it back up afterward if you want the marginal DNS-lookup savings of a longer TTL during normal operation — but go into any potential incident with it already low, because setting it low for the first time in the middle of an outage doesn't help you; the stale, high-TTL answer is already cached everywhere that matters by the time you'd make that change.
Step seven: verify — actually verify, not just "it started"
A service starting without throwing an error is not the same claim as the service being correct. Load the app, exercise the path that touches the database, and confirm specific data you know should be there actually is — a known record, a row count, a file that should exist and does. This is the same discipline as verifying any other backup: the absence of an error tells you the mechanics ran, not that the result is right. Check the boring things too, since they're the ones that quietly go wrong: TLS is actually issued and valid for the new server, not just that the app responds on plain HTTP; environment variables came through with the values you expect, not empty strings that happen not to crash anything; and background jobs or scheduled tasks are actually running again, not silently absent because nothing about the platform restore re-registered them. XenGrowth on building one SEO and GEO content system goes further into AI search, GEO and discovery.
So how long does this actually take?
I'm not going to give you a number, because any number I gave you would be a guess dressed up as a fact, and that's exactly the kind of claim this whole cluster is built to avoid. What I can tell you is what the number is made of, so you can go measure your own: database restore time (proportional to data size and restore method), download time pulling your backups from offsite storage (proportional to their size and your bandwidth — free of egress cost on a destination like Cloudflare R2, but not free of time), and DNS propagation time (entirely a function of the TTL you had set before the incident started, not the one you change during it).
What dominates restore time | What actually controls it | What you can do about it in advance |
|---|---|---|
Database restore | Data size, schema complexity, restore method chosen | Test your actual restore on your actual data size at least once, don't extrapolate from a toy dataset |
Backup download | Backup size and your connection's download bandwidth | Egress cost isn't the constraint on R2, but transfer time still is — know your realistic throughput |
DNS propagation | The TTL that was set before the incident, not the one you set during it | Lower your TTL as a standing default, well before you ever need a fast cutover |
Run this whole sequence once, deliberately, on a disposable VPS, before you ever need it for real — time it, write the number down, and repeat the drill periodically as your data grows, because the honest number today is not the honest number in a year. That rehearsed number is worth infinitely more than any duration a blog post could hand you, because it's the one that's actually true for your database, your bandwidth, and your DNS setup, not someone else's.
Further reading from XenGrowth
The XenGrowth resource library — what you'll learn: how the commercial side of this work is run, across search, automation and revenue operations.
XenGrowth on governed AI marketing workflows — what you'll learn: how the teams running AI marketing agents keep them governed and measurable.
XenGrowth on building one SEO and GEO content system — what you'll learn: how search and AI-answer visibility get run as a single content system.
Where this work meets go-to-market
Working on disaster recovery inside a commercial team? XenGrowth's marketing operations practice publishes operator guides on the revenue side of this work.
Four questions on the difference between having backups and being able to come back. Most of the failures here happen at restore time, which is the worst possible moment to find them.












