Command: restore

The restore command recovers a database from a replica. By default, it attempts to restore the latest data. However, it can also restore databases to a specific point-in-time if it is covered by the WAL time range. It can also run in follow mode (-f) to continuously restore new data as it becomes available, enabling read-only database replicas.

Restoration will only run if the output database file does not exist so you cannot accidentally overwrite your running database.

Usage

With a database path

This command will restore a database specified in the Litestream configuration file to its original location.

litestream restore [arguments] DB_PATH

With a replica URL

This command will restore from a replica without using the Litestream configuration file. It is useful if you don’t have a configuration file such as on a development machine.

litestream restore [arguments] REPLICA_URL

Arguments

-o PATH
    Output path of the restored database.
    Defaults to original DB path.

-if-db-not-exists
    Returns exit code of 0 if the database already exists.

-if-replica-exists
    Returns exit code of 0 if no backups are found. This flag allows the restore
    command to succeed gracefully when no matching backup files are available,
    which is useful for automation and conditional restore scenarios.

-parallelism NUM
    Determines the number of WAL files downloaded in parallel.
    Defaults to 8

-txid TXID
    Restore up to a specific hex-encoded transaction ID (inclusive).
    Defaults to use the highest available transaction.

-timestamp TIMESTAMP
    Restore to a specific point-in-time.
    Defaults to use the latest available backup.

-f
    Continuously restores new data as it becomes available.
    The restored database should only be opened in read-only mode.
    Incompatible with -txid and -timestamp.

-follow-interval DURATION
    Sets the polling interval for follow mode.
    Defaults to 1s.

-dry-run
    Print the restore plan without writing any files.
    Incompatible with -f.

-force
    Overwrite an existing non-empty database file.
    Required when the output path already exists and is not empty.

-json
    Output raw JSON instead of human-readable text.

-config PATH
    Specifies the configuration file.
    Defaults to /etc/litestream.yml

-no-expand-env
    Disables environment variable expansion in configuration file.

Conditional Restore Behavior

Using -if-replica-exists

The -if-replica-exists flag modifies the restore command’s behavior when no backup files are found. Without this flag, the command will fail with a non-zero exit code if no matching backups exist. With the flag enabled, the command succeeds (exit code 0) and logs “no matching backups found” instead.

This flag is particularly useful for:

  • Automation scripts: Prevent automated restore processes from failing when backups don’t exist yet
  • Conditional operations: Create scripts that attempt restoration but continue with alternative logic if no backups are available
  • Idempotent deployments: Build deployment scripts that can safely run restore operations without breaking when backups aren’t present
  • Testing environments: Allow test environments to attempt restoration without failing if the backup source hasn’t been populated

Exit Code Behavior

The command returns different exit codes based on the presence of backups:

Scenario Without flag With -if-replica-exists
Backups found and restored Exit 0 Exit 0
No backups found Exit 1 (error) Exit 0 (success)
Other errors Exit 1 (error) Exit 1 (error)

Note that this flag only affects the behavior when ErrTxNotAvailable is returned (no matching backup files). Other errors will still result in a non-zero exit code.

Interaction with Other Flags

The -if-replica-exists flag works alongside other restore flags:

  • -if-db-not-exists: Combined with -if-replica-exists, you can create truly idempotent restore operations that succeed whether the database exists, doesn’t exist, or has no backups available
  • -timestamp: When used with point-in-time restore, the flag will succeed gracefully if no backups exist at the specified timestamp

Important Notes

  • The flag only suppresses the “no backups found” error; other restore errors will still return non-zero exit codes
  • When the flag is used and no backups are found, a log message is emitted: “no matching backups found”

Dry Run

v0.5.12 The -dry-run flag prints the restore plan without writing any files. This allows you to preview exactly which LTX files would be fetched and the transaction ID range that would be restored.

The dry run output includes:

  • Source database path or replica URL
  • Target database path
  • Replica type (file, s3, etc.)
  • Transaction ID range (min to max)
  • List of LTX files with level, size, and timestamp

Dry run is incompatible with follow mode (-f) since follow mode has no fixed end state to preview.

Human-readable output

$ litestream restore -dry-run -o /tmp/my.db s3://mybkt/my.db
Restore plan:
  source: s3://mybkt/my.db
  target: /tmp/my.db
  replica: s3
  txid range: 0000000000000001 - 0000000000000004

Files to fetch:
level  file                                      min_txid          max_txid          size  timestamp
9      0000000000000001-0000000000000004.ltx     0000000000000001  0000000000000004  8192  2026-04-24T12:00:00Z

JSON output

When combined with -json, the plan is returned as a JSON object:

$ litestream restore -dry-run -json -o /tmp/my.db s3://mybkt/my.db
{
  "source": "s3://mybkt/my.db",
  "target_path": "/tmp/my.db",
  "replica": "s3",
  "min_txid": "0000000000000001",
  "max_txid": "0000000000000004",
  "files": [
    {
      "level": 9,
      "name": "0000000000000001-0000000000000004.ltx",
      "min_txid": "0000000000000001",
      "max_txid": "0000000000000004",
      "size": 8192,
      "timestamp": "2026-04-24T12:00:00Z"
    }
  ]
}

Force Overwrite

v0.5.12 By default, the restore command will not overwrite an existing non-empty database file. This is a safety guard to prevent accidentally destroying a running database.

If the output path already exists and is not empty (or if SQLite sidecar files like -wal, -shm, or -journal exist), the restore will fail with an error:

cannot restore, output path already exists and is not empty: /path/to/db. Use -force to overwrite

Use the -force flag to explicitly allow overwriting:

$ litestream restore -force -o /tmp/my.db s3://mybkt/my.db

The -if-db-not-exists flag continues to work as before — it returns exit code 0 if the database already exists, without attempting to overwrite. The -force flag is for cases where you explicitly want to replace an existing database.

JSON Output

v0.5.12 The -json flag outputs machine-readable JSON instead of human-readable text. All log messages are written to stderr so stdout remains parseable JSON.

After a successful restore, the output is a summary object:

$ litestream restore -json -o /tmp/my.db s3://mybkt/my.db
{
  "db_path": "/tmp/my.db",
  "replica": "s3",
  "txid": "0000000000000004",
  "duration_ms": 125,
  "integrity_check": "none"
}
Field Description
db_path Restored database path
replica Replica client type used for the restore
txid Restored transaction ID, when available
duration_ms Restore duration in milliseconds
integrity_check Integrity check mode used: none, quick, or full

Follow Mode

v0.5.9 The -f flag enables follow mode, which continuously polls for new LTX files after the initial restore is complete. This keeps the restored database up-to-date as new transactions are replicated, enabling read-only database replicas that stay in sync with the primary.

Follow mode runs indefinitely until stopped with Ctrl+C (SIGINT), at which point it shuts down cleanly. The polling interval can be adjusted with -follow-interval (default: 1s).

The -f flag is incompatible with -txid and -timestamp because follow mode is designed to continuously track the latest state rather than restore to a fixed point.

Crash Recovery

v0.5.10 Follow mode writes a -txid sidecar file next to the restored database to enable crash recovery. For example, restoring to /tmp/my.db creates a /tmp/my.db-txid file that tracks the last successfully applied transaction. This follows SQLite’s naming convention for associated files (e.g. -wal, -shm).

The -txid file is written atomically (using a temporary file, fsync, and rename) after each batch of LTX files is applied. If the follow mode process crashes or is terminated unexpectedly, it can resume from the saved TXID on restart without requiring a full re-restore.

When follow mode starts and detects both an existing database file and its corresponding -txid file, it reads the saved TXID and resumes replication from that point. This avoids re-downloading and re-applying the entire database history.

Scenario Behavior
Database exists, -txid file missing Error: delete the database and re-restore
Saved TXID is older than earliest snapshot Error: retention has pruned required history
Saved TXID is ahead of latest snapshot Error: delete the database and -txid file to re-restore

If the saved TXID is behind the earliest available snapshot (because retention policies have pruned older data), follow mode returns a clear error instead of silently stalling. Delete the database file and the -txid file and run a fresh restore to recover.

Examples

Database restore

Restore the latest replica for the /var/lib/db database to its original location:

$ litestream restore /var/lib/db

Replica URL restore

Restore from an S3 replica URL to /tmp/my.db:

$ litestream restore -o /tmp/my.db s3://mybkt.litestream.io/my.db

Restore to new path

Restores the /var/lib/db database to /tmp/db instead of its original location:

$ litestream restore -o /tmp/db /var/lib/db

Point-in-time restore

Restore the /var/lib/db database to a specific point-in-time:

$ litestream restore -timestamp 2020-01-01T00:00:00Z /var/lib/db

Follow mode

Continuously restore new data from an S3 replica to maintain a read-only replica:

$ litestream restore -f -o /tmp/read-replica.db s3://mybkt/db

Follow mode with custom interval

Use a longer polling interval to reduce the frequency of replica checks:

$ litestream restore -f -follow-interval 5s -o /tmp/read-replica.db s3://mybkt/db

Dry run

Preview the restore plan without writing any files:

$ litestream restore -dry-run -o /tmp/my.db s3://mybkt/my.db

Dry run with JSON output

Get the restore plan as JSON for scripting:

$ litestream restore -dry-run -json -o /tmp/my.db s3://mybkt/my.db

Force overwrite

Replace an existing database file:

$ litestream restore -force -o /tmp/my.db s3://mybkt/my.db

Restore with JSON summary

Get a machine-readable summary after restore:

$ litestream restore -json -o /tmp/my.db s3://mybkt/my.db

Conditional restore in automation

Use -if-replica-exists to allow restore operations to succeed even when no backups are available:

$ litestream restore -if-replica-exists /var/lib/db

If backups exist, the database is restored. If no backups are found, the command exits successfully (exit code 0) with a log message.

Idempotent deployment script

Combine -if-db-not-exists and -if-replica-exists for fully idempotent restore operations:

$ litestream restore -if-db-not-exists -if-replica-exists /var/lib/db

This command will succeed in these scenarios:

  • Database exists: exits successfully without overwriting
  • Database doesn’t exist, backups available: restores the database
  • Database doesn’t exist, no backups: exits successfully without error

Note: Other errors (network failures, permission issues, corruption, etc.) will still cause the command to fail with a non-zero exit code.

Shell script with error handling

Example script that attempts restoration with fallback logic:

#!/bin/bash
set -e

# Attempt to restore from backup
if litestream restore -if-replica-exists -o /var/lib/app.db s3://mybkt/app.db; then
  echo "Restore completed or no backups found"

  # Check if database exists after restore attempt
  if [ ! -f /var/lib/app.db ]; then
    echo "No backups available, initializing new database"
    # Initialize new database
    sqlite3 /var/lib/app.db < schema.sql
  fi
else
  echo "Restore failed with error"
  exit 1
fi

# Start application
./start-app.sh

Automation with explicit error checking

Script that distinguishes between “no backups” and actual errors:

#!/bin/bash

# Attempt restore without the flag to detect actual errors
if litestream restore /var/lib/db 2>&1 | grep -q "no matching backup files"; then
  echo "No backups found, proceeding with empty database"
  # Initialize database or take alternative action
elif [ $? -eq 0 ]; then
  echo "Database restored successfully"
else
  echo "Restore failed with error"
  exit 1
fi

Alternatively, use the flag for simpler logic:

#!/bin/bash
set -e

# With -if-replica-exists, this succeeds when no backups are found
# (but other errors like network failures will still cause it to fail)
litestream restore -if-replica-exists /var/lib/db

# Check if we got a database or need to initialize
if [ -f /var/lib/db ]; then
  echo "Database restored from backup"
else
  echo "No backups found, initializing new database"
  # Initialize database
fi

Format Detection

v0.5.8 The restore command automatically detects whether backups are in v0.3.x format or LTX format and restores from whichever has the best available data. This works transparently for both file and S3 backends.

Scenario Behavior
With -timestamp Uses format with best snapshot before timestamp
Without -timestamp Uses format with most recent backup overall
Only v0.3.x exists Uses v0.3.x restore
Only LTX exists Uses LTX restore
Both exist, v0.3.x newer Uses v0.3.x restore
Both exist, LTX newer Uses LTX restore

The -timestamp flag works across both formats, selecting the format that has the closest snapshot before the requested time.

This eliminates the need for manual format handling when migrating from v0.3.x to v0.5.x — simply run litestream restore and it will use the best available backup regardless of format.

See Also