How to use Litestream with SQLite & Prisma
Originally posted on: arnavgosain.com/sqlite-prisma-litestream
One of my side projects is Rune, an alternative email client built for reading and annotating newsletter content.
Rune is built with Remix[1] and uses Prisma[2] as the ORM layer. Prisma supports quite a few databases, of which I prefer Postgres. But I wanted to keep things simple, and didn't want to set up a full-blown Postgres instance, so I decided to use SQLite.
Since since my preferred way to deploy is via Docker on Railway.app, I needed a way to persist SQLite since Docker containers are refreshed on every deployment. Litestream[3] was the perfect tool for the job.
But since Litestream only works with SQLite's WAL journaling mode[4], it needs to be enabled on the SQLite database before running the Remix app.
enable-wal.js
const { PrismaClient } = require("@prisma/client");
let client = new PrismaClient();
client.$queryRaw`PRAGMA journal_mode = WAL;`
.then(() => {
console.log("ENABLED WAL MODE FOR DATABASE");
})
.catch((err) => {
console.log("DB SETUP FAILED", err);
process.exit(1);
});
run.sh
#!/bin/bash
set -ex
## Restores the database from S3
litestream restore -v -config /etc/litestream.yml -if-replica-exists -o /data/db /data/db
## Runs migrations on the restored database
npx prisma migrate deploy
## Enables WAL Mode
node ./scripts/enable-wal.js
npx concurrently "litestream replicate -config /etc/litestream.yml" "npm run start"
Dockerfile
CMD ["bash", "./scripts/run.sh"]
Explanation
- Dockerfile runs the
run.sh
script. - The script first restores the latest snapshot of the database from S3 using Litestream.
- It runs
npx prisma migrate deploy
to deploy any pending migrations. - Then,
enable-wal.js
is run to enable WAL journaling mode using PrismaClient's$queryRaw
- Finally, the Remix app & Litestream are started concurrently using the
concurrently
[5] CLI tool.
Footnotes
1: remix.run 2: prisma.io 3: litestream.io 4: sqlite.org/wal.html 5: npmjs.com/package/concurrently