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

katta
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
achenet
Hello, I’m trying to build a basic Phoenix web-app, and I’d like to use Tailwind. However, when I launch mix phx.server, I get an error...
New
kpanic
Hi everyone, I am toying with the idea of building a “match maker” for giving personal help to people that wants to start coding. I sta...
New
asweet-confluent
I recently noticed that Elixir’s Logger defaults its primary log level to :debug when no :logger, :level application configuration is pre...
New
Cxx-mlr
I’m working on a small exercise involving update_in/3, and I came up with this solution: data = %{ name: "Periodic Table", category:...
New
ChrisAmelia
I’ve got trouble wrapping my head around the order in which functions are called in this snippet (from Phoenix’s authentication): toke...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
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
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews