pelopo

pelopo

Hi, a newbie to web dev and Phoenix & Elixir here.

I need advice on how to conceptually understand the topic of database updates and deployment from dev to prod for a SQLite based Liveview Web App.

I’ve got a python based scheduled data pipeline that scrapes, extract and transforms data from Internet and in the end, it writes it all into a duckdb file based database. After that, it uses a built-in feature called sqlite_scanner that generates a SQLite db from the duckdb file. Depending on the day, the final database is updated once or maximum twice per day.

My dev environment uses this SQLite db as a backend for the app. The reason being is that I want to save costs as much as I can, especially because it is just an initial efforts and prototyping. Besides., I already got a relatively powerful VPS server and I want to reuse it. Also, I don’t expect my app to be used by more than 10,000 people anyway.
My questions are:

1 - how do I deploy to prod to my VPS server in case with a file based database like SQLite?
I have my eyes on piku, but I don’t know how to deal with having a file based database that is about 15Gb and therefore too big for github to handle. I would prefer not to use docker.

2 - How to handle the updates to the database? If my Python data pipeline generates a new SQLite file every day, how can I push it to prod , into the existing and running app without glitches? How do I swap one database file for the newer? I don’t mind the users to experience a 1 second glitch either.

3 - Let’s say my data pipeline got to create a new table in the existing database or a new field in the existing table, how do I deal with that on the Phoenix side, do I somehow run automated migrations or as long as my UI components and the logic are ready to receive new fields on new tables are fine, then I don’t need to do anything else ?

Thanks

Showing Posts 1 to 10

LostKobrakai

LostKobrakai

Does your app only read from the database or does it also do writes?

pelopo

pelopo OP

I expect only a couple of write scenarios.

1 - Generating users and auth. I want to reuse what comes standard with Phoenix Liveview

2 - At some point later, I will probably build and internal bookmarking functionality where the logged users would be able to save certain pages (based on url params) to their list of favourites.

I probably will have to somehow enable the updated and newly generated SQLite DB to respect existing user tables or maybe even use two SQLIte dbs in one app. One for the app itself, which will be mostly tables and charts and the other SQLite db for user management.

garrison

garrison

For your user data, I would caution against using SQLite if you expect thousands of users. SQLite has no write concurrency (at all), and its transactions per second are measured in tens. Which is fine as long as you don’t need many transactions, but just keep in mind it’s not going to scale very far (for writes). If you have a powerful VPS (as you say), consider just running Postgres on the VPS to handle the user data. Then if you ever need to scale in the future you can just get a bigger server.

As for your questions:

If you mean for your user data, check out Litestream and LiteFS (by the same guy, at flyio). They handle backing up/persisting the database to object storage or another server, in slightly different ways. I can vouch for Litestream in particular, very low maintenance (I’ve never had to touch it). Great for personal projects with SQLite.

Well the easiest way might be to run the Python pipeline on the same server, so you already have the file. But if you want or need to use a different machine, you could throw the file into S3 or similar, or rsync/sftp it onto the server. If you were feeling clever you could add an endpoint to your Phoenix server (behind some sort of auth of course) and use that to upload the file over https (I quite like that solution actually).

As far as switching over, I’m not actually sure the best approach there. There’s probably some way to close the existing Repo and re-open it (perhaps someone else can chime in?). You might also be able to engage in some shenanigans with dynamic repos.

Ecto migrations and schemas are separate. If the database is only written by your Python pipeline, as long as the correct schemas are in place in your Elixir app they will just work. If you change the database tables you have to change the Ecto schemas in your code and deploy the changes.

ruslandoga

ruslandoga

:wave:

its transactions per second are measured in tens

Tens of thousands? :slight_smile:

Mix.install([{:xqlite, github: "ruslandoga/xqlite"}])

db = XQLite.open("some-db.sqlite3", [:readwrite, :create])
XQLite.exec(db, "pragma journal_mode=wal")
XQLite.exec(db, "create table records(id integer primary key, age integer not null, name text)")

count = 20_000
records = Enum.map(1..count, fn i -> %{age: i, name: "name-#{i}"} end)

:ets.new(:stmt_cache, [:named_table])

sql = "insert into records(age, name) values(?, ?)"
:ets.insert(:stmt_cache, {sql, XQLite.prepare(db, sql)})

defmodule Bench do
  def insert(%{age: age, name: name}) do
    [{_, stmt}] = :ets.lookup(:stmt_cache, "insert into records(age, name) values(?, ?)")
    :ok = XQLite.bind_integer(stmt, 1, age)
    :ok = XQLite.bind_text(stmt, 2, name)
    XQLite.step(stmt)
  end
end

{ms, :ok} = :timer.tc fn -> Enum.each(records, &Bench.insert/1) end
IO.puts("Inserted #{count} records in #{ms / 1_000_000} seconds")

outputs

Inserted 20000 records in 1.033437 seconds

ruslandoga

ruslandoga

And since it seems like the SQLite databases would be immutable (created by DuckDB), a single readonly connection can be used for multiplexed statements and “unlimited” concurrency. A file watcher can be set up to switch the connection to new database files once they become available.

pelopo

pelopo OP

very nice and way more than I’ll ever need. My writing will only be users registering or changing password. Dozens of transactions per day maximum.

pelopo

pelopo OP

1- What are the multiplexed statements?
2 - Any example of this file watcher or something standard like LItestream/LiteFS should be enough?

pelopo

pelopo OP

@ruslandoga aren’t you the maintainer of a duckdb Elixir version ?GitHub - ruslandoga/duckdb_nifs: DuckDB bindings for Elixir · GitHub

Do you think duckdb could be used as a direct substitute for SQLite?

rhcarvalho

rhcarvalho

Might be worth knowing that recently the SQLite team shipped a new command line tool, sqlite3_rsync, which could solve the problem of updating the file in-place and efficiently.

rhcarvalho

rhcarvalho

I’d also advise using separate Ecto repositories and database files for your user data and this apparently read-only data dump, as it would make your life easier when it comes to database backups and what not.

Where Next? Top

Trending in Questions Top

Blokh
Hey guys, I’ve got a huge CSV ( around 10 GB ) that needs to be processed hourly Do you guys have any suggestions what is the best prac...
New
kszambelanczyk
Hello! Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app. I creat...
New
Onor.io
I have what I’ve heard referred to as a “lookup table” in my database. This is a way of assigning codes to common values. One common lo...
New
Trolleger
What approach to take when sending live updates to “random” users Hi! I have a question, I have a little chat app, and when I create a DM...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
matt-savvy
Anyone here using Honeybadger? My Honeybadger account is being overwhelmed with noise from some bots. Seeing a lot of Bandit.HTTPError...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
wintermeyer
There are three potential reasons for members of this forum to have a look at https://vutuv.de You are tired or annoyed of LinkedIn. Yo...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews