Integrating Local Databases in Flutter Using Drift

Summary
Summary
Summary
Summary

Drift (formerly Moor) offers typed, reactive local database integration for Flutter. This tutorial covers adding dependencies, defining tables and DAOs, writing queries, and handling migrations. Drift generates Dart APIs from table definitions, supports streams for UI reactivity, and provides migration hooks via schemaVersion—making it suitable for both simple caches and complex offline-capable mobile apps.

Drift (formerly Moor) offers typed, reactive local database integration for Flutter. This tutorial covers adding dependencies, defining tables and DAOs, writing queries, and handling migrations. Drift generates Dart APIs from table definitions, supports streams for UI reactivity, and provides migration hooks via schemaVersion—making it suitable for both simple caches and complex offline-capable mobile apps.

Drift (formerly Moor) offers typed, reactive local database integration for Flutter. This tutorial covers adding dependencies, defining tables and DAOs, writing queries, and handling migrations. Drift generates Dart APIs from table definitions, supports streams for UI reactivity, and provides migration hooks via schemaVersion—making it suitable for both simple caches and complex offline-capable mobile apps.

Drift (formerly Moor) offers typed, reactive local database integration for Flutter. This tutorial covers adding dependencies, defining tables and DAOs, writing queries, and handling migrations. Drift generates Dart APIs from table definitions, supports streams for UI reactivity, and provides migration hooks via schemaVersion—making it suitable for both simple caches and complex offline-capable mobile apps.

Key insights:
Key insights:
Key insights:
Key insights:
  • Why Choose Drift: Combines SQL expressiveness with Dart type-safety and reactive streams, ideal for Flutter mobile development.

  • Setting Up Drift: Add drift, drift_dev, build_runner, and a sqlite backend; generate code with build_runner and initialize QueryExecutor with path_provider.

  • Defining Tables And DAOs: Define tables as Dart classes to get generated typed entities; use DAOs to encapsulate queries and simplify testing.

  • Querying And Migrations: Use the fluent DSL and .watch() streams for reactive UIs; manage schema changes with schemaVersion and onUpgrade migration logic.

  • Performance And Testing: Index frequently queried columns, avoid N+1 queries with joins/batching, and test migrations against realistic datasets.

Introduction

Local persistence is a must for many Flutter apps: caching API responses, offline-first flows, or storing user data. Drift (formerly Moor) is a typed, reactive persistence library for Flutter and Dart that combines the familiarity of SQL with generated, type-safe Dart APIs. This tutorial shows how to integrate Drift into a Flutter mobile development workflow, covering setup, schema design, DAOs, queries, and migration strategy with concise, practical examples.

Why Choose Drift

Drift blends raw SQL expressiveness with Dart-level safety. Key benefits for mobile development in Flutter:

  • Type-safe tables and queries generated at build time reduce runtime errors.

  • Reactive API (Streams) makes it easy to reflect DB changes in the UI with Provider, Riverpod, or Bloc.

  • Support for both native and sqflite backends enables consistent code across Android, iOS, and desktop.

  • Built-in migration hooks and schemaVersion simplify upgrades.

Drift is especially useful when you want SQL's power (complex joins, indexes) without writing error-prone boilerplate for mapping rows to Dart objects.

Setting Up Drift

Add dependencies to pubspec.yaml for a Flutter app using the native sqlite implementation or sqflite if you prefer:

dependencies:

  • drift: ^2.0.0

  • path_provider: ^2.0.0

  • sqlite3_flutter_libs: ^0.5.0

dev_dependencies:

  • drift_dev: ^2.0.0

  • build_runner: ^2.0.0

Use path_provider to locate an app-specific directory for the database file. Configure a QueryExecutor in your database constructor. Running flutter pub run build_runner build generates the supporting code.

Defining Tables And DAOs

Define tables by extending Table. Drift generates companion classes and typed entities. Keep models focused and use DAO classes for encapsulated query logic.

Example table definition:

import 'package:drift/drift.dart';

class Todos extends Table {
  IntColumn get id => integer().autoIncrement()();
  TextColumn get title => text().withLength(min: 1, max: 255)();
  BoolColumn get done => boolean().withDefault(const Constant(false))();
  DateTimeColumn get dueDate => dateTime().nullable()();
}

Create a database class that wires the tables and exposes high-level APIs. Use DAOs to group related queries for reuse and testability.

@DriftDatabase(tables: [Todos])
class AppDatabase extends _$AppDatabase {
  AppDatabase(QueryExecutor e) : super(e);
  @override
  int get schemaVersion => 1;

  Stream<List<Todo>> watchAllTodos() => select(todos).watch();
  Future<int> insertTodo(Insertable<Todo> todo) => into(todos).insert(todo);
}

Keep DAOs small and single-responsibility: CRUD, filtered queries, and analytic queries (counts, aggregates). This makes unit testing straightforward because DAOs can be tested against an in-memory database.

Querying And Migrations

Drift supports both fluent DSL queries and raw SQL. Use the DSL for common operations to preserve type-safety and move to customSelect when you need complex SQL. Streams returned by .watch() automatically emit on change, which integrates directly with Flutter widgets via StreamBuilder, Provider, or state management libraries.

Migrations are handled through schemaVersion and migration strategies. When you bump schemaVersion, implement migration logic in migration.dart or override migration getter on the database.

Typical pattern:

  • schemaVersion increments when you change tables.

  • Provide onUpgrade to run ALTER TABLEs, create new tables, and migrate data.

  • For destructive operations, prefer adding new columns and backfills to avoid data loss.

Example migration sketch:

  • Add a new column with ALTER TABLE (or create a new table and copy rows), then update existing rows with default values.

  • Run queries within a single transaction to maintain consistency.

Testing migrations locally before releasing is critical: run migration scripts against a copy of production data or a realistic dataset.

Performance tips:

  • Use indexes for frequently filtered columns.

  • Avoid N+1 queries by composing joins or batch-fetching related rows.

  • Use generated SQL via Drift to keep query plans stable and inspect SQL when tuning.

Vibe Studio

Vibe Studio, powered by Steve’s advanced AI agents, is a revolutionary no-code, conversational platform that empowers users to quickly and efficiently create full-stack Flutter applications integrated seamlessly with Firebase backend services. Ideal for solo founders, startups, and agile engineering teams, Vibe Studio allows users to visually manage and deploy Flutter apps, greatly accelerating the development process. The intuitive conversational interface simplifies complex development tasks, making app creation accessible even for non-coders.

Conclusion

Drift is a pragmatic choice for Flutter mobile development when you need robust local persistence with SQL power and Dart type-safety. The workflow—define tables, generate code, write DAOs, and run migrations—scales from small caches to complex offline-capable apps. Start by integrating Drift with a single feature, expose reactive streams to your UI, and expand to more sophisticated schema changes with controlled migrations. With Drift, you get the performance and flexibility of SQL plus a predictable, testable Dart API that fits naturally into Flutter apps.

Introduction

Local persistence is a must for many Flutter apps: caching API responses, offline-first flows, or storing user data. Drift (formerly Moor) is a typed, reactive persistence library for Flutter and Dart that combines the familiarity of SQL with generated, type-safe Dart APIs. This tutorial shows how to integrate Drift into a Flutter mobile development workflow, covering setup, schema design, DAOs, queries, and migration strategy with concise, practical examples.

Why Choose Drift

Drift blends raw SQL expressiveness with Dart-level safety. Key benefits for mobile development in Flutter:

  • Type-safe tables and queries generated at build time reduce runtime errors.

  • Reactive API (Streams) makes it easy to reflect DB changes in the UI with Provider, Riverpod, or Bloc.

  • Support for both native and sqflite backends enables consistent code across Android, iOS, and desktop.

  • Built-in migration hooks and schemaVersion simplify upgrades.

Drift is especially useful when you want SQL's power (complex joins, indexes) without writing error-prone boilerplate for mapping rows to Dart objects.

Setting Up Drift

Add dependencies to pubspec.yaml for a Flutter app using the native sqlite implementation or sqflite if you prefer:

dependencies:

  • drift: ^2.0.0

  • path_provider: ^2.0.0

  • sqlite3_flutter_libs: ^0.5.0

dev_dependencies:

  • drift_dev: ^2.0.0

  • build_runner: ^2.0.0

Use path_provider to locate an app-specific directory for the database file. Configure a QueryExecutor in your database constructor. Running flutter pub run build_runner build generates the supporting code.

Defining Tables And DAOs

Define tables by extending Table. Drift generates companion classes and typed entities. Keep models focused and use DAO classes for encapsulated query logic.

Example table definition:

import 'package:drift/drift.dart';

class Todos extends Table {
  IntColumn get id => integer().autoIncrement()();
  TextColumn get title => text().withLength(min: 1, max: 255)();
  BoolColumn get done => boolean().withDefault(const Constant(false))();
  DateTimeColumn get dueDate => dateTime().nullable()();
}

Create a database class that wires the tables and exposes high-level APIs. Use DAOs to group related queries for reuse and testability.

@DriftDatabase(tables: [Todos])
class AppDatabase extends _$AppDatabase {
  AppDatabase(QueryExecutor e) : super(e);
  @override
  int get schemaVersion => 1;

  Stream<List<Todo>> watchAllTodos() => select(todos).watch();
  Future<int> insertTodo(Insertable<Todo> todo) => into(todos).insert(todo);
}

Keep DAOs small and single-responsibility: CRUD, filtered queries, and analytic queries (counts, aggregates). This makes unit testing straightforward because DAOs can be tested against an in-memory database.

Querying And Migrations

Drift supports both fluent DSL queries and raw SQL. Use the DSL for common operations to preserve type-safety and move to customSelect when you need complex SQL. Streams returned by .watch() automatically emit on change, which integrates directly with Flutter widgets via StreamBuilder, Provider, or state management libraries.

Migrations are handled through schemaVersion and migration strategies. When you bump schemaVersion, implement migration logic in migration.dart or override migration getter on the database.

Typical pattern:

  • schemaVersion increments when you change tables.

  • Provide onUpgrade to run ALTER TABLEs, create new tables, and migrate data.

  • For destructive operations, prefer adding new columns and backfills to avoid data loss.

Example migration sketch:

  • Add a new column with ALTER TABLE (or create a new table and copy rows), then update existing rows with default values.

  • Run queries within a single transaction to maintain consistency.

Testing migrations locally before releasing is critical: run migration scripts against a copy of production data or a realistic dataset.

Performance tips:

  • Use indexes for frequently filtered columns.

  • Avoid N+1 queries by composing joins or batch-fetching related rows.

  • Use generated SQL via Drift to keep query plans stable and inspect SQL when tuning.

Vibe Studio

Vibe Studio, powered by Steve’s advanced AI agents, is a revolutionary no-code, conversational platform that empowers users to quickly and efficiently create full-stack Flutter applications integrated seamlessly with Firebase backend services. Ideal for solo founders, startups, and agile engineering teams, Vibe Studio allows users to visually manage and deploy Flutter apps, greatly accelerating the development process. The intuitive conversational interface simplifies complex development tasks, making app creation accessible even for non-coders.

Conclusion

Drift is a pragmatic choice for Flutter mobile development when you need robust local persistence with SQL power and Dart type-safety. The workflow—define tables, generate code, write DAOs, and run migrations—scales from small caches to complex offline-capable apps. Start by integrating Drift with a single feature, expose reactive streams to your UI, and expand to more sophisticated schema changes with controlled migrations. With Drift, you get the performance and flexibility of SQL plus a predictable, testable Dart API that fits naturally into Flutter apps.

Build Flutter Apps Faster with Vibe Studio

Build Flutter Apps Faster with Vibe Studio

Build Flutter Apps Faster with Vibe Studio

Build Flutter Apps Faster with Vibe Studio

Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.

Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.

Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.

Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.

Other Insights

Other Insights

Other Insights

Other Insights

Join a growing community of builders today

Join a growing community of builders today

Join a growing community of builders today

Join a growing community of builders today

Join a growing community of builders today

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025