# Drift: a reactive, typesafe SQLite persistence library for Dart and Flutter

> Drift generates Dart code from your tables and SQL, so query mistakes surface at compile time and any query can be exposed as an auto-updating stream. It targets Flutter and Dart apps that need more than a key-value store but do not want to hand-write SQLite glue.

**simolus3/drift** — Drift is an easy to use, reactive, typesafe persistence library for Dart & Flutter.

- Repository: https://github.com/simolus3/drift
- Website: https://drift.simonbinder.eu/
- Stars: 3,283 · Forks: 468
- Language: Dart
- License: MIT
- Published: 2026-09-24 · Updated: 2026-09-24 · Language: en
- Canonical page: https://hysenlabs.com/projects/simolus3-drift

## What Drift is for, and who should reach for it

Drift is a persistence library for Flutter and Dart built on top of SQLite. The README describes it as reactive, meaning a query can be turned into an auto-updating stream, and typesafe, meaning the code you call is generated from your table definitions and SQL rather than assembled from strings at runtime.

The audience is narrow but real. If your app stores records that relate to each other, filters and sorts them, and shows the result in a UI that must stay current as rows change, you are the intended user. The README lists joins, transactions, schema migrations, batched updates and complex filters as builtin features, and mentions support for SQL features like WITH and WINDOW clauses. A settings screen with a handful of keys is not that audience. A local-first app with a few tables that the UI observes is.

The project is published under the MIT license, lives on pub.dev as two packages (drift for the runtime, drift_dev for the generator), and the repository also contains sqlparser, a standalone SQL parser and static analyzer written in pure Dart that the README says can be used without Drift.

## How the generator turns tables and SQL into Dart APIs

The mechanism is code generation, and it is the part that shapes everything else about working with the library. You declare tables and queries, and drift_dev compiles them into Dart classes. The README states that drift generates type-safe code based on your tables and queries, and that mistakes in queries are found at compile time with descriptive lints. That is the core trade: you give up writing raw SQLite calls and get a generated API that the analyzer checks.

The repository layout reflects this split. drift/ holds the runtime, drift_dev/ holds the compiler, and the README notes that drift_dev also contains a fully-featured SQL IDE for the Dart analyzer, so the generator is not only a build step but also a source of editor tooling. Queries can be written in SQL or in Dart; the README describes fluent APIs for both languages, and says SQL files support imports and that database code can be split into daos, which the README frames as keeping database code modular.

Reactivity sits on top of that generated layer. Any SQL query can become an auto-updating stream, including queries that touch several tables. That means the generated code has to track which tables a query depends on and re-run it when those tables change, which is why the stream API is a property of the query objects rather than something you wire up by hand. The README also claims drift is the only major persistence library with builtin threading support, letting database code run across isolates without additional effort.

## Installing Drift and running a first query

The README does not spell out an installation command; it points to the getting-started documentation at drift.simonbinder.eu/docs/getting-started/. What the repository does show is the package split, which tells you what to add. The runtime is published as drift and the generator as drift_dev, both on pub.dev. The repository also contains a drift_flutter/ package and a drift_sqflite/ package, which the README does not describe in detail.

A typical setup adds the runtime as a dependency and the generator as a development dependency:

```bash
dart pub add drift
dart pub add --dev drift_dev build_runner
```

After that, the generator runs through the Dart build system. The exact build command is not given in the README, so check the getting-started page for the invocation that matches your project layout before assuming one.

The README does give a concrete cross-platform example to compare against: a Flutter todo app at examples/app that the README says works on all platforms. That example is the honest starting point for a first real use, because it shows a complete project rather than a fragment. For a first query of your own, the pattern the README describes is to define a table, let the generator produce the accessor, then call the generated query method and either await it once or listen to it as a stream. The stream is the part worth trying first, since it is the behaviour that distinguishes Drift from calling SQLite directly.

## The code-generation step is the main cost

The most obvious limitation is structural: Drift depends on a generator. The README presents this as a safety feature, and it is, but it also means your build has another moving part. Table definitions and SQL are inputs to drift_dev, so a change to a table is not finished until the generator has run and the produced Dart has been updated. In a large project that is a build-time cost you pay repeatedly, and it is the reason the repository ships a Dockerfile that installs Chromium, builds SQLite from source, and runs tool/upgrade_all.sh followed by tool/test_all.sh.

The README does not document rollback behaviour for schema migrations, and it does not describe what happens when a migration fails partway. Migrations are listed as a builtin feature, but the failure path is not covered in the README text, so anyone shipping a migration to production should read the migration documentation rather than infer the behaviour.

The library is also the wrong tool when your data is genuinely a small set of scalars. The README compares Drift's performance to key-value stores like shared preferences and Hive, but performance is not the deciding factor: if you have no relations, no joins and no need to observe query results, the generated table and query layer is overhead you will not recover. Drift is also scoped to SQLite. If you need a client-server database, this is not a substitute.

## Drift against a key-value store, and against raw SQLite

The README itself names the closest alternative: shared preferences and Hive, both key-value stores, and it argues Drift can keep up with their performance. The difference is not speed, it is the data model. A key-value store gives you a map you read and write whole; Drift gives you tables, joins and filters, and a query that re-runs when its underlying rows change. If your app's state is one record, the key-value store is simpler and you should use it. If your state is many records that reference each other, the key-value store forces you to load and rewrite more than you need, and Drift's query layer earns its place.

The other alternative is using SQLite directly through a Dart binding. That removes the generator and the build step, and it gives you full control over SQL. What you lose is the compile-time checking the README emphasizes: queries become strings, and a typo in a column name becomes a runtime error. You also lose the auto-updating stream, which in Drift is a property of the generated query object. The repository's sqlparser package sits between these positions: it is a pure-Dart SQL parser and static analyzer that the README says can be used without Drift, so you can get some analysis of SQL statements without adopting the whole persistence layer.

## Maintenance, releases and what the MIT license means here

The repository is not archived and the last push was on 2026-09-22. Recent releases are drift-2.35.0 on 2026-09-09, drift-2.34.4 on 2026-09-02 and drift-2.34.3 on 2026-07-27, so the release cadence over the past two months has been frequent and the version numbers are close together, which is typical of a library that ships fixes without waiting for a major version.

The repository is managed with melos, and the README gives the commands for working on it: dart pub global activate melos, then dart pub get in the repository root, then melos bootstrap. That matters for upgrade cost in a different way than for a normal dependency. Because the repository contains several packages (drift, drift_dev, sqlparser and the Flutter and sqflite integration packages), upgrading the runtime may also mean upgrading the generator, and the generator is what produces your code. A version bump therefore touches both your dependencies and your generated files.

On licensing: the repository is MIT licensed. MIT is permissive, which generally means you can use the library in closed-source applications, but this is not legal advice and the LICENSE file in the repository root is the authoritative text. The README also lists sponsors, Stream and PowerSync, which is context for how the project is funded rather than a constraint on users.

## Conclusion

Adopt Drift if you are building a Flutter or Dart app that needs real relational queries, joins, transactions or migrations, and you want compile-time checking instead of string-built SQL. Do not adopt it if a key-value store covers your data model, or if you cannot accept a code-generation step in your build. Before committing, verify three things in the docs: which database implementation you need for your target platforms (drift_flutter, drift_sqflite or the core package with a custom executor), how schema migrations are expressed through the generated schema helpers, and whether running queries across isolates matters for your workload, since the README calls builtin threading support a differentiator.

## FAQ

### How do I install Drift in a Dart or Flutter project?

The README does not give an install command; it directs readers to the getting-started documentation at drift.simonbinder.eu/docs/getting-started/. The repository shows the package split: drift is the runtime on pub.dev and drift_dev is the generator, also on pub.dev.

### How do I use Drift in a Flutter app?

You define tables and queries, let drift_dev generate the Dart code, and then call the generated query methods. The README says any SQL query can be turned into an auto-updating stream, and points to a Flutter todo app at examples/app that works on all platforms as a reference.

### Which platforms does Drift support?

The README states that Drift works on Android, iOS, macOS, Windows, Linux and the web, and links to a Flutter todo app template that runs on all of them.

### What license is Drift released under?

The repository is MIT licensed. The LICENSE file in the repository root is the authoritative text; this is not legal advice.

### Does Drift require a code generation step?

Yes. The README says Drift generates type-safe code based on your tables and queries, and that mistakes in queries are found at compile time. The generator is published separately as drift_dev.

### Can I use Drift's SQL parser without adopting Drift?

Yes. The README says the sqlparser package is a SQL parser and static analyzer written in pure Dart that can be used without drift to perform analysis on SQL statements.

## Sources

- [License: MIT](https://github.com/simolus3/drift/blob/develop/LICENSE)
- [Project website](https://drift.simonbinder.eu/)
- [README](https://github.com/simolus3/drift/blob/develop/README.md)
- [Releases](https://github.com/simolus3/drift/releases)
- [simolus3/drift on GitHub](https://github.com/simolus3/drift)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/simolus3-drift
