Litestream、意外な点で注意が必要

Litestream を実際に Google Cloud で使ってみて引っかかったところを挙げておく。

なお、今回は以下の環境で試した結果を挙げている。

  • Google Cloud Run Jobs ( x86_64 Linux debian-slim )
  • litestream 0.3.13

2025-10-09 時点で最新は 0.5 なのだが、compaction エラーというログが出続けるので 0.3.13 で動作させた。

Litestreamとは

SQLite データベースファイルをストリーミングレプリケーションできる OSS アプリ。

SQLite ファイルと関連ファイル(WAL)の変更を検知して replication してくれる。これによって SQLite ファイルにもし破損が起きても復旧できるようになる。

SQLite ファイルを読み書きするアプリケーション側には手を加える必要がなく、litestream が litestream.yml にしたがって実際のファイルを監視して動作してくれる。

使い方

バックアップ

  1. litestream.yml を準備
  2. YAML の中で DB ファイルとレプリケーション先を設定
  3. litestream replicate を実行

2 は設定ファイルじゃなくて直接 DB ファイルとレプリケーション先をコマンドライン引数で指定する方法もあるが、後述するが引数に与えられるオプションが少ないので設定ファイルを前提に考えた方がよいと思う。

3 については 2025-10 時点で公式ドキュメントには以下のインフラストラクチャガイドが用意されている。

  • Docker container
  • Kubernetes clouster
  • Systemd service
  • Windows Service

全部関係ないんだけどなという場合も Docker の案内に従う格好になる。1

Running in a Docker container - Litestream

ここに built-in の プロセス管理の仕組みを使う -exec オプションが紹介されている。

litestream replicate -config <config> -exec "app"

とすると、litestream の子プロセスとして app が起動し、app が終了したら litestream も graceful shutdown してくれる。

app が Web アプリじゃない場合はこれが便利。仮にアプリが Rails だとすると rails runner がこれに相当する。Cloud Run だと Cloud Run Jobs になる。

リストア

litestream restore -config <config> <DB_PATH | REPLICA_URL>

ここで一つ問題があって、

  1. restore に利用する replica ファイルが見つからなかった場合は exit status が failure になる
  2. 初回起動時は replica ファイルがないので、replica が restore に失敗したからといってアプリケーション起動そのものをエラーにすべきではない
  3. restore 時にすでに DB ファイルがあってもエラーになる

restore 周りの処理を雑にするなら exit status は無視でもよいが、厳密に処理しようと思ったら工夫が必要になる。

Cloud Storageと組み合わせて使う際の注意点

gcsなのかgsなのか

0.3 と 0.5 で非互換があって、0.5 では gcs という表現が通用しないっぽい。gs に一本化されるようだ。まぁ確かに URL として表現すると gs:// になるのは通例2 なので、「そういうもの」と言えばそういうものだ。

生ファイルシステム以外への転送はログに残らない

これが実はかなりのクセモノ。確認したのは Cloud Storage のみなので「Cloud Storageと組み合わせて」と表現しているけど、生ファイルシステム以外に転送する処理は共通なのではないかと予想している。

このログがどうなるかというと、以下のようになる。

まず、log level を変更する。

logging:
  level: debug

すると以下のようなログが出る。(以下は shutdown 時のログを抜粋したもの)

level=DEBUG msg="sync: ok" db=<DBパス>
level=DEBUG msg="copy-shadow: break: salt mismatch" db=<DBパス> filename=<内部レプリカ>
level=DEBUG msg=copy-shadow db=<DBパス> filename=<内部レプリカ>
level=DEBUG msg=sync db=...

何事もなく成功裡に完了したかのように見えるが、実際には Cloud Storage のレプリカ先の指定を間違えていると黙って書き込みに失敗してしまう。

0.5 は gcs に設定すると設定自体に対してエラーを吐くが、0.3 ではエラーにならない。しかし設定ファイル自体にエラーがなくても実際の動作に対してミスがあった場合、それはどこにも情報としては出てこない。実際の動作を見て、合っているかどうかを確認するしかない。

例えば Cloud Storage の bucket の中に特定の prefix を用意して下に replica を保存することにしているが、実際にはその prefix (ディレクトリに相当)が存在しない場合、replica は作成されず、その失敗の様子を知る手段がない。少なくとも 0.3.13 では存在しないように見える。

  1. ここはちょっと分かりにくいと思うけど、解説記事や、今なら AI の要約ですぐに回答に辿り着けそう。ガイド部分のドキュメントは比較的充実してると思う。) 

  2. おまけに Cloud Storage を操作する標準ツールは gsutil 

More