If you’re building a Flutter app that needs offline data persistence, SQLite is one of the best lightweight solutions available. This guide is tailored for Flutter beginners who want to integrate SQLite step-by-step using sqflite
, the most popular Flutter plugin for working with SQLite databases.
SQLite is a relational database that stores data in tables, rows, and columns. It’s embedded within your Flutter application and doesn’t require any server or setup, making it perfect for offline-first mobile apps.

Step-by-Step Implementation of SQLite in Flutter
Let’s build a simple CRUD (Create, Read, Update, Delete) app for managing notes.
Step 1: Add Dependencies
Open your pubspec.yaml
and add the following:
dependencies: flutter: sdk: flutter sqflite: ^2.3.0 path: ^1.8.3
Then run:
flutter pub get
Step 2: Create Model Class
// file: models/note.dart class Note { final int? id; final String title; final String content; Note({this.id, required this.title, required this.content}); Map<String, dynamic> toMap() { return { 'id': id, 'title': title, 'content': content, }; } factory Note.fromMap(Map<String, dynamic> map) { return Note( id: map['id'], title: map['title'], content: map['content'], ); } }
Step 3: Create Database Helper Class
// file: db/database_helper.dart import 'package:sqflite/sqflite.dart'; import 'package:path/path.dart'; import '../models/note.dart'; class DatabaseHelper { static final DatabaseHelper instance = DatabaseHelper._init(); static Database? _database; DatabaseHelper._init(); Future<Database> get database async { if (_database != null) return _database!; _database = await _initDB('notes.db'); return _database!; } Future<Database> _initDB(String filePath) async { final dbPath = await getDatabasesPath(); final path = join(dbPath, filePath); return await openDatabase(path, version: 1, onCreate: _createDB); } Future _createDB(Database db, int version) async { await db.execute(''' CREATE TABLE notes ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, content TEXT NOT NULL ) '''); } Future<int> insertNote(Note note) async { final db = await instance.database; return await db.insert('notes', note.toMap()); } Future<List<Note>> getNotes() async { final db = await instance.database; final result = await db.query('notes'); return result.map((map) => Note.fromMap(map)).toList(); } Future<int> updateNote(Note note) async { final db = await instance.database; return await db.update( 'notes', note.toMap(), where: 'id = ?', whereArgs: [note.id], ); } Future<int> deleteNote(int id) async { final db = await instance.database; return await db.delete( 'notes', where: 'id = ?', whereArgs: [id], ); } Future close() async { final db = await instance.database; db.close(); } }
Step 4: Use in UI
// file: main.dart import 'package:flutter/material.dart'; import 'db/database_helper.dart'; import 'models/note.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'SQLite Demo', home: NotePage(), ); } } class NotePage extends StatefulWidget { @override _NotePageState createState() => _NotePageState(); } class _NotePageState extends State<NotePage> { final _titleController = TextEditingController(); final _contentController = TextEditingController(); List<Note> _notes = []; @override void initState() { super.initState(); _refreshNotes(); } Future<void> _refreshNotes() async { final data = await DatabaseHelper.instance.getNotes(); setState(() { _notes = data; }); } Future<void> _addNote() async { final note = Note(title: _titleController.text, content: _contentController.text); await DatabaseHelper.instance.insertNote(note); _titleController.clear(); _contentController.clear(); _refreshNotes(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("SQLite Note App")), body: Column( children: [ Padding( padding: EdgeInsets.all(8), child: Column( children: [ TextField(controller: _titleController, decoration: InputDecoration(labelText: "Title")), TextField(controller: _contentController, decoration: InputDecoration(labelText: "Content")), ElevatedButton(onPressed: _addNote, child: Text("Add Note")), ], ), ), Expanded( child: ListView.builder( itemCount: _notes.length, itemBuilder: (context, index) { final note = _notes[index]; return ListTile( title: Text(note.title), subtitle: Text(note.content), ); }, ), ) ], ), ); } }
External Reference
For more advanced database features in Flutter, you can refer to Flutter SQLite Guide on RayWenderlich.