SQLite-based databases on the Postgres protocol? Yes we can
blog.turso.tech
blog.turso.tech
It seems like this project removes that benefit, so what is it solving for or adding instead? What's the upside?
I believe FirebirdSQL has done this for a while - you can either link the whole database library to your code, or with the same API, link a client library that talks to a remote database over the network.
It's a great idea because you can link to the embedded version for development and unit testing, but upgrade to a full networked DB server for the live deployment.
The main idea was that I could use Sqlite as a nicer/easier to query JSON with almost no upfront infra for a relatively simple project (https://lemonade.sonnet.io). It worked quite well! But then I had some issues with accessing fs (it _is_ officially supported for reads). I could read the file from one route, but accessing it from another would result in a file not found error...
I pivoted when I managed to get it working... by renaming the db file to db.png and getting its path via `import` in Next. I know there's a simpler way to to that.
Remix is worth a close look; if you accept up front that a js server runtime is required, it's fantastic. Or, there's Vite, which (with vite-plugin-ssr) covers most Next.js use cases with fewer opinions and less framework magic.
For most of my small/medium projects now I use SvelteKit. I used to think it was a bit too magical because of the new syntax, but I tend to write more vanilla JS/TS with it than I expected. Productivity- and dev experience wise it's quite impressive. My workflow is prototyping/spikes, many wip commits then -> rewrite/sometimes TDD for critical parts.
( More info here: https://sonnet.io/posts/wip/ and https://sonnet.io/posts/code-sober-debug-drunk/ )
For large apps I'd still stick with Next, although the refresh times in dev mode are a bit annoying and I don't share th3o's optimism re Vercel having so much control over React.
And I think there are other approaches to replication that still retain the embedded aspect; litefs, litestream.
I guess I'm thinking, if it looks like postgres, and it speaks postgres (wire protocol) and it has features or replication like postgres, why wouldn't you use postgres?
Because postgres is not single file?
Most (all?) of the well-known RDBMS are designed to host the data needs of multiple separate applications, which makes configuration look a lot more complicated when all you want is n=1.
It seems like the inflection point moving from "single-local-application" to "writing-to-remote-db" would be an appropriate point to switch from a single file DB to a larger RDBMS.
I can think of a few scenarios where it could make sense, like a shared small DB on a LAN that doesn't need a full fledged "server", but a primary/secondary relationship makes sense. But those are pretty few... and n>1.
Obviously someone wrote this because they felt a need for it, but I'm struggling to see the use-case. Maybe it's good for CI/or unit testing?
Not really, with this solution now you need to manage a non-replicated, non-high-availability mock of Postgres where every user is 'postgres', dealing with the usual remote RPC call issues and latency.
If you need to manage a RDBMS anyways, you probably can manage Postgres; if you can't manage Postgres then it's unlikely that you will be able to manage this solution as well.
I found that there are just so many differences that supporting both leads to having multiple codepaths. Some examples:
- only postgres supports `with conn.cursor as cur`, need `cur.close()` or commit or similar with SQLite
- Escaping things for columns and table names: postgres has psycopg2.sql.SQL.format() that only works with postgres connections.
As my least favorite example, DB-API has two transaction modes, both of which are unnecessarily error prone: autocommit on, and autocommit off. Autocommit on makes transactions useless (intentionally), but it still allows commit() and rollback(), so one can write code that thinks transactions are enabled, have it appear to work, and end up with all manner of corruption.
Autocommit off has a bad interface. The begin() function is entirely missing, so you can’t pass it arguments. Worse, since there is no explicit start of a transaction, the library can’t catch misuse of a transaction.
As a result, every SQL library for Python of any reasonable quality implements its own special API, and nothing is particularly interoperable.
This is all sort of fine if the database is only accessed through a higher level library like SQLAlchemy. But sometimes a developer just wants to execute raw SQL against a database, and the situation in Python is not very nice.
I think the real problem is that DB-API exists and is bad — its existence comes with the automatic imprimatur of being an official standard and this seeming desirable to use.
(PostgreSQL experts: Is there a magic way to sync schema changes and data from a local instance to a production server?)
They're just adding more complexity to a well established project. NIH syndrome to me.
NIH syndrome.
I wrote a small PHP library that gives you a key-value storage interface to SQlite files: https://github.com/aaviator42/StorX
I've been dogfooding for a while by using it in my side projects, and it holds up very well (mostly thanks SQLite's robustness!).
And there's a basic API too, to use it over a network: https://github.com/aaviator42/StorX-API
For instance - I would love to be able to use https://github.com/porsager/postgres with sqlite.