---
title: Backups and restore
description: A database is backed up without you setting it up; restore takes it back to a point in time, in place.
type: how-to
product: database
summary: What is kept for you, and how to put a database back to an earlier moment.
updated: 2026-10-01
order: 4
---

Every database has its own backup, kept on our side and separate from it. You
do not schedule it, store it or name it. What you do is decide when to go
back to it.

## What is kept

A database is protected continuously rather than at a nightly snapshot: the
backups of the day plus the write-ahead log mean a restore can name any point
inside the retention window, not just the last backup. That window is what
bounds recovery — nothing older than it can be restored.

The backup belongs to the database, not to a project or an environment:
dropping a project, or deleting a database with
[`deletion_protection`](/docs/api/databases) unset, does not leave its backup
behind in a place you could restore from afterwards.

## Restore to a point in time

A restore takes the point in time and puts the database back to it, in place.

<Callout tone="note" title="Restore is by request">
`databases restore` is in the [API reference](/docs/api/databases/restore), and
api.sylphx.com does not serve it, or the `delete` call. To
restore a database today, write to hi@sylphx.com with the database name and the
moment you want it back to. Name the moment as an exact
UTC timestamp, such as `2026-09-28T09:00:00Z`.
</Callout>

<Callout tone="warning" title="A restore is not a rollback">
It puts the whole database back, and everything written after the restore
point is gone — including writes that had nothing to do with whatever went
wrong. Take the name of the exact moment first; a restore *to* the wrong
second is one you cannot undo by restoring again, because the backups after
it are gone with the database.
</Callout>

While the restore runs, the database is unavailable: connections fail rather
than serve stale or partial data. When it finishes it is the same database —
same name, same `uid` — with its contents from the restore point.

## Protect against the wrong delete

`deletion_protection` in the spec is the guard that survives a mistake:

<PropertyTable
	properties={[
		{
			name: 'deletion_protection',
			type: 'bool',
			description: 'While set, Delete fails with DELETION_PROTECTED and the database is kept.',
		},
	]}
/>

Set it on anything whose loss would be a day's work, and unset it for the
minutes it takes to delete a scratch database. It is a spec field, so it
changes through `update` like any other.

## Rehearse before a risky migration

The useful habit is to restore *before* you need to: name the restore point,
run the migration against a copy of the data, and find out what it does to
real rows while the production database is still untouched. A rehearsal is a
restore you would have had to do anyway, made at a moment you chose.

## After a restore

- Point the application at the database again, or wait for it — connections
  made before the restore are gone.
- Check the schema version. A restore takes the schema back too, so a
  migration that ran after the restore point has to run again.
- Read the last few minutes of application logs against what the database now
  has: a restore explains the data, not the writes that were discarded.

<RelatedDocs
	links={[
		{
			href: '/docs/api/databases/restore',
			label: 'restore',
			description: 'Every field, the scope, and the examples.',
		},
		{
			href: '/docs/database/migrations',
			label: 'Migrations',
			description: 'Change the schema, and why a migration is the safer undo.',
		},
		{
			href: '/docs/database/quickstart',
			label: 'Quickstart',
			description: 'Create a database and get its connection.',
		},
	]}
/>
