SQLite is the favorite tool of indie developers. It is extremely fast, uses no extra background processes, and stores everything in a single file on disk. But hosting SQLite has a major problem: if your server crashes or your container restarts, you lose your data. Cloud hosts run ephemeral disks, meaning your database file disappears on every deploy.

In this guide, we will solve this problem using **Litestream**. We will deploy SQLite on free server layers (like Fly.io or Koyeb) and stream database changes in real-time to free cloud storage buckets (like Cloudflare R2 or Backblaze B2), keeping hosting costs at exactly $0.

The Litestream Architecture

Litestream is an open-source tool that runs alongside your main application. It watches your SQLite database file for changes. Every time your application writes data, Litestream intercepts the write-ahead log (WAL) and streams those changes to an object storage bucket immediately.

If your server restarts, Litestream downloads the latest backup from the bucket automatically before starting your app, ensuring zero data loss.

Step 1: Setting Up the Cloud Storage Bucket

First, sign up for a free object storage tier (such as Cloudflare R2, which offers 10GB of storage for free). Create a new bucket named my-sqlite-backups and generate API Access Keys (Access Key ID and Secret Access Key).

Step 2: Configuration (litestream.yml)

We write a simple YAML file to direct Litestream on which database to watch and where to stream the backups:

# litestream.yml
dbs:
  - path: /data/db.sqlite
    replicas:
      - type: s3
        name: cloudflare_r2
        bucket: my-sqlite-backups
        endpoint: https://<your-account-id>.r2.cloudflarestorage.com
        access-key-id: ${LITESTREAM_ACCESS_KEY_ID}
        secret-access-key: ${LITESTREAM_SECRET_ACCESS_KEY}

Step 3: Dockerizing the Setup

To run Litestream alongside your main backend application (e.g. a Go, Python, or Node app), use a multi-stage Docker build. This installs Litestream, restores the database on boot, and runs both processes:

# Dockerfile
FROM alpine:3.18

# Install litestream
ADD https://github.com/benbjohnson/litestream/releases/download/v0.3.13/litestream-v0.3.13-linux-amd64.tar.gz /tmp/litestream.tar.gz
RUN tar -C /usr/local/bin -xzf /tmp/litestream.tar.gz

WORKDIR /app
COPY . .

# Copy configuration
COPY litestream.yml /etc/litestream.yml

# Environment variable keys
ENV LITESTREAM_ACCESS_KEY_ID=""
ENV LITESTREAM_SECRET_ACCESS_KEY=""

# Start script
RUN echo '#!/bin/sh \n\
# Restore database from replica if exists \n\
litestream restore -if-db-not-exists -if-replica-exists /data/db.sqlite \n\
# Run litestream sidecar alongside app \n\
exec litestream replicate -exec "node index.js"' > /app/start.sh
RUN chmod +x /app/start.sh

CMD ["/app/start.sh"]

Why This Setup Wins

  • High Speed: Reads and writes run locally at disk speed (usually <1ms).
  • Robust Backups: Litestream writes incrementally every second, preventing major data loss during crashes.
  • Zero Cost: Koyeb, Fly.io, and Cloudflare R2 all offer free tiers that cover this setup completely.

By decoupling replication from the database itself, you can write apps using SQLite and scale them on modern serverless hosts without ever paying for expensive hosted SQL instances.