Is LiteFS a direct replacement for multiple volumes

Hi,

I’m currently hosting my Shopify remix app on fly.io and looking at some hosting solutions for my database. By default this is a sqllite DB and works quite well since I only have 1 table and very little read/write.

To prevent downtime I have 1 app with 2 machines and have also set up 2 volumes for my SQLLite.

So now I have persistent data but as I understand I can have some issues because the data can get out of sync between the 2 volumes.

I.e.
Machine 1 with Volume 1 inserts record ABC into row 1

I run a deploy

Machine 2 comes up with Volume 2, while it has a valid running SQLLite it does not have row 1 from above.

Before I can into other options, is the above assumption correct? Is there anyway to keep the above simple approach working without turning into alternative?

While looking at alternatives I am seeing LiteFS come up quite a bit. Is this the answer for above if I want to stay with a sqllite world?

I am a bit unsure from reading the LiteFS how it works with volumes or if it needs them at all?

Assuming my setup of 1 app with 2 machines what would the normal setup be that both machines have access to the same data and its persistent?

Am I still creating 2 volumes with LiteFS on it, and they somehow keep the data replicated?

1 Like
  1. Sqlite will be mounted on a volume on a machine. Otherwise, the disk is not persistent, which is not really great for databases.
  2. Litefs will replicate from one volume to another (or multiple volumes).
  3. Litefs has a proxy that allows writes to go to the master.

Still bit confused I will try and write clearer questions.

  1. So if I go for LiteFS do I still need to have the same set up of 2 machines and 2 volumes? If a write happens on one machine it will auto add that the other volume? So sqlite file on both volumes stay in sync?

  2. In the above setup is there a way to keep the LiteFS set up super simple since I will only always have 1 machine and 1 volume up and running and it will only switch to the second machine during a deploy? I.e. Seeing a lot of complexity in blog posts about replica nodes and a leader node etc.

Basically I am just trying to see what the easiest way to migrate from a machine + volume using normal sqlite to litefs is.

If you have 2 machines then one will be the primary and changes will be shipped to the other one. There will be some small delay—typically on the order of a few milliseconds—but it could be longer if the two machines are physically far away.

The typical setup is to run 2 machines in a region where either one could become primary and then run other machines around the world for fast regional reads. We haven’t put work into a single-node deployment where it could switch over on deploy. Something like that could be possible but there’s probably some footguns in there.

Thanks for replies!

So just to confirm, for my set up which is:

  • I’m happy with for my app to just be deployed in one region
  • In that region I have 2 machine and a volume each (so 2 volumes)
  • Very happy with SQLLite
  1. If I want my data to be in sync across both volumes (because my machines will switch during a deploy) I need to switch to LiteFS.

  2. My LiteFS setup can stay the same 2 machines and 2 volumes for the one region. What would be easiest way to allow the new machine + volume combo to be allowed to write automatically. Is this where the litefs proxy comes into play? Basically I am hoping for a simple setup like above I need to manage who can write and who can read this there will only be 1 active machine + volume at anytime if that makes sense? I just need to the 2 volumes to stay in sync

Yes.

Probably best to have two regions, but yes.

Yes, this is where litefs proxy comes in. Wherever a write comes in, the proxy forwards to the active / primary litefs. See the documentation here:

Update on this I tried to set it up today and although no errors on deploy it seems be behaving just like a normal SQLLite volume and don’t believe its replicating across all volumes.

Some questions I have.

  1. I have created a litefs.yml as the docs suggest in the speed run (Speedrun: Add LiteFS to your app · Fly Docs) but I am unclear if I need to add this file to my docker file as well. The docs just mention the creation of the file but not if it needs to be added to the docker file as I see some other people have done.

Here is my current docker file

FROM node:18-alpine

EXPOSE 3000

WORKDIR /app
COPY . .

ENV NODE_ENV=production

RUN npm install --omit=dev
# Remove CLI packages since we don't need them in production by default.
# Remove this line if you want to run CLI commands in your container.
RUN npm remove @shopify/app @shopify/cli
RUN npm run build

# for alpine-based images
RUN apk add ca-certificates fuse3 sqlite
COPY --from=flyio/litefs:0.5 /usr/local/bin/litefs /usr/local/bin/litefs
ENTRYPOINT litefs mount

Does the above need a line to copy my litefs.yml on the machine? If so how does this current not complain…

  1. I want to make sure all my paths are correct and if I am reading / writing in the correct folder

In my fly toml

[env]
  DATABASE_URL = 'file:/litefs/sqlite.db'

[mounts]
  source = 'litefs'
  destination = '/data'

in my litefs.yml

fuse:
  dir: "/litefs"

data:
  dir: "/data"

proxy:
  addr: ":8080"
  target: "localhost:8081"
  db: "sqlite.db"
  passthrough: 
    - "*.ico"
    - "*.png"

and my lease code

lease:
  type: "consul"
  advertise-url: "http://${HOSTNAME}.vm.${FLY_APP_NAME}.internal:20202"
  candidate: ${FLY_REGION == PRIMARY_REGION}
  promote: true

  consul:
    url: "${FLY_CONSUL_URL}"
    key: "litefs/${FLY_APP_NAME}"

Also some of the logs if that helps

2024-05-02 16:44:25.000	
waiting for signal or subprocess to exit


2024-05-02 16:44:25.000	
level=INFO msg="starting background subprocess: npm [run docker-start]"
2024-05-02 16:44:25.000	
level=INFO msg="proxy server listening on: http://localhost:8080"
2024-05-02 16:44:25.000	
level=INFO msg="node is already primary, skipping promotion"
2024-05-02 16:44:25.000	
level=INFO msg="node is a candidate, automatically promoting to primary"
2024-05-02 16:44:25.000	
level=INFO msg="connected to cluster, ready"
2024-05-02 16:44:25.000	
level=INFO msg="633AAA8F0808ED94: primary lease acquired, advertising as http://683d47dc546e78.vm.{appname}.internal:20202"
2024-05-02 16:44:25.000	
level=INFO msg="waiting to connect to cluster"
2024-05-02 16:44:25.000	
level=INFO msg="http server listening on: http://localhost:20202"
2024-05-02 16:44:25.000	
level=INFO msg="LiteFS mounted to: /litefs"
2024-05-02 16:44:25.000	
level=INFO msg="using existing cluster id: \"someid\""
2024-05-02 16:44:25.000	
level=INFO msg="wal-sync: no wal file exists on \"sqlite.db\", skipping sync with ltx"
2024-05-02 16:44:25.000	
level=INFO msg="initializing consul: key=litefs/{appname} url=...checkout.internal:20202"
2024-05-02 16:44:25.000	
level=INFO msg="Using Consul to determine primary"
2024-05-02 16:44:25.000	
LiteFS v0.5.11, commit=63eab529dc3353e8d159e097ffc4caa7badb8cb3
2024-05-02 16:44:25.000	
config file read from /app/litefs.yml
2024-05-02 16:44:25.000	
level=INFO msg="no backup client configured, skipping"
2024-05-02 16:44:25.000	
level=INFO msg="host environment detected" type=fly.io
2024-05-02 16:44:25.000	
Machine created and started in 2.557s
2024-05-02 16:44:25.000	
2024/05/02 15:44:25 INFO SSH listening listen_address=dns_server=[fdaa::3]:53
2024-05-02 16:44:25.000	
 INFO [fly api proxy] listening at /.fly/api
2024-05-02 16:44:25.000	
 INFO Preparing to run: `/bin/sh -c litefs mount` as root
2024-05-02 16:44:25.000	
 INFO Resized /data to 1056964608 bytes
2024-05-02 16:44:25.000	
 INFO Mounting /dev/vdb at /data w/ uid: 0, gid: 0 and chmod 0755
2024-05-02 16:44:25.000	
 INFO Starting init (commit: c1e2693b)...
2024-05-02 16:44:24.000	
[    0.046721] PCI: Fatal: No config space access function found

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.