Hive vs Isar vs SQLite: Choosing Local Storage for Offline-First Flutter Apps

Words
476
Reading
3 min
Listen
Play
21d

If you're building offline-first in Flutter, sooner or later you have to pick a local storage engine. I've used all three of these in production apps, and each one has a real trade-off — here's how I'd actually decide between them.

Quick overview

HiveIsarSQLite (sqflite)
TypeNoSQL key-valueNoSQL object databaseRelational (SQL)
Query PowerBasicStrong (indexes, filters, sorting)Full SQL
Setup ComplexityVery LowLow-mediumMedium
Speed (simple reads/writes)Very FastVery FastFast, but slower for simple ops
Best forSimple key-value data, settings, small datasetsStructured objects with queries, medium-large datasetsComplex relational data, joins, existing SQL knowledge

Hive — when simplicity wins

Hive (the Flutter package, not the blockchain — easy to confuse if you're active on both like I am) is essentially a fast, lightweight key-value store. No query engine, no schema migrations to worry about. It shines when your data doesn't need complex querying — user preferences, cached API responses, simple lists.

dart var box = await Hive.openBox('tasks'); box.put('task1', Task(title: 'Buy milk', done: false)); var task = box.get('task1');

The catch: once your data model gets more relational (tasks that belong to projects that belong to users, with filtering across all of it), you'll feel Hive's limits fast.

Isar — the middle ground that often wins

Isar gives you Hive-like speed with actual query capabilities: indexes, filters, sorting, even full-text search. For most offline-first apps I build now, this is my default. It handles the "I need structured data AND I need to query it" problem without the overhead of full SQL.

dart
final tasks = await isar.tasks
.filter()
.doneEqualTo(false)
.sortByCreatedAtDesc()
.findAll();

The trade-off is a slightly steeper setup (code generation via build_runner) and it's a newer project than SQLite, so the ecosystem and community answers are thinner if you hit an edge case.

SQLite — when you actually need relational data

If your data genuinely has complex relationships — multiple tables, joins, aggregate queries — SQLite via sqflite is still the most battle-tested option. It's not Flutter-specific, so any SQL knowledge you already have transfers directly, and debugging tools are mature.

dart
final db = await openDatabase('app.db');
final tasks = await db.rawQuery(
'SELECT * FROM tasks WHERE done = 0 ORDER BY created_at DESC'
);

The cost is more boilerplate — you're writing migrations, managing schema versions, and SQL strings are less type-safe than Isar's query builder unless you add an ORM layer on top.

My actual decision rule

  1. Small, flat data (settings, cache, single-entity lists) → Hive

  2. Structured data that needs filtering/sorting but isn't deeply relational → Isar

  3. Genuinely relational data, or you're porting from a backend that's already SQL → SQLite

I default to Isar for most new offline-first apps at this point — it hits the sweet spot between Hive's simplicity and SQLite's query power without dragging in the full weight of a relational database.

What's your default pick, and has it changed as your apps got more complex? Curious if others have landed somewhere different.

Hive vs Isar vs SQLite: Choosing Local Storage for Offline-First Fl... | Ecency