5 min read

sqlite-utils 4.0rc1: migrations, nested transactions and changes

sqlite-utils 4.0rc1, published 21st June 2026, adds built-in migrations and a db.atomic() API for nested transactions while including.

The Brieftide

TL;DR

  • 01sqlite-utils 4.0rc1, published 21st June 2026, adds built-in migrations and a db.atomic() API for nested transactions while including.
  • 02The release is a major version bump and includes a number of backward-incompatible changes that the author wants users to test before a stable release.
  • 03The RC adds two significant features: integrated migrations and an atomic transaction context manager that supports nested savepoints.

sqlite-utils 4.0rc1, the first release candidate for sqlite-utils v4, was published on 21st June 2026 and bundles two headline features: built-in database migrations and a db.atomic() API that exposes nested transactions (savepoints). The release is a major version bump and includes a number of backward-incompatible changes that the author wants users to test before a stable release.

What is new in sqlite-utils 4.0rc1?

The RC adds two significant features: integrated migrations and an atomic transaction context manager that supports nested savepoints. The migrations feature is a slightly modified port of the sqlite-migrate package the author released a few years ago, and it can be run from Python or from the CLI. The db.atomic() API borrows the term "atomic" from Django and Peewee and wraps SQLite savepoints for easier nested transaction handling.

The post includes usage examples for both features. For migrations you can define a migrations.py and run it in Python with Database("creatures.db") and migrations.apply(db), or on the command line with sqlite-utils migrate creatures.db migrations.py. For testing or trying the RC the author suggests pip install sqlite-utils==4.0rc1 or running the CLI via uvx --with sqlite-utils==4.0rc1 sqlite-utils --help.

How do migrations and db.atomic() work?

Migrations are implemented as a compact system that does not provide reverse migrations, so the workflow expects deliberate forward changes and fixes applied by new migrations. The migrations API example shows a Migrations("creatures") object with decorated functions like create_table and add_weight that call into the sqlite-utils Database and table helpers.

The db.atomic() context manager exposes SQLite savepoints so nested blocks can be rolled back independently. The examples show nested with db.atomic(): blocks where an inner exception can be caught and the outer transaction continues, enabling partial rollbacks inside a larger unit of work. The author notes db.atomic() is less exercised than migrations and asks for more attention from testers.

What backward-incompatible changes should users expect?

The major version bump brings a set of breaking changes carried from the 4.0 alpha notes. Key items called out include:

  • Upsert operations now use SQLite's INSERT... ON CONFLICT SET syntax on all SQLite versions later than 3.23.1, which differs slightly from the previous INSERT OR IGNORE then UPDATE approach. The test suite now also runs against SQLite 3.23.1, described as the last version from 2018-04-10 before that syntax was added.
  • Dropped support for Python 3.8 and added support for Python 3.13.
  • db.table(table_name) now only works with tables; SQL views must be accessed via db.view(view_name).
  • The default floating point column type changed from FLOAT to REAL for auto-detected columns.
  • Packaging moved to pyproject.toml from setup.py and the sqlite-utils TUI is provided by the sqlite-utils-tui plugin.
  • Several CLI behaviors changed, for example type detection for CSV/TSV imports is now on by default (use --no-detect-types to restore previous behavior) and the --functions argument can accept a file path and be specified multiple times.

The release notes list more granular changes such as table.convert behavior, table and column quoting style, and insert/upsert API adjustments; users migrating to v4 should review the alpha release notes referenced in the post.

Why it matters

Bundling a proven migrations implementation and a simple nested-transaction API reduces the amount of glue code projects need to manage SQLite schema and transactional workflows. The author notes the migrations predecessor has been used by LLM and other projects for several years, which suggests the pattern is battle tested. Given sqlite-utils is both a library and a CLI, these additions affect a wide range of small apps and scripts that rely on easy SQLite manipulation.

The backward-incompatible changes mean projects that depend on older behaviors, Python versions, or CLI defaults will need to test and adjust, so this RC stage is important for community validation.

What to watch

Try the RC using pip install sqlite-utils==4.0rc1 and report issues or compatibility problems, since the author wants people to test before declaring a stable 4.0 release. Watch for the stable release candidate becoming v4.0 and for any follow-up fixes to the db.atomic() API after broader testing.

Relevant dates
  1. 21st June 2026
    sqlite-utils 4.0rc1 published

    First release candidate for sqlite-utils v4, adds migrations and db.atomic()

  2. 2018-04-10
    SQLite 3.23.1 release

    Last SQLite version before INSERT ... ON CONFLICT SET syntax was added (used in tests)

Advertisement

Written by The Brieftide · Sources: Simon Willison, Simon Willison

The Brieftide Daily · 06:00

Briefs like this one, in your inbox every morning.

 

FreeOne email a dayEvery claim sourcedUnsubscribe in one click
Advertisement