Local Data Persistence
Choose between sqflite and Hive for offline-first data caching in Flutter.
Overview
Most Flutter apps need to persist data locally — whether it's user settings, cached API responses, bookmarks, or offline-first content. Choosing the right storage solution depends on your data's complexity, how often it changes, and whether you need to query it with complex filters.
Flutter offers several local storage options depending on your data complexity:
| Option | Type | Best For |
|---|---|---|
SharedPreferences | Key-value | Simple settings, flags |
sqflite | Relational SQL | Complex queries, relations |
Hive | NoSQL key-value | Fast read/write, simple models |
Isar | NoSQL (typed) | High-performance queries |
sqflite (SQLite)
A relational database with full SQL support. Great for structured data with complex queries:
bookmark_db.dart
import 'package:sqflite/sqflite.dart';
class BookmarkDatabase {
static Database? _db;
static Future<Database> get database async {
_db ??= await openDatabase(
'bookmarks.db',
version: 1,
onCreate: (db, version) async {
await db.execute('''
CREATE TABLE bookmarks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
url TEXT NOT NULL,
category TEXT DEFAULT 'general',
created_at TEXT DEFAULT CURRENT_TIMESTAMP
)
''');
},
);
return _db!;
}
static Future<int> insert(Map<String, dynamic> bookmark) async {
var db = await database;
return db.insert('bookmarks', bookmark);
}
static Future<List<Map<String, dynamic>>> getByCategory(String category) async {
var db = await database;
return db.query('bookmarks',
where: 'category = ?',
whereArgs: [category],
orderBy: 'created_at DESC',
);
}
static Future<int> delete(int id) async {
var db = await database;
return db.delete('bookmarks', where: 'id = ?', whereArgs: [id]);
}
}
Hive (NoSQL)
A lightweight, extremely fast key-value database with no native dependencies:
hive_bookmark.dart
import 'package:hive/hive.dart';
@HiveType(typeId: 0)
class Bookmark extends HiveObject {
@HiveField(0)
late String title;
@HiveField(1)
late String url;
@HiveField(2)
String category = 'general';
@HiveField(3)
DateTime createdAt = DateTime.now();
Map<String, dynamic> toJson() => {
'title': title, 'url': url,
'category': category, 'createdAt': createdAt.toIso8601String(),
};
}
// Initialize and use
void initHive() async {
await Hive.initFlutter();
Hive.registerAdapter(BookmarkAdapter());
await Hive.openBox<Bookmark>('bookmarks');
}
// CRUD operations
var box = Hive.box<Bookmark>('bookmarks');
await box.add(bookmark); // Insert
var all = box.values.toList(); // Read all
await box.deleteAt(0); // Delete first
Detailed Comparison
| Feature | sqflite | Hive |
|---|---|---|
| Storage Type | SQLite relational DB | NoSQL key-value store |
| Query Language | SQL | Method chaining |
| Performance | Good for complex queries | Blazing fast for simple reads/writes |
| Data Size | No practical limit | Best for < 100MB |
| Schema | Defined via CREATE TABLE | Adaptive (no migrations needed) |
| Best For | Relational data, complex joins | Settings, caches, simple lists |
💡 Decision Framework
- Use Hive for: user settings, app preferences, simple caching, offline bookmarks
- Use sqflite for: chat messages, transaction logs, user-generated content, anything with relationships
- Use both for: Hive for fast access + sqflite as the source of truth
sqflite vs Hive
| Feature | sqflite | Hive |
|---|---|---|
| Data Model | Relational (tables) | NoSQL (boxes) |
| Query Language | SQL | API methods |
| Performance | Good for complex queries | Excellent for simple reads |
| Setup | Moderate (schema) | Simple (adapters) |
| Best For | Relations, joins, filtering | Fast caching, key-value |
Real-World Example: Offline Bookmarking Cache
bookmark_service.dart
class BookmarkService {
final _box = Hive.box<Bookmark>('bookmarks');
// Add bookmark
void addBookmark(String title, String url, {String category = 'general'}) {
var bookmark = Bookmark()
..title = title
..url = url
..category = category;
_box.add(bookmark);
}
// Search bookmarks
List<Bookmark> searchBookmarks(String query) {
return _box.values
.where((b) => b.title.toLowerCase().contains(query.toLowerCase()))
.toList();
}
// Get by category
List<Bookmark> getByCategory(String category) {
return _box.values.where((b) => b.category == category).toList();
}
// Delete
void removeBookmark(int index) {
_box.deleteAt(index);
}
// Export to JSON for cloud sync
List<Map<String, dynamic>> exportAll() {
return _box.values.map((b) => b.toJson()).toList();
}
}
Summary
SharedPreferencesfor simple key-value settingssqflitefor relational data with complex queriesHivefor fast, lightweight NoSQL storage- Use Hive as a cache layer, sync to cloud when online
🚀 Next Step Continue to API Integration & JSON.