How to Use Litestream: The Beginner's Guide (First Replicate, the WAL Rule, Restore, and the LiteFS Decision)
CodexFuse Team · 2026-11-01T14:35:05.369Z · 16 min read
Learn how to use Litestream: install the open-source SQLite replication tool, configure your first replica, restore point-in-time backups, and decide when to graduate to LiteFS.
How to Use Litestream: The Beginner's Guide (First Replicate, the WAL Rule, Restore, and the LiteFS Decision)
Learning how to use Litestream is the fastest way to make a SQLite database survive a dead server. Litestream is a free, open-source Go tool by Ben Johnson that runs beside your SQLite app, watches the database's write-ahead log, and streams every change to cheap object storage like S3 or Backblaze B2 — continuously, while the app keeps running. As of this writing it sits at version 0.5.17, carries an Apache 2.0 license, and holds roughly 14,500 GitHub stars. This Litestream tutorial runs the complete beginner arc in one sitting: the mental model, installation, the WAL rule every beginner must obey, the config file, your first replicate, a real restore, always-on systemd service, Docker, the true monthly cost, the seven beginner mistakes, and the honest LiteFS decision at the end.
Most readers run their app on a single server, so the natural first move is reading the VPS hosting guide — that is where the server your SQLite app lives on comes from. If your app already ships in a container, the Docker beginner guide covers the container lane you will reuse in the Docker section below.
How do you use Litestream?
You use Litestream by installing the binary, pointing it at your SQLite database, and running litestream replicate so it streams write-ahead log frames to an object-storage replica — then you restore from that replica when disaster strikes. The full beginner path is eight steps:
- Confirm your database runs in WAL journal mode and set a 5-second busy timeout.
- Install Litestream from the binary, the .deb package, or Homebrew.
- Write a small
litestream.ymlconfig with your database path and replica URL. - Run
litestream replicate -config litestream.ymland watch it stream. - Practice a restore to a scratch database before you ever need one.
- Move the config to
/etc/litestream.ymland enable the systemd service. - Pick a sync interval you can afford, because PUT requests are the real cost.
- Decide once, up front, whether your app is single-writer (Litestream) or needs multi-writer (LiteFS).
What is Litestream, exactly?
Litestream is a continuous backup and replication layer for SQLite that works by tailing the write-ahead log instead of copying files. Here is the one-sentence mental model to carry through this whole guide: your app keeps writing to its normal app.db file on disk, and Litestream sits next to it, reads every new WAL frame the moment SQLite commits it, and ships those frames to a replica in S3, Google Cloud Storage, Azure, SFTP, or even a local folder. It is SQLite replication done the append-only way: because it ships changes continuously, a crash costs you seconds of data, not hours — and restores are just a snapshot plus WAL replay.
The design choice that makes this possible is discipline: Litestream never touches the live database file directly. As the independent guide on amireslampanah.com puts it, "Litestream is read-only against the database file via the SQLite API - it does not touch the WAL pages directly." That read-only posture is why it is safe to run against a production database while the app is writing.
What do you need before installing Litestream?
You need three things: a SQLite database in WAL journal mode, a Litestream binary, and an object-storage target with credentials. WAL mode is the non-negotiable one — Litestream only works with the SQLite WAL journaling mode, because WAL frames are the actual data stream it replicates. If your database is still in the default delete/rollback journal mode, the WAL rule section below fixes that with a single PRAGMA.
For storage, any S3-compatible target works: Amazon S3, Backblaze B2, MinIO you host yourself, Google Cloud Storage, Azure Blob, SFTP, or a plain local directory for testing. The cheapest honest starting point is a new B2 account, whose first 10 GB of storage is always free — plenty for a small database's snapshot plus a month of WAL frames.
How do you install Litestream?
Install Litestream from the release binaries on GitHub — the Debian package is the smoothest path on a VPS. The current release is v0.5.17, published August 31, 2026, and ships .deb, .rpm, tar.gz archives for Linux (amd64, arm64, armv6, armv7) and macOS, plus Homebrew. On Debian or Ubuntu:
wget https://github.com/benbjohnson/litestream/releases/download/v0.5.17/litestream-v0.5.17-linux-amd64.deb
sudo dpkg -i litestream-v0.5.17-linux-amd64.deb
litestream version
On macOS or for a quick test machine, brew tap benbjohnson/litestream && brew install litestream gets you the same binary. The whole litestream install takes under a minute, and the Debian package also drops a sample config at /etc/litestream.yml and a systemd unit (disabled by default), which the systemd section below puts to work. One platform caveat from the release notes: Windows binaries are provided for convenience, but Windows is not an officially supported platform.
What is the WAL rule every beginner must know?
The WAL rule is this: Litestream only works with SQLite in WAL journal mode, and your application must set PRAGMA journal_mode = WAL; plus PRAGMA busy_timeout = 5000;. The busy timeout matters because Litestream takes brief write locks when it checkpoints, and without it a busy app can throw locking errors at exactly the wrong moment. Litestream will automatically flip a database to WAL mode if the app has not already enabled it, but making it explicit in your app startup is the safer habit.
The same rule has a dark twin: never rsync, scp, or file-copy a live SQLite database that Litestream is watching, and never run Litestream on a database you are concurrently copying at the file level. As the amireslampanah guide states: "Do not use it on a database that is being concurrently rsynced/copied, or that uses non-WAL journal modes." File-level copies of a WAL-mode database are inconsistent by nature — that is precisely the problem Litestream exists to solve, so let it do the replicating and keep rsync away.
Two more PRAGMAs worth knowing from the official tips page: PRAGMA synchronous = NORMAL; is safe in WAL mode and improves throughput, and PRAGMA wal_autocheckpoint = 0; is recommended for high-write-load servers so checkpointing stays under your control.
How do you write a litestream.yml config?
A Litestream config names your databases and, for each one, a single replica URL — the v0.5.0 schema uses one singular replica: per database, and the old multi-replica arrays are deprecated. Here is a complete minimal config for a small app backing up to Backblaze B2:
dbs:
- path: /var/lib/myapp/app.db
replica:
type: s3
bucket: myapp-litestream
path: prod/app.db
endpoint: https://s3.us-west-004.backblazeb2.com
region: us-west-004
sync-interval: 10s
snapshot:
interval: 24h
retention: 24h
Two details carry the whole design. First, the replica URL is the entire destination contract: url: s3://mybucket/path/to/db works as shorthand, and the table below maps every supported scheme to its URL shape — the litestream s3 setup in the example above is just the most common row. Second, credentials never go in the config — Litestream reads them from the environment automatically (AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY, or the LITESTREAM_-prefixed equivalents), and you can interpolate them with ${VAR} anywhere in the file.
| Storage backend | Replica URL shape | When to use it |
|---|---|---|
| Amazon S3 | s3://bucket/path/db | Default production choice |
| S3-compatible (B2, MinIO) | s3://bucket/path/db + endpoint | Cheapest real backups |
| Google Cloud Storage | gs://bucket/path/db | Already on GCP |
| Azure Blob Storage | abs://[email protected]/container/db | Already on Azure |
| SFTP | sftp://user@host:22/backup/db | Private server without object storage |
| NATS | nats://host:4222/bucket | Stream-native infrastructure |
| WebDAV | webdavs://host/path/db | HTTPS storage appliances |
| Local file | file:///backups/my.db | Testing and dev only |
Defaults you should know before touching them: sync-interval is 1 second, snapshots run every 24 hours with 24-hour retention, and the default config path is /etc/litestream.yml (override with the LITESTREAM_CONFIG environment variable). Leave the intervals at their defaults until you have read the cost section — the sync interval is your monthly bill in disguise.
How do you start your first replication?
Start replication with litestream replicate -config /etc/litestream.yml — that single command launches the daemon, which reads your config and streams every database until the process exits. The fastest way to see it work is the local MinIO recipe straight from the official getting-started tutorial:
docker run -p 9000:9000 minio/minio server /data
export LITESTREAM_ACCESS_KEY_ID=minioadmin
export LITESTREAM_SECRET_ACCESS_KEY=minioadmin
litestream replicate fruits.db s3://mybkt.localhost:9000/fruits.db
Write a few rows into fruits.db from another terminal while it runs, and you will see replication activity in the logs — the command blocks forever, which is exactly the point: it is meant to run as a background service.
Now the distinction that confuses every beginner: litestream replicate is the daemon launcher, while litestream start and litestream stop are client commands that tell an already-running daemon to resume or pause replication for one database. Per the official tutorial: "they require the daemon's IPC control socket to be enabled in the configuration file." If you just want Litestream running, replicate is the only command you need; start and stop exist for pausing replication on demand without killing the daemon.
How do you restore a Litestream backup?
You restore with litestream restore -o restored.db s3://mybucket/path/app.db, which downloads the latest snapshot and replays the WAL segments recorded after it. Restore is the command you should rehearse when nothing is wrong, because it is the entire payoff of the system. You can restore either a database named in your config or a replica URL directly — the URL form is what disaster-recovery runbooks use:
litestream restore -o /tmp/app-rewind.db -timestamp 2026-02-27T15:00:00Z s3://my-app-litestream/prod/app.db
The -timestamp flag is the point-in-time superpower: pass an RFC3339 timestamp and Litestream reconstructs the database exactly as it looked then, which is how you recover from "oops, I deleted the wrong rows" as well as from a dead disk. A -txid flag offers the same rewind at transaction granularity, and -o chooses where the rebuilt database lands.
The honest boundary, quoted verbatim from the independent tutorial: "Replication is one-way and append-only; the destination is not a live SQLite endpoint." Your replica is a snapshot archive plus a WAL stream, not a hot standby you can query. If you need a lightweight read-only copy without restoring to disk, the v0.5.x VFS extension (installable via pip install litestream-vfs or npm/gem) exposes replicas through SQLite's virtual file system — but that is an advanced lane, not the beginner arc.
How much does Litestream cost on S3?
Litestream itself is free and open source; your only bill is object storage, and Ben Johnson's own line on the matter is: "Typical costs are only about $1 per month." Storage really is that cheap — a small app's daily snapshot plus a month of WAL frames lands around 100–500 MB, which at S3's $0.023 per GB-month is literal cents, and Backblaze B2's always-free 10 GB tier covers many hobby apps entirely.
The cost you actually control is request volume, and the official config reference publishes the math. Litestream issues a PUT on roughly every sync interval when writes are happening:
| sync-interval | Monthly PUT-request cost (S3, constant writes) | Best for |
|---|---|---|
| 1s (default) | ~$12.96/month | Maximum RPO on a busy DB |
| 10s | ~$1.30/month | The sweet spot for most apps |
| 1m | ~$0.22/month | Quiet databases |
That table is why the default 1-second interval deserves a conscious decision, not a shrug. A quiet side project at 10 seconds costs about a dollar a month in requests plus cents in storage; the same database at 1 second costs thirteen dollars. Dropping the interval is the real cost lever — storage size barely matters until your database gets large.
How do you run Litestream with systemd?
Run Litestream as a systemd service: move your config to /etc/litestream.yml, then sudo systemctl enable --now litestream starts replication on boot and keeps it alive. This litestream systemd setup is how production servers run it — the daemon is supervised, logs go to the journal, and a crashed process restarts in a second.
The unit is a plain always-restart service wrapping the daemon command. A representative example:
[Unit]
Description=Litestream replication service
After=network.target
[Service]
Type=simple
Restart=always
RestartSec=1
ExecStart=/usr/bin/litestream replicate -config /etc/litestream.yml
EnvironmentFile=/etc/litestream.env
[Install]
WantedBy=multi-user.target
Keep credentials in the referenced /etc/litestream.env file (mode 600, root-only), not in the unit or the YAML. After enabling, sudo systemctl status litestream confirms it is active and sudo journalctl -u litestream -f shows the live replication log — watch it for a minute on first boot; the first snapshot upload is the moment your backup story becomes real. If the server behind all of this is still a shopping decision, the cheap VPS comparison covers the side-project tier where most Litestream users land.
How do you run Litestream in Docker?
Run the official litestream/litestream image as a sidecar next to your app container, sharing a named volume that holds the database. The sidecar pattern is the documented default and keeps concerns clean — your app container knows nothing about backups:
docker run -d --env LITESTREAM_ACCESS_KEY_ID --env LITESTREAM_SECRET_ACCESS_KEY -v app-data:/data -v ./litestream.yml:/etc/litestream.yml litestream/litestream replicate
The alternative documented pattern is same-container: litestream replicate -exec "myapp -myflag myarg" runs your app as a child process so Litestream supervises it directly. It is the pattern Fly.io popularized, and it guarantees the database path is always local to the replicator. Whichever litestream docker pattern you choose, the replica still lands in the same object-storage URL — containers change the packaging, not the backup format.
One Docker-specific warning carries over from the official docs, stated plainly: network filesystems and cross-OS bind mounts can corrupt a SQLite database — use named volumes, and keep the host and container on the same OS. Docker Desktop's bind mounts on macOS and Windows fall into the danger zone; a named volume does not.
What are the 7 mistakes every Litestream beginner makes?
Every one of these mistakes is documented in the official docs or the independent tutorial — they keep happening because the defaults look harmless.
| Mistake | Why it hurts | The fix |
|---|---|---|
| Forgetting WAL mode | Litestream silently has nothing to replicate | PRAGMA journal_mode=WAL; in app startup |
| Skipping busy_timeout | Locking errors during checkpoints | PRAGMA busy_timeout=5000; |
| rsync-ing the live DB "for safety" | Inconsistent copies; worse, a false sense of backup | Let Litestream replicate; rsync only replicas |
| Leaving sync-interval at 1s | $13/month in PUTs on a quiet database | 10s or 1m unless RPO demands otherwise |
| Using multi-replica config arrays | Deprecated since v0.5.0; config rejected or ignored | One singular replica: per db |
| Running two writers behind a load balancer | Unsupported model; split-brain databases | One writer, or graduate to LiteFS |
| Never testing restore | A backup you have never restored is a rumor | Monthly litestream restore drill to /tmp |
Litestream vs LiteFS: when do you switch?
You switch to LiteFS the day your app needs more than one writer. Litestream is a single-writer tool: one process writes to one database file, and Litestream backs it up. Put a load balancer in front of two instances writing to the same Litestream-backed database and you have entered an unsupported model — as the independent guide states: "for that, use Litestream's successor project, LiteFS."
LiteFS is Ben Johnson's second project in this space: it distributes SQLite with leader election so multiple machines can participate, while Litestream, in usher.dev's summary, "is now focused primarily on disaster recovery." Even LiteFS's own documentation agrees with the division of labor: "For backups of SQLite, look at Litestream." The graduation path is therefore clean — run Litestream while one server writes; reach for LiteFS when scale forces multi-writer. Both are by the same author, both are open source, and choosing wrong in either direction costs you the property you actually needed.
When should you NOT use Litestream?
Do not use Litestream for multi-writer apps, for databases that cannot run in WAL mode, or when what you actually need is file-level versioned backup. The last case deserves its line: Litestream replicates a live database's logical changes; if you need whole-machine or whole-directory backup with deduplication and encryption, the Restic beginner guide covers that lane — Restic snapshots files, Litestream streams database transactions, and they complement rather than replace each other.
Also skip Litestream when your SQLite usage is truly embedded and ephemeral — a desktop app's local cache does not need continuous replication. The tool earns its keep exactly where a server writes to SQLite in production and losing the disk would lose the business.
Sources
- GitHub releases API — api.github.com/repos/benbjohnson/litestream/releases/latest — v0.5.17, published 2026-08-31
- Release page — github.com/benbjohnson/litestream/releases/tag/v0.5.17 — VFS extension (pip/npm/gem install), Tigris multipart fix, v3 WAL segment >4GB restore fix, Windows not officially supported, install methods (brew tap, .deb, .rpm, tar.gz)
- Star tracker — star-history.com — ~14,500 stars, Apache 2.0 license (approximate, third-party)
- Getting started (vendor tutorial) — litestream.io/getting-started/ — MinIO/Docker first-run, replicate-vs-start/stop distinction, VFS read-replica note
- Config reference — litestream.io/reference/config — singular replica: field (v0.5.0+), replica URL schemes (s3, gs, abs, sftp, nats, webdav, file), env-var credential names, ${VAR} expansion, sync-interval/snapshot defaults, request-cost table ($12.96 / $1.30 / $0.22)
- Tips page — litestream.io/tips — WAL mode requirement, PRAGMA busy_timeout = 5000, synchronous = NORMAL, wal_autocheckpoint = 0
- Docker guide — litestream.io/guides/docker — official image litestream/litestream, sidecar and -exec patterns, named-volume warning
- systemd guide — litestream.io/guides/systemd — /etc/litestream.yml, enable/start/stop commands
- Independent tutorial — amireslampanah.com/tutorials/litestream-sqlite-replication.html (Feb 28, 2026) — WAL + busy_timeout pragmas, never-rsync quote, point-in-time restore example, one-way/append-only quotes, standby read-only copy, B2 backend listing
- ServiceStack docs — docs.servicestack.net/ormlite/litestream — Ben Johnson quote: "Typical costs are only about $1 per month"
- Upstash blog (Oct 2026) — Backblaze B2: $6.95/TB/month, first 10 GB free
- dev.to/ethan-carter (Aug 2026) — B2: first 10 GB always free, free egress up to 3x storage
- usher.dev (Oct 2022) — Litestream as first attempt, now focused on disaster recovery; live replication moved to LiteFS
- Fly.io LiteFS Cloud docs — fly.io/blog/litefs-cloud/ — "For backups of SQLite, look at Litestream"
- Package install index — x-cmd.com/install/litestream/ — file:// replica URL shape
Frequently Asked Questions
How do you use Litestream for SQLite backups?
Install the Litestream binary, set your database to WAL mode with a 5-second busy timeout, write a small config naming your database path and a replica URL, then run litestream replicate. It streams write-ahead log frames to object storage continuously and restores from them with litestream restore — including point-in-time restores via -timestamp.
Does Litestream require WAL mode?
Yes, unconditionally. Litestream only works with the SQLite WAL journaling mode because the WAL is the data stream it replicates. It will flip a database to WAL automatically if the app has not, but the documented practice is to set PRAGMA journal_mode = WAL; and PRAGMA busy_timeout = 5000; in your application startup.
How much does running Litestream cost?
Ben Johnson's own estimate is about $1 per month for typical use: storage is cents (100–500 MB for a small app) and Backblaze B2's first 10 GB is free. The lever is the sync interval — the default 1 second can cost ~$12.96/month in S3 PUT requests on a constantly writing database, while 10 seconds drops it to ~$1.30.
Can Litestream replicate to multiple writers?
No. Litestream is a single-writer tool for disaster recovery; the replica is one-way and append-only, not a live database. If your app needs several processes writing behind a load balancer, the documented graduation is LiteFS, Ben Johnson's successor project with leader election.
Is Litestream still maintained?
Yes. The current release is v0.5.17 from August 31, 2026, adding a read-only VFS extension installable via pip, npm, and gem alongside multipart-upload and large-segment restore fixes. It remains the recommended answer for SQLite backups even in LiteFS's own documentation.