Restore a backup

Restore any successful backup in-product — into a new database, over the existing one, or onto a new server — with a pre-flight writability check and a full, redacted restore log.

Not verified yet

Every successful backup can be restored from the dashboard. Open the datasource, find the backup in Backup jobs, and use the row's restore action — a short wizard picks where the data goes, tests that the target is reachable and writable, and queues the run. Progress and the full tool output appear in Restore history on the same page.

Restore is the read-side twin of a backup: it streams the archive back out of storage and replays it into a live database with the engine's own tool (pg_restore / mongorestore). Postgres and MongoDB are supported today.

Want this to happen automatically, as a check rather than a recovery? Restore checks periodically restore a backup into a throwaway database to prove it's recoverable, then tear it down — the automated, never-destructive twin of the flow on this page.

What restore is for

Three jobs, one flow:

  • Recover — bring a database back after data loss, a bad migration, or a dropped table. Restore over the existing database, or into a fresh one next to it so you can copy just what you need across.
  • Clone — stand up a realistic staging, QA, or debugging copy from last night's production backup, on a server you control.
  • Migrate — seed a newly provisioned server from an existing backup as the first step of moving hosts.

Restores are never blocked by billing status — recovering data you already backed up is data-care, not a new chargeable commitment.

The three target modes

ModeRestores intoCredentials you provideDestructive?
New databasea fresh database created on a server you point ata connection string with create-database rights, plus the new database's nameNo
Overwrite existingthe datasource's current databasenone — the datasource's stored credentials are reusedYes
New serverthe database named in a connection string, on a server you provisioneda write-capable connection stringNo*

New database vs. new server — both take a connection string and both are non-destructive, but they differ in who creates the database. New database creates a brand-new database (the name you give it) on a server that's already running other databases, so the name must be free. New server restores into the database your connection string already names — ideal for a freshly provisioned, empty server. On Postgres it creates that database if it's missing.

Is it safe? What each mode touches

New database and new server never touch your original database — they write somewhere new, so the worst case is a failed run with nothing lost. *New server is only "not destructive" in the sense that it won't touch the source datasource; if you point it at a server that already holds data under that database name, its objects can be replaced. Point it at an empty target.

Overwrite is destructive and irreversible. It replays the backup over the datasource's live database, dropping and recreating every object the archive contains (pg_restore --clean --if-exists on Postgres, per-collection --drop on MongoDB). There is no undo. The wizard makes you tick an explicit confirmation, and the API refuses the run unless you pass confirmOverwrite: true. If you're unsure, restore into a new database first and compare.

One nuance worth knowing: overwrite is not a clean-slate wipe. Objects that exist in the target but are absent from the backup survive on Postgres (only what the archive contains is dropped and recreated); on MongoDB, --drop clears each collection the archive is about to restore, but collections not in the archive are left alone. If you need a guaranteed pristine result, restore into a new empty database instead.

The target check (pre-flight)

Before anything runs, the wizard's Test restore target verifies the target is reachable and writable — so a read-only role or an unreachable host fails in the wizard, not halfway through a restore:

  • Overwrite — the datasource's stored credentials are tested by creating and dropping a throwaway norcube_write_test_… table (a collection on MongoDB). Backup credentials are frequently a read-only role — this catches that up front. If the role can't write, restore with a write-capable connection string via new server instead.
  • New database — the supplied connection is checked for create-database capability, and the chosen name is checked for collisions (it must not exist yet).
  • New server — a write test runs against the database named in the connection string.

Target connection strings are used once: KMS-encrypted at rest while the restore is queued, never returned by any API, and scrubbed the moment the run reaches a terminal state — see Encryption.

Reaching a private target

The writability probe and the restore worker connect to your target from the same single static egress IP as every backup worker — 18.196.207.101. If the target database (or the new server you're restoring onto) sits behind a firewall or security group, allow that IP on the database port, exactly as you would for connecting a datasource. A target that isn't reachable from the allowlisted IP fails the pre-flight check with a timeout/network_unreachable result before any restore is queued.

Following a restore

Restore history on the datasource page tracks every run — status, mode, a redacted target reference (postgres://…@host:5432/db, never any credential), duration, and bytes restored. While a restore is queued or running the table refreshes automatically.

Every run uploads its full log — the pg_restore / mongorestore output, with any connection strings redacted before storage — viewable in a terminal-style panel and downloadable as a file. The log is kept for failures too; it's usually the fastest way to see why a restore stopped.

A restore that loses contact with the platform (worker crash, network partition) is marked failed within about an hour — never silently blessed as successful. Re-run it; new database and new server runs are always safe to repeat, and re-running an overwrite just replays the same archive.

How it runs

Restores execute on the same isolated, one-shot workers as backups, in the same private network. Each run:

  1. downloads the archive from storage — Norcube-managed or a BYO destination — using the job's own scoped read access,
  2. decompresses it (gzip archives are streamed, never staged whole on disk), and
  3. applies it with the engine's native tool: pg_restore for the custom-format Postgres archives (the matching client major is selected for the target's version), mongorestore --archive for MongoDB.

For new database restores on MongoDB the archive's namespaces are remapped from the source database name to the new one, so the data lands under the name you chose rather than the original. The connection password is never placed on a command line — Postgres gets it via PGPASSWORD, MongoDB via a locked-down config file.

Behaviour and edge cases

  • Only successful, non-expired backups restore. An Expired row's archive has been removed by retention; a failed backup has nothing to restore from. The restore action is disabled for both, with the reason shown.
  • new_server creates the database if missing (Postgres) — pointing it at a freshly provisioned empty server just works. MongoDB creates databases implicitly on first write, so there's no create step in any mode.
  • The two-step overwrite-approval flow is reserved. Today overwrite is guarded by the confirmOverwrite flag plus the write-probe; a future "create-pending, approve-separately" flow is stubbed (POST /restores/{id}/approve-overwrite currently returns 501) and not required.
  • Audit trail — every restore writes restore_job.created / started / completed / failed audit entries, plus one for each log-link download.

On this page