What Is SQLite? The Database Inside Your App
SQLite is a serverless, file-based SQL database compiled directly into an application. How it works, why it's everywhere, and when to reach for it.
SQLite is a relational database engine that runs as a library linked directly into an application, rather than a separate server process a client connects to over the network. The entire database — schema, tables, indexes, and data — lives in a single ordinary file on disk. There’s no server to start, no port to open, and no connection string to configure; the application just opens the file and reads or writes SQL against it.
No server, one file
Compare this to PostgreSQL or MySQL: both run as standalone server processes that listen on a network port, accept connections from one or many clients, and manage users, permissions, and concurrent access across a fleet of applications. SQLite has none of that infrastructure. The “database” is a .sqlite (or .db) file, and the “client” is the SQLite library compiled into your program. Reading and writing means calling functions in-process — there’s no network round trip, no connection pooling to manage, and no separate service to deploy, monitor, or keep alive.
This makes SQLite trivial to embed: mobile apps, desktop applications, browsers (many implement Web Storage internals on top of it), and countless command-line tools ship a SQLite database as part of their install, with zero setup required from the user.
It’s still a real SQL database
Despite the lightweight packaging, SQLite supports the SQL most developers already know: JOINs, transactions with ACID guarantees, indexes, triggers, views, and most of the standard data types. It enforces foreign keys (when enabled), supports window functions and CTEs, and its query planner does the same kind of cost-based optimization a bigger database does, just scoped to a single file rather than a cluster.
Where it genuinely differs from a client-server database is concurrency: SQLite allows many simultaneous readers, but historically only one writer at a time locks the whole database file. Its newer WAL (write-ahead logging) journal mode improves this considerably — readers no longer block writers — but SQLite still isn’t built for the high write concurrency a multi-tenant server database handles by design. That’s the trade-off for having no server to scale in the first place.
SQLite vs a client-server database
| SQLite | PostgreSQL / MySQL | |
|---|---|---|
| Architecture | Embedded library, single file | Standalone server process |
| Setup | None — just open the file | Install, configure, run as a service |
| Concurrent writers | One at a time (even with WAL) | Many, via MVCC and connection pools |
| Network access | None — in-process only | Yes, over TCP |
| Best for | Local apps, embedded devices, small-to-medium workloads, testing | Multi-user apps, high write concurrency, centralized data |
| Multi-machine access | No — one file, one machine | Yes — many clients over the network |
Where it actually shows up
SQLite is arguably the most widely deployed database engine in the world, precisely because it’s invisible: it’s the default storage engine on both major mobile platforms, it’s bundled into most web browsers, and it’s a common choice for local-first software — apps that keep a full working copy of data on-device and sync in the background rather than requiring a live network connection for every operation. It’s also a favorite for testing: spinning up an in-memory SQLite instance for a test suite is far faster than provisioning a real Postgres instance, since there’s no server startup involved at all.
It’s a poor fit, on the other hand, for a backend that many application servers write to concurrently at high volume — that’s squarely a client-server database’s job, and trying to point a fleet of web servers at one shared SQLite file over a network filesystem is a well-known way to hit locking contention and corruption risk.
File format stability and portability
One underappreciated property of SQLite is the stability of its on-disk file format: a database file written years ago on one platform can typically be opened directly on another without any export or conversion step, because the file format itself is the interchange format — there’s no separate dump-and-restore process required the way there often is between different versions or vendors of a client-server database. That single-file portability is also why SQLite databases are a common choice for distributing read-only datasets alongside an application, or for moving a working dataset between a developer’s laptop and a CI environment with nothing more than copying a file.
Working with it
Because SQLite speaks standard SQL, most ORMs support it as a backend alongside Postgres and MySQL, which is part of why it’s such a common default for local development and prototyping — the same schema and queries often run against SQLite locally and a full server database in production with minimal changes.
Configuration is nearly nonexistent
A client-server database ships with a substantial set of tunable parameters — memory allocation, connection limits, query planner settings — that someone has to configure sensibly for the workload at hand. SQLite has comparatively little to configure precisely because there’s no shared server to tune for competing workloads; the main levers are the journal mode (rollback journal versus WAL) and a handful of pragmas controlling things like synchronous write behavior. This minimal surface area is part of the same trade-off as everything else about SQLite: less to configure and less that can be misconfigured, in exchange for less flexibility to tune for a demanding, highly concurrent workload in the first place.
The takeaway
SQLite trades the concurrency and centralization of a client-server database for zero operational overhead: no server process, no network layer, just a single file and an in-process library that speaks full SQL. That makes it the right default for embedded, local-first, and single-writer workloads — mobile apps, desktop tools, test suites — and the wrong choice for a backend that many servers need to write to concurrently, where Postgres or MySQL is the better fit.
Tagged
Keep reading
The Lycoris Team · · 5 min read What Is a Stored Procedure? SQL Logic in the Database
A stored procedure is precompiled SQL saved inside the database and invoked by name, cutting network round trips and centralizing business logic.
The Lycoris Team · · 5 min read What Is a Database Trigger?
A database trigger is a procedure that runs automatically on an insert, update, or delete — enforcing rules the application layer can't guarantee.
The Lycoris Team · · 4 min read Primary Key vs Foreign Key vs Unique Constraint
Primary keys identify a row, foreign keys link one table to another, and unique constraints just prevent duplicates. How the three differ in SQL.