The fkra blog
Engineering · 9 min

SQLite is planning for 2050

SQLite’s developers plan to support it through 2050. Keeping old files readable takes compatibility rules, failure tests, and people willing to maintain them.

Listen to this article

11:19
0:00

AI may have been used to generate this audio.

Press Space or K to play or pause, and J or L to go back or forward 15 seconds.

Sources checked on 16 October 2026.

2050 is an unusual date to find in software documentation. By then, a file you save today could have outlasted several laptops, employers, operating systems, and the company that made the application.

SQLite’s developers say they plan to support it through that year. They also distinguish an intention from a prediction: nobody can guarantee what the world will need that far ahead. That intention makes their present decisions about compatibility and maintenance worth examining. [1]

We routinely choose a dependency because it saves us an afternoon. Much less often do we ask what will make its data readable twenty years later, or who will still understand the decisions inside it.

An application using SQLite can keep its records in an ordinary file. You can keep that file after you have stopped using the application.

It started with a server that could be unavailable

Richard Hipp was working on software that helped people understand and manage systems aboard a naval ship. The application depended on an Informix server. When that server was unavailable, the application could not get the data it needed, even when its own computer was functioning. He wanted to read the data directly from disk. [2]

Hipp says SQLite was used for development and testing on the original project; it did not become the customer’s official database. The tidy version, in which a developer writes a replacement and immediately saves the ship, would be a better anecdote and a worse account of what happened.

SQLite 1.0 appeared on 17 August 2000. [3] Its architecture removed a particular dependency: an application could call a database engine embedded in its own process, without communicating with a separately running database server. That remains an important distinction when reading the word “serverless” in SQLite’s documentation. There is no managed cloud service hiding behind it. [4]

This changes the work required to distribute a small application. A notes tool or a catalogue can keep structured records without asking its user to install, configure, and maintain a database service. The person opening the application may never need to know which engine it uses.

It also gives the project a boundary. A database designed to live inside an application will make different choices from one designed to coordinate many independent clients across a network. Comparing them only by how many features appear in a checklist misses the reason for the design.

The file from 2004

On 18 June 2004, SQLite 3.0.0 introduced the file format used by the SQLite 3 family. The project documents backward compatibility with files from that first release, across machines with different architectures. A newer engine can still work with a database created by the old one. [5]

Backward compatibility also has a direction. A current engine reading an old database does not mean every old engine understands every new database. SQLite added opt-in STRICT tables in November 2021. Older versions generally cannot open a schema using that keyword, although the underlying file format remains the same. [6]

An archive reader therefore needs a minimum engine version as well as a file-format name. Record both when a newer schema feature matters.

Fifty years on one ruler

Position is proportional to calendar year. The hatched area after 2026 is future time; 2050 is an intention, not a release date.

An archive needs its context

Suppose a photo application keeps captions and dates in catalog.db, with the photographs in a neighbouring folder. Years later, you recover the database from an old laptop and open it without trouble. Every photograph points to a folder that was never copied.

A second omission is harder to spot. One column contains status = 3. Does that mean approved, hidden, or waiting for review? SQLite has preserved the number correctly. Someone still needs to preserve its meaning. In the fictional archive below, the photos and a short data dictionary can be packed alongside the database. Try leaving either out.

Pack an archive you can understand

Fictional catalogue. The meaning of status 3 is defined only for this example. The database can remain readable while assets or definitions are missing.

Real formats do this extra work. The Open Geospatial Consortium’s GeoPackage standard defines conventions for storing geographic features, map tiles, and descriptive tables inside SQLite. Its rules tell another application how to interpret those records. The database container handles storage; the GeoPackage specification supplies the shared vocabulary. [14]

Fossil, the version-control system used by the SQLite project, stores a project’s revision, ticket, and wiki history in a repository database. Its documentation distinguishes that repository from separate checkout and configuration databases. A file can hold far more than a cache, but understanding which file contains which work remains part of the application’s design. [15]

For a product team, this changes the export specification. Include the records, referenced assets, field definitions, and version requirements needed to use the export. Test it with someone who did not write the application.

One file, with some working files beside it

The phrase “single-file database” is attractive enough to become dangerous shorthand. While a database is in use, transaction machinery can create other files. In write-ahead logging mode, committed changes can live in a -wal file before being checkpointed into the main database; a -shm file normally helps coordinate access. WAL has been available since July 2010. [7]

So a casual copy of the main .db file while an application is writing may omit work that has already been committed. SQLite provides an Online Backup API, and its documentation describes VACUUM INTO as another way to produce a separate copy of a live database. [8]

The product therefore needs explicit backup behaviour. A user sees a document and reasonably expects copying it to preserve the document. The application developer has to turn that expectation into a safe operation, especially while the document is changing.

The same care applies to sync. Sending a completed snapshot to another machine is one problem. Allowing several machines to edit their own copies and then reconciling those edits is another. Choosing SQLite provides storage; the product still has to decide what conflicting edits mean.

Follow one edit to disk

Conceptual values, not SQLite’s page layout. This example delays checkpointing and omits the coordination file. A backup is separate from a checkpoint. [7] · [8]

Reliability takes work you rarely see

SQLite’s testing documentation describes several independent test systems, deliberate memory-allocation failures, simulated I/O errors, crash testing, malformed databases, and fuzzing. It reports full branch coverage in an as-deployed configuration. Each catches a different kind of failure. [9]

Consider a task application moving a card from one list to another. It updates the list identifier and the card’s position in a transaction. A failure test can interrupt that work between updates, then reopen the database and check for an incomplete move. Passing a test in which the application exits normally would leave that failure unexamined.

Coverage numbers cannot establish the absence of defects. In March 2026, the project documented a rare WAL-reset bug that could cause corruption when connections wrote or checkpointed at precisely overlapping moments. The WAL documentation identifies fixed releases and later records an independently developed reproducer. [7]

Maintainers need to discover defects, explain which releases are affected, and distribute repairs. Calling an old dependency “proven” is not a reason to stop reading its release notes. As of this article’s source check, the release history had reached SQLite 3.54.1, dated 16 October 2026. [10]

The less visible benefit of testing is permission to improve the code. If maintainers can check established behaviour carefully, they can change an implementation with a clearer account of what they might break. Stability requires continuing work even when the user-facing result is that nothing surprising happens.

Someone has to pay for the years between releases

SQLite’s distributed code and documentation are dedicated to the public domain. Its contribution process is tightly controlled, including documentation of contributors’ rights to dedicate their work. Open access to the code does not mean every proposed patch is accepted. [11]

The project also sells professional support and offers consortium membership. Its support page describes companies sponsoring ongoing development in return for services and access to additional products and test suites. [12]

A product team can use the code freely while paying for help with the dependency it ships. The licence alone will not answer who investigates a difficult failure.

When evaluating a dependency, ask who reviews a difficult change, who responds to a defect, and which organisations pay for that work.

It is easy to notice the cost of a support contract because it appears on an invoice. The cost of an abandoned dependency tends to arrive later, spread across an upgrade, a security review, a migration, and the engineer who has to work out why the old data no longer loads.

Choose it for the shape of the work

SQLite’s own guidance recommends considering a client/server engine when many writers must proceed simultaneously, or when applications on different machines need direct access to shared storage. SQLite allows one writer at a time per database file; brief writes can take turns, but that does not remove the constraint. [13]

The number of people using a product is therefore a poor substitute for understanding its database activity. A busy, mostly read-only catalogue and a smaller system full of overlapping write transactions can impose very different demands. The useful questions concern the work, its location, and what happens when operations overlap.

Consider a local catalogue importing a batch of records while the user edits a tag. The tag update may be tiny, yet it has to wait if the import still holds the write transaction. Splitting an import into smaller committed batches can create opportunities for other writes, but also changes whether the entire import succeeds or fails as one unit. The application has to choose that behaviour deliberately.

In the schedule below, four fictional writes arrive at known times. Change only the import’s time holding the writer slot. The later edits keep their arrival times and their own work. This isolates why the duration of one transaction matters to the person waiting behind it.

Three edits behind one import

Illustrative schedule in milliseconds. Writes run in the chosen arrival order and wait without timing out. SQLite does not promise this scheduling order or these durations. Dashed segments show waiting; solid segments show time holding the writer slot. [13]

A question worth asking

What the answer changes

Where does the code issuing queries run?

Whether local embedded storage fits the architecture

How long does each write transaction keep other writers waiting?

Whether writers can comfortably take turns

What has to survive a lost machine?

The backup and recovery design

Will several devices edit independently?

The need for a separate conflict and synchronisation strategy

Can someone explain the stored data without this application?

Whether a readable file remains useful after the product changes

For a small product team, SQLite is worth evaluating early when the workload fits. Doing so means testing the actual write pattern and recovery process, rather than dismissing it because “lite” sounds temporary or choosing it because a familiar company uses it somewhere.

Try the archive exercise on your own product. Take a real export. Open it on a clean machine, without the application that created it. Check whether the records, attachments, relationships, and meaning can be recovered. Add the missing definitions and files to the export, then repeat the test.

Sources

0
74 views
SQLiteDatabasesDependenciesMaintenancePortability
Mosab Alrasheed
Get the next entry

One email when we publish. Research, product decisions, and what teams report back.

Now playingSQLite is planning for 2050