top | item 45333190

What if we treated Postgres like SQLite?

75 points| markusw | 5 months ago |maragu.dev

81 comments

order
[+] eirikbakke|5 months ago|reply
The PostgreSQL data directory format is not very stable or portable. You can't just ZIP it up and move it to a different machine, unless the new machine has the same architecture and "sufficiently" similar PostgreSQL binaries.

In theory the data directory works with any PostgreSQL binaries from the same major version of PostgreSQL, but I have seen cases where this fails e.g. because the binaries were from the same major version but compiled with different build options.

[+] OutOfHere|5 months ago|reply
I would never ever zip up a PostgreSQL data directory and expect it to restore elsewhere. I would use a proper export. If the export is too slow, it could help to use streaming replication to write intermediate files which can be moved to a backup location.

Even with SQLite, for a simple file copy to work reliably, one has to set these three:

  "_pragma=synchronous(FULL)",
  "_pragma=checkpoint_fullfsync(ON)",
  "_pragma=fullfsync(ON)",
[+] tracker1|5 months ago|reply
Yeah, I was going to mention, just upgrading between PG versions can be a bit of a pain. Dump/Restore really seems like a less than stellar option of you have a LOT of data. I mean you can stream through gzip/bzip to save space but still.

I often wish that Firebird had a license that people found friendlier to use as it always felt like a perfect technical option for many use cases from embedded to a standalone server. PG has clearly eclipsed it at this point though.

[+] markusw|5 months ago|reply
Yeah, that really is a great thing about SQLite.

I wonder whether packaging everything in Docker (including a specific Postgres container identified by hash or whatever) and deploying on the same architecture would solve this?

[+] oulipo2|5 months ago|reply
So the alternative would be to just pg_dump / pg_restore the content? Is it an issue?
[+] freedomben|5 months ago|reply
I've been hit by this too, so definitely a risk. I've also had permissions on the files get broken which is a bitch to debug
[+] mutagen|5 months ago|reply
Some apps do, the most used I know of is Blackmagic's Davinci Resolve, the video editor with a relatively full featured free edition available. I think this has more to do with its roots being in a high end networked environment but still, the local desktop version installs Postgres.
[+] markusw|5 months ago|reply
Oh, interesting! But that's more of a desktop application now, right? I was thinking of web servers when writing the article, but I can see how that's not totally clear. :-)
[+] emschwartz|5 months ago|reply
I think this is a neat direction to explore. I've wondered in the past whether you could use https://pglite.dev/ as if it were SQLite.
[+] tensor|5 months ago|reply
Someone is working on a libpglite based around pglite. I think this is what will provide an actual sqlite alternative:

https://github.com/electric-sql/pglite-bindings

It would still be missing the standardized disk format aspect of sqlite, but otherwise will be neat.

[+] thruflo|5 months ago|reply
This is very much the point of https://pglite.dev

It's an embeddable Postgres you can run in process as a local client DB, just like SQLite but it's actually Postgres.

[+] markusw|5 months ago|reply
Interesting! I'm going to look into that. :-) Thank you for sharing.
[+] bob1029|5 months ago|reply
I think this is a great idea for testing. MSSQL has LocalDB which is used a lot throughout the .NET ecosystem:

https://learn.microsoft.com/en-us/sql/database-engine/config...

For heavy duty production use (i.e., pushing the actual HW limits), I would feel more comfortable with the SQLite vertical. Unix sockets are fast, but you are still going across process boundaries. All of SQLite can be ran on the same thread as the rest of the application. This can dramatically reduce consumption of memory bandwidth, etc.

[+] bluGill|5 months ago|reply
Memory bandwidth I don't worry about much - most of the time you should settup a small database with just enough data for that test, which hopefully is fast. However sockets and processes are a worry as starting as there are places things can go wrong not related to your test and then you have flakely tests nobody trusts.
[+] markusw|5 months ago|reply
I am so tempted to benchmark some more… :D Would be great to get some numbers on this, super interesting.
[+] srameshc|5 months ago|reply
When I want to treat my Postgres like SQLite , I use DuckDB using PostgreSQL Extension https://duckdb.org/docs/stable/core_extensions/postgres.html and this is one of may extensions, there is more and I love DuckDB for that
[+] markusw|5 months ago|reply
While I really like DuckDB, I wouldn't use it for OLTP workloads.

I'm curious, when do you want to treat your Postgres like SQLite? :-) That's basically the opposite of what I was thinking of in the article.

[+] oulipo2|5 months ago|reply
In what kind of scenarios are you using Duckdb from postgres? And does it improve over, say, having a Clickhouse instance nearby?
[+] kissgyorgy|5 months ago|reply
The huge advantage of SQLite is not that it's on the same machine, but it's that is it in process which makes deployment and everything else just simpler.
[+] markusw|5 months ago|reply
Yeah, totally agreed. An embedded Postgres would be sweet (see pglite elsewhere here in the comments, looks interesting).
[+] kketch|5 months ago|reply
I've been using postgres as a local database for one of my personal projects, a GUI app or to run python tests that depend on it without having to rely on installing it in my environment.

I created a Python package that downloads an embedded Postgres binary, sets up the database, and gives you a database URL: https://github.com/kketch/tinypg

It downloads pg binaries from this project: https://github.com/zonkyio/embedded-postgres-binaries. There are other similar projects listed on that page that provide this for Java, Go, Rust and Node

[+] kketch|5 months ago|reply
When not using python, been using this script to create ephemeral postgres databases for tests but also persistent one in my dev containers: https://github.com/eradman/ephemeralpg

I've wrapped it with yet another shell script to make it usable just like this:

`export DB_URL=$(./pgtest.sh)`

This version (pgtest.sh), just creates a disposable ephemeral postgres: https://gist.github.com/kketch/d4e19a7fb6ebc1cfc265af44c1b41...

This version (pgdev.sh), starts a postgres instance (if not already running) and persists the DB. Also supports seeding it with a SQL script (dev_seed.sql): https://gist.github.com/kketch/88bb5b766994e247a9f2c37f13306...

[+] nu11ptr|5 months ago|reply
You can, just embed it in your Go app:

https://github.com/fergusstrange/embedded-postgres

[+] OutOfHere|5 months ago|reply
Does this use an external binary or CGO or Wazero (Wasm) or is it rewritten in Go?

With SQLite, although all approaches are available, my fav is to use https://github.com/ncruces/go-sqlite3 which uses Wazero.

I try to avoid CGO if I can because it adds compile-time complexity, making it unfriendly for a user to compile.

[+] tptacek|5 months ago|reply
This just runs Postgres as a process, right?
[+] 8organicbits|5 months ago|reply
I do this using the Docker approach, especially for low scale web apps that run on a single VM. I like that its full Postgres versus the sometimes odd limits of SQLite. My usual approach uses a Trafik container for SSL, Django+gunicorn web app, and Postgres container; all running as containers one VM. Postgres uses a volume, which I back up regularly. For testing I use `eatmydata` which turns off sync, and speeds up test cycles by a couple percent.

I haven't tried the unix socket approach, I suppose I should try, but it's plenty performant as is. One project I built using this model hit the HN front page. Importantly, the "marketing page" was static content on a CDN, so the web app only saw users who signed up.

[+] markusw|5 months ago|reply
Yeah, basically the same here, except it's Caddy in front instead of Traefik.

So you do periodic backups, not incremental on every write or something (read replica-like)?

It's important to me to not lose any data once committed if at all possible.

(For testing, I've sped everything up by running migrations on `template1` and every test gets a random database name. Works wonders.)

[+] whartung|5 months ago|reply
I don’t recall the mechanics but I do know that folks have bundled starting a local instance of PG solely for unit tests.

There’s a pre-install step to get PG on the machine, but once there, the testing framework stands it up, and shuts it down. As I recall it was pretty fast.

[+] majewsky|5 months ago|reply
This is my version of it: https://pkg.go.dev/github.com/sapcc/go-bits/easypg#WithTestD...

The most annoying part of it is that Postgres absolutely detests running as PID 0, which makes running `make check` in Docker containers an unnecessarily frustrating experience. I understand why Postgres rejects PID 0 by default, but I would really like for them to recognize strcmp(getenv("I_AM_IN_DOCKER_AND_I_DONT_CARE"), "true") or something.

[+] nullzzz|5 months ago|reply
This is IMO best done running pg in a container using docker-compose or similar
[+] OutOfHere|5 months ago|reply
SQLite is used more in resource-constrained environments. If I had much memory to waste, I would've used a local PostgreSQL installation to begin with.

Note that advanced vector-embedding querying techniques for approximate nearest neighbor search inevitably always need an absurd amount of memory, so it typically doesn't make sense to use them in a resource-constrained environment to begin with.

[+] yndoendo|5 months ago|reply
I have used SQLite with embedded 2MB flash and 8MB RAM. The microSD card was used as swap for producing reports and serving them over HTTP.

Next embedded model version moved to 8MB flash and 64MB RAM with the same software infrastructure.

[+] munchlax|5 months ago|reply
From what I've read about it, DuckDB comes close. Regular files, like sqlite, but pg functionality.
[+] OutOfHere|5 months ago|reply
If I am not mistaken, DuckDB is suitable for columnar analytics queries, less so for multi-column row extractions. Which PG-like functionality does it offer on top?
[+] nullzzz|5 months ago|reply
No it’s not ”pg functionality”. It’s close to SQL standard compliance but not close to what Postgres has to offer. Also, single transaction writing at a time, in-process etc.
[+] JodieBenitez|5 months ago|reply
> You can just install Postgres on your single big and beefy application server (because there’s just the one when you use SQLite, scaled vertically), and run your application right next to it.

Am I getting old ? Seems obvious to me.

[+] BiteCode_dev|5 months ago|reply
Yes, you are old.

I meet an unexpected number of young devs that:

- Find hypermedia to be exotic. JSON web API is the only way that makes sense to them.

- Say they use the cloud to "save money".

- Use third-party services for things as basic as authentication because "it's hard".

- Encode security stuff in the frontend code.

It's the cycle of life.

[+] omarqureshi|5 months ago|reply
Literally prior to the cloud being a thing, for medium sized web apps, this was the way.
[+] markusw|5 months ago|reply
Hehe. Yes and no.

In the cloud, as you probably know, the usual way now is to spin up Postgres separately (RDS, Supabase, Planetscale, Crunchy Bridge, you name it). We've gotten so used to it that a different way of doing it is often not even considered.

But I think tooling has come a long way, and there have been a lot of learnings from the cloud, so it's time to swing the pendulum back and reconsider assumptions!

[+] tptacek|5 months ago|reply
You'd still be incurring client/server IPC for individual database queries, which would cost you one of the benefits of using SQLite (IDGAF-queries that just hammer tables repeatedly because there's almost no cost to doing so).
[+] nullzzz|5 months ago|reply
TLDR: a dude ponders if postgres could be used instead of sqlite. Close to zero useful information, no learnings from serious production use.
[+] apalmer|5 months ago|reply
I upvoted this, because while it was critical it didn't feel meanspirited and it was factually correct.

After fully reading the article I came to understand it really was not referring to anything sqllite specific, was really 'what if you ran postgres as an application on a server', there really is nothing more to be gained from reading the article beyond this, and this is kind of the most basic deployment model for postgres for like the last 40 years.

[+] markusw|5 months ago|reply
Indeed pondering! The dude here. I think writing a little piece like that often sparks some interesting discussions here and elsewhere. :-)