# Backup and Restore

This guide explains how to **back up and restore** EventSourcingDB using the HTTP API. It covers **when and how to create backups**, how to **restore them**, and what constraints apply.

## Overview

Backups in EventSourcingDB are **newline-delimited JSON files** that **contain both events and schemas**. Snapshots are implicitly included because they are **stored as regular events**.

*(Changed in 1.3)* Currently, **only full backups are supported**. Incremental or differential backups are not yet available.

## Performing a Backup

*(Changed in 1.3)* To create a backup, send a **`POST`** request to **`/api/v1/backup`**. The server responds with a stream of **newline-delimited JSON** representing **all events and schemas in the database**.

```shell
curl \
  -X POST \
  -H "Authorization: Bearer <API_TOKEN>" \
  http://localhost:3000/api/v1/backup \
  -o backup.json
```

By default, the backup is streamed to **standard output**. In the example above, the `-o` option redirects it to a file named `backup.json`.

The filename `backup.json` is used **for demonstration purposes only** – you can **choose any name** or **storage path** that fits your backup strategy.

If the backup cannot be completed – say part of the store cannot be read – the stream ends with an `error` line instead:

```json
{"type":"error","payload":"..."}
```

The status code is already **200** by the time the first line goes out, so **the last line is what tells you whether the backup is complete**. Treat a backup that ends with an `error` line as incomplete, and do not keep it as your backup.

*(Changed in 1.3)* The backup can be run **while the database is in normal operation** or in **read-only mode**. During the backup, EventSourcingDB **automatically switches into read-only mode** to **prevent write conflicts**. This temporary mode is **lifted when the backup completes**.

> **Optional Manual Read-Only Mode**
>
> If you're migrating to a new instance, you can **explicitly enable read-only mode** before starting the backup to **ensure no writes occur after the backup completes**. However, read-only mode can then only be **exited via restart**, and **any restart exits it**, including one you did not plan, such as Kubernetes restarting the pod. To keep the old instance read-only for the whole migration, start it with the **`--read-only` flag** instead.

## Restoring a Backup

*(Changed in 1.3)* To **restore a backup**, send the backup file as a binary payload to the **`/api/v1/restore`** endpoint:

```shell
curl \
  -i \
  -X POST \
  -H "Authorization: Bearer <API_TOKEN>" \
  --data-binary '@backup.json' \
  http://localhost:3000/api/v1/restore
```

The database will enter **lockdown mode** during the restore. In this mode, **all read and write operations are disabled**. Lockdown mode ensures **consistency** and is **automatically lifted once the restore is complete**.

> **Restore Requires an Empty Database**
>
> Restores can only be performed into **an empty database**. If data is already present, the restore will be **rejected**. This prevents **accidental overwrites or conflicts**.

## Compatibility

*(Changed in 1.3)* There are **no hard limits** on the size of the backup file, apart from operating system constraints. EventSourcingDB imposes no restrictions. Backups are **version-tolerant** and can be restored **across different versions** of EventSourcingDB, assuming **format compatibility is maintained**.

*(Removed in 1.3; Broken in 1.2, fixed in 1.3)* **When the clock of the server goes back** while it writes, for example when NTP corrects it, new events can be **older than the event before them**. EventSourcingDB then **refuses to restore a backup** that holds such an event, even one it created itself, and **[verifying](/docs/eventsourcingdb/v1.2/verifying-store-integrity)** and **[auditing](/docs/eventsourcingdb/v1.2/auditing-the-event-store)** the store fail from that event on. Since events cannot be changed, this holds for every later backup of the database as well.

## Best Practices

- Store backups in a **secure, version-controlled location**
- Use read-only mode for **zero-downtime migrations**
- *(Changed in 1.3)* **Monitor backup and restore processes** via logs, HTTP status codes, and the last line of each backup
- Restore only into **freshly initialized databases**
- Use **version-pinned builds** to ensure compatibility

Backups give you confidence that your event history is **safe**, **portable**, and **restorable** – across environments and over time.
