The SQLite database: a complete overview, pros, cons and limits
What SQLite is used for, whether it is good for a website and where a server database wins: WAL mode, pros and cons, a comparison with PostgreSQL and MySQL, tools, SQL examples, limits and tips.
In short
SQLite is a database in a single file: a small library inside the application, with no server, no users and no setup. By its authors’ estimate it is the most widely deployed database in the world — it lives in every phone, every browser and countless programs. For a website it is a serious option: with WAL mode many readers work in parallel with a writer, transactions are fully reliable, and there is full-text search, JSON, RETURNING and strict tables. Its limit is one writer at a time and one machine: for a busy shop with many simultaneous orders or several app servers, take PostgreSQL or MySQL.
SQLite at a glance
The main facts in one table — what SQLite is, how it stores data and where it lives.
- Type
- An embedded relational database: a library, not a server
- History
- D. Richard Hipp, 2000; the file format of version 3 is stable since 2004
- License
- Public domain — no licence at all
- Storage
- The whole database is one file that can be copied like any other
- Transactions
- ACID; in WAL mode readers do not block the writer
- Writes
- One writer at a time; the rest wait their turn
- SQL
- Window functions, CTEs, upsert,
RETURNING, generated columns,STRICTtables - Built in
- JSON functions, FTS5 full-text search, R*Tree for coordinates
- Limits
- Up to 281 TB per file in theory; in practice — one machine
- Where it lives
- Android and iOS, every major browser, desktop programs, devices
- In languages
- Built into PHP, Python and Node.js (
node:sqlite); drivers for the rest
What SQLite is used for: 8 areas
From phones to production websites. Under each area — the tools it usually comes with.
-
01
Sites and blogs
Content, forms and an admin panel: most sites write rarely and read a lot — SQLite’s strong case.
-
02
Small services and internal tools
One server, one file, nothing extra to administer.
-
03
Mobile apps
The default local database on Android and iOS.
-
04
Desktop programs
Settings, history and documents of applications are often stored in SQLite.
-
05
Browser extensions
SQLite compiled to WebAssembly keeps data right in the browser.
-
06
Data analysis
Load a CSV and query it with SQL in seconds, without a server.
-
07
Tests and prototypes
A database in memory is created for each test and disappears after it.
-
08
Distributed SQLite
Copies near the user and replication to storage — through separate projects.
Pros and cons of SQLite
SQLite trades a server for simplicity. What you gain and what you give up both come from that.
Pros · 8
-
Nothing to administer
No server, users, ports or passwords — the database starts with the application.
-
Very fast reads
No network between the code and the data: a query is a function call.
-
A backup is a copy of a file
The whole database moves and backs up as one file.
-
Reliable
Full transactions; the code is tested more thoroughly than almost any software.
-
Modern SQL
Window functions, upsert,
RETURNING, JSON and strict tables. -
Search out of the box
FTS5 gives full-text search with ranking without a separate engine.
-
Free forever
Public domain and a file format the authors promise to support until 2050.
-
Cheaper hosting
No separate database server — one machine is enough for the whole project.
Cons · 8
-
One writer at a time
Many simultaneous writes queue up — busy shops and services feel it.
-
One machine
Several app servers cannot share one file safely over a network drive.
-
No users and rights
Access is decided by file permissions, not by database accounts.
-
Lax types by default
Without
STRICTa text can quietly end up in a number column. -
Limited ALTER TABLE
Some schema changes mean rebuilding the table by hand.
-
No built-in replication
Copies and failover come from separate tools like Litestream.
-
Search without morphology
FTS5 does not know word forms out of the box; prefix queries help.
-
File permissions matter
In WAL mode even reading needs write access to the
-waland-shmfiles next to the database.
SQLite compared with PostgreSQL and MySQL
A file versus a server — the comparison is about the model, not about benchmarks.
| Criterion | SQLite | PostgreSQL | MySQL |
|---|---|---|---|
| Model | a library and a file | a server | a server |
| Setup | none | yes, plus a pooler | yes |
| Simultaneous writes | one at a time | many | many |
| Several app servers | no | yes | yes |
| Read speed on one machine | very high, no network | high | high |
| Users and rights | file permissions | roles and rights | users and rights |
| Replication | external tools | built in | built in |
| Best for | sites, small services, apps | services with complex data | CMS and web apps |
When to choose SQLite — and when not to
Twelve typical tasks with a verdict. Where SQLite is not the best choice, the alternative is named.
-
Corporate site or blog
Best fitFew writes, many reads — exactly SQLite’s case.
-
Landing page with a form
Best fitA server database would be overkill.
-
Internal tool for a team
Best fitOne server, one file, nothing to administer.
-
Mobile or desktop app
Best fitThe standard local database.
-
Tests and prototypes
Best fitA fresh database in memory for each run.
-
Catalogue of a few thousand items
Best fitReads and search work well; imports go in one transaction.
-
Small online shop
WorksFine at a modest number of orders; plan the move when it grows.
-
SaaS at the start
WorksPossible on one server with WAL; PostgreSQL is safer for growth.
-
Busy shop with many orders at once
Pick anotherPostgreSQL or MySQL: many writers at a time.
-
Several app servers
Pick anotherA server database they all connect to.
-
Strict access rights for many users
Pick anotherPostgreSQL with roles.
-
Geodata and vector search at scale
Pick anotherPostgreSQL with PostGIS and pgvector.
The SQLite ecosystem: tools for common tasks
The middle column is what comes with SQLite itself.
| Task | Built in | Tools |
|---|---|---|
| Command line | sqlite3 | — |
| Backups | VACUUM INTO, .backup | Litestream |
| Replication | — | Litestream, LiteFS, Turso |
| Full-text search | FTS5 | — |
| JSON | json_*, ->> | — |
| Vectors | — | sqlite-vec |
| In the browser | — | sqlite-wasm |
| Viewing data | — | DB Browser for SQLite, Datasette, DBeaver |
| In PHP | PDO_SQLITE, SQLite3 | — |
| In Node.js | node:sqlite | better-sqlite3 |
The limits of SQLite and common mistakes
-
The default journal mode
Without WAL a write blocks readers. For a site, turn WAL on once — it is stored in the file.
-
“database is locked” without a timeout
Without
busy_timeouta request that meets a busy file fails at once instead of waiting a moment. -
Wrong owner of the WAL files
If
-walor-shmbelong to another user, the site gets random errors — even on reads. -
A file on a network drive
File locks over NFS are unreliable — the database can be damaged.
-
Copying a live file
A plain copy during writes may be broken; use
VACUUM INTOor.backup. -
Growth without a plan
When writes or servers multiply, the move to a server database is easier planned in advance.
8 tips for SQLite in production
-
01
WAL mode
PRAGMA journal_mode = WAL— readers and the writer stop blocking each other. -
02
busy_timeout
A few seconds of waiting instead of “database is locked”.
-
03
Foreign keys on
PRAGMA foreign_keys = ONin every connection — it is off by default. -
04
STRICT tables
Types are checked, and wrong data is an error, not a surprise.
-
05
Imports in one transaction
Thousands of inserts in one transaction are many times faster than one by one.
-
06
One owner for all files
The database,
-waland-shmbelong to the user the site runs as. -
07
Backups with Litestream
Continuous copying to storage — restore to any moment.
-
08
Plan the exit
Standard SQL and a migration tool make a later move to PostgreSQL routine.
What SQLite looks like: 3 SQL examples
Settings for a site with a strict table, full-text search and JSON with an index. Checked in SQLite 3.40 on a database file.
Settings and a strict table
WAL, waiting instead of an error, upsert with RETURNING — and a text in a price column is rejected.
-- settings for a site: readers do not block the writer, and a busy file waits instead of failing
PRAGMA journal_mode = WAL; -- wal
PRAGMA busy_timeout = 5000;
PRAGMA foreign_keys = ON;
-- STRICT: column types are checked, as in a server database
CREATE TABLE products (
id INTEGER PRIMARY KEY,
sku TEXT NOT NULL UNIQUE,
title TEXT NOT NULL,
price INTEGER NOT NULL CHECK (price >= 0)
) STRICT;
INSERT INTO products (sku, title, price) VALUES ('A-100', 'Oak table', 24000)
ON CONFLICT (sku) DO UPDATE SET price = excluded.price
RETURNING id, title, price; -- 1|Oak table|24000
INSERT INTO products (sku, title, price) VALUES ('A-101', 'Oak chair', 'cheap');
-- error: cannot store TEXT value in INTEGER column products.price
Full-text search in the file
FTS5 finds and highlights the match and sorts by relevance.
-- full-text search right inside the file: no separate search engine
CREATE VIRTUAL TABLE articles USING fts5(title, body);
INSERT INTO articles (title, body) VALUES
('How to choose a table', 'Oak and walnut tables for the kitchen'),
('Chair care', 'How to clean oak chairs'),
('Shelves', 'Pine shelves for a small room');
SELECT title, snippet(articles, 1, '[', ']', '…', 4) AS fragment
FROM articles
WHERE articles MATCH 'oak'
ORDER BY rank;
-- Chair care|How to clean [oak]…
-- How to choose a table|[Oak] and walnut tables…
JSON with an index
A generated column pulls a field out of JSON, and an index makes the search by it fast.
-- JSON in a column and an index on a field inside it
CREATE TABLE events (
id INTEGER PRIMARY KEY,
payload TEXT NOT NULL CHECK (json_valid(payload)),
kind TEXT GENERATED ALWAYS AS (payload ->> '$.kind') VIRTUAL
);
CREATE INDEX events_kind_idx ON events (kind);
INSERT INTO events (payload) VALUES ('{"kind": "order", "total": 24000}'), ('{"kind": "visit"}');
SELECT id, payload ->> '$.total' AS total
FROM events
WHERE kind = 'order'; -- 1|24000
Questions about SQLite
Can SQLite be used for a website?
Yes. Most sites read far more than they write, and SQLite in WAL mode handles that very well.
How many visitors can SQLite handle?
It depends on writes, not visits: reads scale well, and the limit is many simultaneous writes.
SQLite or PostgreSQL?
SQLite for a site or service on one server; PostgreSQL when there are many writers, several servers or complex data.
Is SQLite reliable?
Yes: full transactions and one of the most thoroughly tested codebases in the world. Risks come from network drives and copying a live file.
How do I back up SQLite?
VACUUM INTO or .backup for a consistent copy, or Litestream for continuous copying.
Why “database is locked”?
Another connection is writing. Turn on WAL and set busy_timeout so requests wait a moment.
Does SQLite support full-text search?
Yes, FTS5 with ranking and highlighting; it does not know word forms, so prefix queries help.
Is moving from SQLite to PostgreSQL hard?
Not if the SQL is standard: pgloader moves the data, and the code changes little.
Online form
A database
for your scale
I choose the database for the scale of the project: SQLite for sites and small services, PostgreSQL or MySQL where the load and data grow — and move data when it is time. Tell me about the task — I answer within one working day.