SQLite may become foundational for digital progress
venturebeat.com
venturebeat.com
Don't get me wrong, there are plenty of uses for SQLite, but I think the hype is getting out of hand IMHO.
If you are making an app that only a single person is going to use at a time, then there are plenty of options, including SQLite. Heck, IndexedDB is sufficient. CouchDB tried the whole DB-per-user thing and it didn't end super well.
Happy to be proven wrong though. If anyone has an example of a site with more than say, 10K concurrent writers (edit: changed from users) running on a single SQLite DB I'd probably change my mind.
---
Now, what would be interesting is a way to architect an app such that you can have a central entity, like this site, for instance, but all of your posts are actually referring to your own SQLite, or equivalent store. In that sense you can own your data completely. For performance you can specify a TTL for your data and the consumer (this site) could cache* it accordingly.
Though this would probably end up being a lot less performant than simply using something like Postgres, but at least you'd have more control over your own data.
* - This caching ideally would be enforced by the browser, and not the server, that way the server actually never touches or knows what data you have.
>If many threads and/or processes need to write the database at the same instant (and they cannot queue up and take turns) then it is best to select a database engine that supports that capability, which always means a client/server database engine.
Not a lot of applications have many processes that need to write at the same instant in time and cannot be put in a queue instead.
I remember Richard Hipp mentioning Bloomberg in one of his interviews (don't ask me which one, I don't remember), that they use SQLite to serve billions of bank transaction on a daily basis without a problem.
[1] https://github.com/bloomberg/comdb2
Update: I have found the following paper that describes the engine in greater detail: http://www.vldb.org/pvldb/vol9/p1377-scotti.pdfThat's different than using the DB directly though.
No, not really possible, and attempts to do so would be misguided. But it does not prevent Python from being highly successful in other areas.
Same with SQLite: it's a fine tool for a large spectrum of applications, but high-throughput OLTP is not it; SQLite can't reasonably replace Cassandra or even Postgres.
The point of much of the "SQLite hype" is that there are many applications where read load is high and queries complicated, but the write load is low to non-existent. In situations like these, you can make do with a smaller DB than Postgres.
Sure, but my point is that unless you know for sure your app will stay the same forever, why not just use Postgres or something more flexible to begin with? With things like Supabase, Hasura, and Managed Postgres why even bother with SQLite? Just seems like you're causing your tech team inevitable pain when you have more writes than expected and have to migrate off of it.
Both Fly.io and Cloudflare's solutions are a good example of this. If you're going to use another service, why even bother with SQLite? I totally get the SQLite use case when you're using it directly like with X-Range-Requests (https://phiresky.github.io/blog/2021/hosting-sqlite-database...) or SQLite.js and a WASM app (https://blog.ouseful.info/2022/02/11/sql-databases-in-the-br...), but idk.
tldr: if you're using a service, why bother with one backed by SQLite instead of Postgres? The underlying data store will be abstracted away anyways. One scales decently, and the other, not so much.
Can anyone give further context here? Haven't looked at CouchDB for several years, remember it as being good for certain use cases (intermittently offline devices etc).
So I'm wondering as well who it didn't end too well for.
A common pattern (which I've implemented myself in Datasette) is to put your writes in an in-memory queue and apply them using a single dedicated connection.
We have server app on a single beefy server servicing ~100,000 simultaneous users with avg user action per second of 0.2 (~20k actions per second) requiring some ~60k sqlite writes per second.
A single thread handles that with message passing with little load. We estimate we can handle 5-10 times as much without changing anything. That's with SSD's and standard OS caching. With either an in-memory db or using zstd compressed ramdisks the limits are ridiculous.
Who needs durability anyway, right?
Suitability depends on what the requirements are.
But more seriously if you want the best of both worlds (in-memory speeds and durability) there are NVDIMMs.
SQL Server can take advantage of them: https://docs.microsoft.com/en-us/sql/relational-databases/pe...
I imagine with some effort SQLite could as well.
[1] example: not quite WAL, but disabling full logging, so it was then on simple logging, on MSSQL as part of a log shrink process. On a cient site. Who did 3-hourly log backups.
1 connection per database is critical. WAL is important. Not double-locking helps (most builds of SQLite serialize all writes internally).
You do all of these things correctly at the same time, then you can easily handle tens of thousands of transactions per second.
Additionally, we also do a per session database concept where data is scoped as specifically as possible. Using just 1 sqlite database for the whole application would be a mistake imo.
Synchronous replication is our next step, but we might build something in-house for this.
Even if you are taking advantage of the built in WAL feature?
https://blog.synopse.info/?post/2022/02/15/mORMot-2-ORM-Perf...
If you’re averaging 1000/s and you get 1010 req in one sec, yes this leads to an infinite queue - but your average is now above 1000/s! Then if a few seconds later you get 990 requests, the queue catches up (because your avg is back to 1000)
IOW - it assumes only positive variability and no negative variability which does not mimic real world systems in my experience.
It’s an academic exercise that’s interesting to think about, but has no practical application. Else we would see infinite queue backups every time a system received a burst of traffic beyond their maximum throughput in any given time period.
What am I missing?
You do actually expect the server to eventually recover from all load spikes, but that dead time means cumulatively you'll typically have queued more requests than you've handled at long enough time scales. On average that surplus is infinite, despite it sometimes being as low as 0.
It's not just academic, but it's not surprising that doesn't echo your real-world experience either. We don't usually run systems anywhere near capacity, and even when you do you'll still expect the queue to be able to handle the load eventually.
We got to the canonical "LAMP" stack incrementally, shaped by the computing environment at the time. The servers that you had available to your web app 15 years ago were maybe 2 cores running at 1.5GHz and you had a couple gigs of RAM, and you wrote the app in a very slow dynamic language. So in order to scale out to the Internet, you had to split your application into replicas that ran on different servers; the traffic you were getting and the architecture of your application meant that you needed more than 1 CPU second per second, and that was the only way to get that at the time. All of these replicas needed some coordination, so you had a database server to handle that coordination, and it ran on the biggest computer possible because it was the single point of failure. (And when one computer wasn't big enough, it was time for ugly hacks like sharding.)
Fast forward 15 years and the landscape has changed dramatically. You can get 448vCPU machines from AWS. You're writing your application that is compiled or JIT'd into native code. With the same hardware, your application of today might be 10-100x faster than your application 15 years ago on the same hardware. But the hardware is even faster, and computers are bigger (you can go get a 64 core processor off the shelf at an electronics store!). So one node might now be 1000-10000x more powerful than where this "I must have a hundred replicas of my application" mindset came from.
With that in mind, if you start right now, you can build a web application that scales beyond your wildest dreams with a single computer. If you only have one computer, why not build the database into the application? You will have made so much money by the time the 448 core computer is inadequate for your application that it doesn't even matter. Hire 100 developers to move the thing to FoundationDB or Spanner or Postgres or whatever "real" database you think you need to scale to the next 10 billion users. (Interestingly, the top article on HN right now is "What if it changes?", a sarcastic reminder that maybe today you should build the system you need for today. If it sucks in a year, fix it in a year.)
I am throwing some pretty important things out the window. You probably update your application, so you want some rolling deployment that aborts if the new version fails to start up or whatever. A tornado blowing up your datacenter on your biggest use day of the year would be bad. Your users are all over the world, so you probably want to serve as much content as you can from a computer near them. But honestly, the state of the art for these concepts are pretty new. Globally consistent ("planet scale") transactions are hard, and not that fast. Automated canarying is also not trivial. So you might build a really complicated application to support those needs, and not even achieve them, because nobody has achieved perfection there yet.
Anyway, my controversial opinion is: don't build a distributed system unless you are absolutely sure you must have a distributed system. Every time you split up your state storage, your work as a programmer becomes harder. A single thread; no need for transactions, everything happens in order. A single computer with multiple threads; you'll need some locks, write barriers, or atomic instructions. Multiple computers with multiple threads? Now you're writing a computer science paper. That's a super fun activity, but check that discovering new classes of computer science problems is what your company's business is before you go out of your way to start doing it. You might be able to make a lot of money by being pretty boring. When you're relaxing on your private island, you might find a recreational activity even more fun than finding bugs in distributed transaction protocols. Who knows.
The currently-accepted simplification is to use a single database server to coordinate your stateless application replicas. That doesn't protect you from tornadoes, give users in Antarctica sub-millisecond page loads, or let you upgrade the database without downtime. If you're OK with that, it's totally reasonable to just build the database into your application as SQLite does. It's simpler, and no worse to an outside observer.
(That said, I tend to reach for Postgres first because it has a lot of polish that I don't think SQLite has. But I don't think anyone is unreasonable or stupid for picking SQLite. Especially if the SQLite instance streams its data to S3 and you have point-in-time recovery options for a disaster or bad release. You're going to want those with Postgres too, and they aren't enabled out of the box.)
How is this controversial. This should be mainstream thinking. Solve the problems that you have, when you're having them, instead of spending time preparing for a future that may never come.
I don't think we'd need a UI served by that central server at that point. A sqlite file and some local program that communicates with other (de)centralized hosts for whatever services or data isn't available locally sounds like a neat departure from the approach the Solid project is taking with plug-able data backends.
Instead whatever ecosystem springs up around really making use of sqlite at "the edge" (here I mean individual's computing devices - not what they mostly references to fly.io and cloudflare from TFA) could invert how web apps are delivered and consumed for the 1% of people who care about this kind of thing. By invert I just mean that the user hosts their own frontends and interfaces with DNS named hosts / ports providing functionality, CPU, disk, network a la plan9.
Sqlite is almost never the right solution.
Making the database fast has the advantage of not requiring extra concurrency complications throughout the rest of your application.
When people created desktop apps - they needed a datastore that was simple and reliable to use. SQLite was perfect for this.
Now, no-one is creating desktop apps anymore (everything is a web app), but people still need a simple & reliable datastore. Even though SQLite has historically advertised to not be used for client/server, people are finding that SQLite works great for most web apps as well.
I'm working on a project, for fun not for money, that uses Golang and talks to a SQLite database for things like accounts and user content. So far I really enjoy writing it a lot but I have to admit that it would probably have issues if it scaled to a large number of users.
In fairness to SQLite it was designed in a different era technologically. Maybe there will be a replacement for the web app era if we distill what we like about SQLite
The code is in the public domain. The spec could just say to include SQLite.
IndexedDB implementations all use SQLite under the hood anyway, AFAIK.
Nowadays, if you look up those opportunists on LinkedIn, you can see their NoSQL careers didn't quite go the way they were expecting. Their wrongdoing is a very, very sore point for them, and it's unfortunate the web had to pay for their hubris.
For more details: https://nolanlawson.com/2014/04/26/web-sql-database-in-memor...
Wonder if there's some schadenfreude seeing Firefox fade rapidly into obscurity and SQLite continue to take over the world.
It worked fine as the system was read heavy and write light. SQLite serialises writes so does not perform well with multiple writers, particularly if the write transactions are long running. Reads were blazingly fast as there was no round-trips across the network to a separate database tier. The plan for dealing with performance problems if/when they arrived was to shard the servers into groups of customers.
I moved on and the next developer ripped it out and replaced it with Postgres because it was such an oddball system. I came back six months later to fix the mess as the new developer messed up transactions with the new database code.
Technically using SQLite with replication tacked on works fine. Superficially it is all the same because it is SQL. However the performance characteristics are very different from a conventional Multi Version Concurrency Control databases such as Postgres.
This is where the problem lies with this kind of database - developers seeing SQL and assuming they can develop exactly the same way they would with other SQL databases. That said I love approaches that get away from the database architectures of last century.
Could you please elaborate?
CRUD Database products like Jira, Salesforce, Airtable, Notion, Clickup, Asana, etc. seem like internal line of business services that just need to be thick clients with a distributed database. Most individual businesses/tenants won’t have to deal with more than 100 concurrent writes at a time (if that) so SQLite could definitely handle that.
> Another wrinkle is that it’s not exactly open source. The original developer of SQLite, Dwane Richard Hipp, placed it in the public domain. Generally, this means that there are no legal restrictions on using the code at all, although there are some questions whether every country recognizes this view.
A bigger issue than the license is that it’s not open for contributions. They don’t accept pull requests and the extensive test suite is proprietary.
SQLite is open for contributions, as long as you "submit an affidavit dedicating your contribution into the public domain" (https://www.sqlite.org/copyright.html). It's not "Open-Contribution" in the sense that some npm packages are for example, where if you send any PR, it will most likely be merged and then you get write access to the repository. If you're curious how you can contribute, check out this page: https://system.data.sqlite.org/index.html/doc/trunk/www/cont...
Personally, I prefer projects that are limited in what contributions they accept to the main trunk. Code quality tends to be a lot higher in those. As long as the source is open so I can freely maintain my own patches, I have no qualms with that workflow.
This may be seen as advantageous however.
I do not find this argument very persuasive. Other aspects and of IP law and of licensing related law are different in different countries too.
If I find some software purportedly from a developer in Wheretheheckisthatistan that says it is under some OSI-approved license all that tells me is that the developer (probably) tried to license it under that license. But I have no idea if they actually succeeded in doing so--for instance maybe their employment agreement for their day job says it belongs to the employer and they are in a country where such agreements are enforceable.
I'm curious about the "citizens cannot revoke their human rights and as such cannot put things into public domain" part of your comment. How does putting something into public domain revoke anything regarding your human rights?
Hence you must explicitly licence to allow reuse.
It's why personally if I want something as free as possible I dual licence under Unlicense and MIT with the user able to take whichever suits them best.
Any legal risk, and Hwaci can avoid employing people from problematic jurisdictions (from their POV). I suspect there is a workaround anyway: Hwaci can require any German developers to assign copyright of code to Hwaci, and then Hwaci can put that code into the public domain.
Regardless, Hwaci mention that SQLite is “Open-Source, not Open-Contribution” and also say “the project does not accept patches. If you would like to suggest a change and you include a patch as a proof-of-concept, that would be great. However, please do not be offended if we rewrite your patch from scratch.”.
It doesn't mean they don't accept contributions at all, just that they are strict about who can contribute.
The main problem is that with your contribution you're making them do the work of writing tests for their proprietary 100% branch coverage suite to cover your contribution.
Spelling fixes and such are trivially accepted. Everything else is not.
The public domain thing is a red herring not worthy of the attention it's gotten, but the infeasibility of making contributions is very much worth talking about.
Basically, Richard Hipp is an open source business genius. He made an exceedingly popular open source thing. Then he found a way to make it so no one would bother using any forks. Then he created a consortium that pays for development and upkeep.
The secret to that success is the proprietary test suite and their refusal to accept contributions. Anyone wanting to fork the code base will not be able to recreate that test suite, nor the upkeep, therefore they won't be anywhere near as trusted as the SQLite dev team.
Wut?
Every scripting language includes a SQLite driver.
Python's SQLAlchemy wraps SQLite beautifully. You can develop locally and then deploy to an enterprise server with a simple change of connection string.
I must be missing the speaker's point.
It is possible to build all kinds of cool things on top of SQLite, but most of these articles sound like it is going to replace PostgreSQL or MySQL.
[1] https://github.com/andyhebear/sqlitefs [2] https://github.com/narumatt/sqlitefs [3] https://github.com/jilio/sqlitefs, https://github-com.translate.goog/jilio/sqlitefs?_x_tr_sl=ru...
So for some applications it might be faster to put "files" in a database (where primary keys are hierarchical full paths) as opposed to actually use the filesystem.
With that said, I've found that I'm a bit hesitant to use SQLite for anything interactive for one silly reason:
It's so hard to query precise date ranges in an ergonomic way interactively. There is no timestamp type, and the general advice I've seen is to use Unix Epoch offsets. This works fine except for exploring.
I keep finding myself desiring porting my SQLite's to PostgreSQL for only the comparatively easy ranged data exploration.
select * from table where startDate >= 123 and endDate <= 456;
would solve the problem.
https://www.sqlite.org/draft/gencol.html
Ignore the text column in your application so it won't be computed at runtime, but it will appear when you 'select *' or use a db browser in exploration mode.
Some things got easier to express with SQL after Json_agg in postgres became a thing (now you can do multi-depth relations without blowing up the result table with Cartesian product) but it's still massive pain in the ass and Json agg has performance overhead too.
This is the joy of SQLAlchemy: great features when you want to use them; escape hatches when you don't.
After days of fumbling in the dark you finally isolate the problematic query, post it like "guys I found it," and still nobody speaks up. So you hack the ORM to attach tracebacks as comments to each query, retest everything, and finally git-blame your way to somebody who owns that bit of code and they're always like "wait, the ORM did WHAT?"
I'd rather grep code for SQL any day.
I’m yet to find a better way to write crud apps than that pattern.
Granted I'm the author, but until I get around to rewriting it from the ground up, I really think it saves a lot of time for editing single cells, querying, and viewing in a headless environment.
It's key/value.