<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/sqlite-utils-4-0rc1-adds-migrations-and-nested-transactions-vffby2kab" -->

---
title: sqlite-utils 4.0rc1 adds migrations and nested transactions
description: sqlite-utils 4.0rc1 is the first release candidate for the major version of Simon Willison's Python library and CLI tool for SQLite. Two significant new...
canonical: https://daily.dev/posts/sqlite-utils-4-0rc1-adds-migrations-and-nested-transactions-vffby2kab
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: sqlite-utils 4.0rc1 adds migrations and nested transactions | daily.dev
og:description: sqlite-utils 4.0rc1 is the first release candidate for the major version of Simon Willison's Python library and CLI tool for SQLite. Two significant new...
og:url: https://daily.dev/posts/sqlite-utils-4-0rc1-adds-migrations-and-nested-transactions-vffby2kab
og:image: https://api.daily.dev/og/posts/vfFby2kab.png
og:image:alt: sqlite-utils 4.0rc1 adds migrations and nested transactions
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# sqlite-utils 4.0rc1 adds migrations and nested transactions

**[Simon Willison](https://daily.dev/sources/simonwillison)** · 5 min read · 0 upvotes · 0 comments

## Summary

sqlite-utils 4.0rc1 is the first release candidate for the major version of Simon Willison's Python library and CLI tool for SQLite. Two significant new features are introduced: database migrations (ported from the sqlite-migrate package, supporting forward-only migrations defined as decorated Python functions) and nested transactions via a new db.atomic() context manager inspired by Django and Peewee. The release also includes several backwards-incompatible changes from earlier alphas, including updated upsert syntax using INSERT ... ON CONFLICT SET, dropped Python 3.8 support, changed default float column type from FLOAT to REAL, double-quoted identifiers in schemas, and type detection now enabled by default for CSV/TSV imports. The RC can be installed via pip or tested with uvx.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://simonwillison.net/2026/Jun/21/sqlite-utils-40rc1>

## Questions this post answers

### What breaking changes are in sqlite-utils 4.0 compared to version 3?

Several breaking changes ship in sqlite-utils 4.0: db.table(table_name) now only works with actual tables (use db.view() for SQL views), the default floating point column type changed from FLOAT to REAL, table and column names are now wrapped in double-quotes instead of square braces, table.convert() no longer skips False values (removing the need for --skip-false), and type detection is now the default for insert/upsert CLI commands when importing CSV or TSV data.

_daily.dev helps developers track breaking changes like these before running a major library upgrade._

### How do I add database migrations to a project using sqlite-utils?

sqlite-utils 4.0rc1 bundles a migrations system, ported from the earlier standalone sqlite-migrate package, letting you define migration functions in a migrations.py file decorated with @migrations(), then apply them via migrations.apply(db) in Python or the sqlite-utils migrate command-line tool. The system deliberately has no reverse migrations; fix mistakes by writing a new forward migration instead.

_developers planning a schema migration workflow can follow sqlite database changes like this on daily.dev._

### How do nested transactions work in sqlite-utils with db.atomic()?

sqlite-utils 4.0rc1 introduces db.atomic(), a context manager built on SQLite's native savepoint support that allows nesting transactions, borrowing its naming convention from Django and Peewee. Wrapping a block in db.atomic() lets you catch and roll back inner operations, such as a failed insert, without discarding the outer transaction's already-committed inserts.

_teams comparing transaction handling approaches can track sqlite tooling updates like this on daily.dev._

## Similar posts on daily.dev

- [sqlite-utils 4.0, now with database schema migrations](https://daily.dev/posts/sqlite-utils-4-0-now-with-database-schema-migrations-cco2twstz) · Simon Willison · 0 upvotes · 0 comments
- [sqlite-utils 4.0rc2, mostly written by Claude Fable](https://daily.dev/posts/sqlite-utils-4-0rc2-mostly-written-by-claude-fable-ez8975ilm) · Simon Willison · 0 upvotes · 0 comments
- [sqlite-utils 4.0a1 has several \(minor\) backwards incompatible changes](https://daily.dev/posts/sqlite-utils-4-0a1-has-several-minor-backwards-incompatible-changes-itttfhqzt) · Simon Willison · 0 upvotes · 0 comments

---

Tags: [#python](https://daily.dev/tags/python), [#database](https://daily.dev/tags/database), [#sqlite](https://daily.dev/tags/sqlite)

[View this post on daily.dev](https://daily.dev/posts/sqlite-utils-4-0rc1-adds-migrations-and-nested-transactions-vffby2kab)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"sqlite-utils 4.0rc1 adds migrations and nested transactions","url":"https://daily.dev/posts/sqlite-utils-4-0rc1-adds-migrations-and-nested-transactions-vffby2kab","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/sqlite-utils-4-0rc1-adds-migrations-and-nested-transactions-vffby2kab"},"datePublished":"2026-06-21T23:38:55.811Z","dateModified":"2026-09-13T18:36:44.199Z","description":"sqlite-utils 4.0rc1 is the first release candidate for the major version of Simon Willison's Python library and CLI tool for SQLite. Two significant new...","image":"https://media.daily.dev/image/upload/s--0_ODbtD2--/f_auto/v1722860399/public/Placeholder%2008","thumbnailUrl":"https://media.daily.dev/image/upload/s--0_ODbtD2--/f_auto/v1722860399/public/Placeholder%2008","isAccessibleForFree":true,"articleSection":"Simon Willison","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Simon Willison","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/cf12b897300740218b35f49a6309ec5b","url":"https://daily.dev/sources/simonwillison"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/sqlite-utils-4-0rc1-adds-migrations-and-nested-transactions-vffby2kab","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"python,database,sqlite","timeRequired":"PT5M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Simon Willison","item":"https://daily.dev/sources/simonwillison"},{"@type":"ListItem","position":3,"name":"sqlite-utils 4.0rc1 adds migrations and nested transactions"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/sqlite-utils-4-0rc1-adds-migrations-and-nested-transactions-vffby2kab#faq","mainEntity":[{"@type":"Question","name":"What breaking changes are in sqlite-utils 4.0 compared to version 3?","acceptedAnswer":{"@type":"Answer","text":"Several breaking changes ship in sqlite-utils 4.0: db.table(table_name) now only works with actual tables (use db.view() for SQL views), the default floating point column type changed from FLOAT to REAL, table and column names are now wrapped in double-quotes instead of square braces, table.convert() no longer skips False values (removing the need for --skip-false), and type detection is now the default for insert/upsert CLI commands when importing CSV or TSV data. daily.dev helps developers track breaking changes like these before running a major library upgrade."}},{"@type":"Question","name":"How do I add database migrations to a project using sqlite-utils?","acceptedAnswer":{"@type":"Answer","text":"sqlite-utils 4.0rc1 bundles a migrations system, ported from the earlier standalone sqlite-migrate package, letting you define migration functions in a migrations.py file decorated with @migrations(), then apply them via migrations.apply(db) in Python or the sqlite-utils migrate command-line tool. The system deliberately has no reverse migrations; fix mistakes by writing a new forward migration instead. developers planning a schema migration workflow can follow sqlite database changes like this on daily.dev."}},{"@type":"Question","name":"How do nested transactions work in sqlite-utils with db.atomic()?","acceptedAnswer":{"@type":"Answer","text":"sqlite-utils 4.0rc1 introduces db.atomic(), a context manager built on SQLite's native savepoint support that allows nesting transactions, borrowing its naming convention from Django and Peewee. Wrapping a block in db.atomic() lets you catch and roll back inner operations, such as a failed insert, without discarding the outer transaction's already-committed inserts. teams comparing transaction handling approaches can track sqlite tooling updates like this on daily.dev."}}]}
```

