Mọi bài "database Flutter tốt nhất" đều benchmark tốc độ insert. Gần như không ai hỏi câu quyết định kiến trúc thực sự: liệu nó có còn được maintain khi bạn ship v2?
Câu hỏi đó quan trọng hơn throughput thuần túy, bởi vì ba local database mà cộng đồng Flutter từng yêu thích — Hive, Isar, và Realm — hiện nay đều thực tế không còn được hỗ trợ. Hive và Isar bị tác giả gốc bỏ rơi; Realm's sync bị MongoDB khai tử. Các team đã đặt cược vào chúng đang phải viết migration code thay vì viết tính năng. Tốc độ và tính năng đưa chúng vào; maintenance đang đẩy chúng ra.
Vì vậy, hướng dẫn này xếp hạng các lựa chọn theo một trục khác. Performance là điều kiện tối thiểu; tất cả đều đủ nhanh cho phần lớn các app. Điều phân biệt chúng trong năm 2026 là maintenance health, độ phủ nền tảng, và chi phí khi chọn sai hai năm sau.

Bối cảnh: viết dựa trên Flutter 3.44 và Dart 3.12 (cả hai phát hành tháng 5/2026).
---
TL;DR
SharedPreferences hoặc flutter_secure_storage là đủ.---
Tại sao maintenance mới là benchmark thực sự
Một local database là một trong những quyết định khó thay đổi nhất trong codebase của bạn. Schema, query, migration, reactive layer — tất cả đều couple chặt chẽ với thứ bạn đã chọn. Thay thế nó sau này đồng nghĩa với data migration trên các thiết bị đã trong tay người dùng, và đó là một trong những thứ rủi ro nhất bạn có thể ship.
Đó chính là toàn bộ lập luận. Một database nhanh hơn 5x nhưng không được maintain là canh bạc tệ hơn so với một cái "đủ nhanh" và được phát triển tích cực, bởi vì chi phí của cái không được maintain sẽ xuất hiện muộn hơn, lớn hơn, và vào thời điểm tệ nhất có thể — khi một Dart SDK mới, một Android NDK mới, hay một nền tảng mới làm hỏng package và không ai ở đó để sửa.
Vậy trước khi xem benchmark, hãy hỏi ba câu về bất kỳ ứng viên nào:
1. Tác giả gốc hoặc một team uy tín có còn đang ship release không?
2. Nó có theo kịp các Dart/Flutter SDK và platform requirement mới không?
3. Nếu nó chết ngày mai, chi phí để thoát ra là bao nhiêu?
Bây giờ là các ứng viên, xếp theo mức độ tự tin tôi sẽ bắt đầu một production app mới trên chúng hôm nay.
---
Drift — lựa chọn mặc định
Drift (trước đây là Moor) là một reactive persistence library xây trên SQLite. Nó không phải là một database engine; nó là một ORM type-safe và query layer trên database embedded được battle-tested nhất hiện có.
Maintenance: healthy. Được phát triển tích cực bởi Simon Binder với các release đều đặn trong năm 2026, và hiện được tài trợ bởi Stream và PowerSync. SQLite bên dưới có nghĩa là storage format sẽ tồn tại lâu hơn tất cả chúng ta.
Tại sao nó là lựa chọn mặc định:
drift_flutter đã thêm shareAcrossIsolates, cho phép nhiều isolate truy cập cùng một database mà không cần bạn tự dây port.Đánh đổi: Bạn phải tư duy theo SQL và table. Có bước codegen build_runner. Với nhu cầu key-value đơn giản thì nó nặng hơn cần thiết — nhưng đó không phải mục đích của nó.
Chọn Drift khi: bạn có relational data, cần migration có thể lý luận được, muốn reactive query, hoặc đang xây bất cứ thứ gì offline-first. Tức là hầu hết các app.
---
ObjectBox — lựa chọn NoSQL có sync sẵn
ObjectBox là một NoSQL object database nhanh với native Dart API. Điểm nổi bật của nó không phải là tốc độ — mà là engine Data Sync tích hợp sẵn.
Maintenance: healthy. Được hỗ trợ thương mại, với các release thường xuyên (5.3.2 stable, 6.0 đang preview vào giữa năm 2026) và hỗ trợ nền tảng hiện tại.
Tại sao nó nổi bật:
Đánh đổi:* NoSQL có nghĩa là không có SQL — relational reporting và ad-hoc analytical query yếu hơn. Nó là native dependency lớn hơn. Tính năng hấp dẫn nhất (Sync) ràng buộc bạn với model của ObjectBox. Và **schema migration đòi hỏi sự cẩn thận thực sự: ObjectBox theo dõi từng entity và property bằng một UID ổn định được lưu trong objectbox-model.json và objectbox.g.dart được sinh ra. Những file này là source-of-truth và phải được version-control và giữ đồng bộ — regenerate chúng cẩu thả (UID sai, file model bị ghi đè) và bạn có nguy cơ gây ra *destructive schema change trên data đã có trong tay người dùng. Không giống Drift, không có migration script SQL nào bạn có thể đọc, diff, và test từng bước; bạn đang tin tưởng các binding file sẽ nhất quán, đó là lý do tại sao các production setup gác chúng sau CI check.
Chọn ObjectBox khi: bạn muốn object persistence kèm device sync mà không cần tự xây sync layer, hoặc bạn cần vector search on-device.
---
sqflite — baseline thuần túy
Một wrapper mỏng, được maintain tốt xung quanh SQLite. Không ORM, không codegen, không reactive layer — chỉ SQL và Map<String, dynamic>.
Maintenance: healthy và ổn định. Đây là baseline lâu đời mà cộng đồng hay quay về.
Chọn sqflite khi: bạn muốn toàn quyền kiểm soát SQL, thoải mái tự map row, hoặc đang tự xây abstraction mỏng và không muốn quan điểm của ORM. Với hầu hết các team, Drift cho bạn độ tin cậy của sqflite cộng thêm type safety và reactivity, vậy nên chỉ chọn sqflite khi bạn có lý do cụ thể để tránh codegen.
---
Isar — nhanh, nhưng đừng bắt đầu ở đây
Isar là một NoSQL database cực nhanh, được viết bởi Simon Leier (cũng là tác giả của Hive). Trên giấy tờ nó rất đẹp: composite index, full-text search, multi-isolate mặc định, ACID, static typing.
Maintenance: đây là vấn đề. Tác giả gốc im lặng — khoảng trống dài giữa các commit, không có phản hồi trên các kênh của project — và v4 chính thức chưa bao giờ đạt được một release stable đáng tin cậy. Project tồn tại chủ yếu thông qua community fork isar-community.
Một community fork có thể ổn. Nhưng hãy hiểu bạn đang đăng ký gì: bạn đặt cược vào thời gian rảnh của các tình nguyện viên để theo dõi các thay đổi Dart SDK và platform breakage, và khoảnh khắc fork đó đình trệ, bạn sở hữu việc thoát ra. Với hobby project, có thể chấp nhận. Với thứ bạn sẽ maintain trong nhiều năm, rủi ro hiếm khi đáng đổi lấy tốc độ.
Chọn Isar khi: bạn đang prototype, tốc độ thực sự quan trọng cho workload cụ thể của bạn, và bạn đã có ý thức chấp nhận maintenance risk. Ngoài ra, đừng bắt đầu một production app mới ở đây.
---
Hive — câu chuyện tương tự
Hive là một key-value store nhẹ, pure-Dart. Pure Dart có nghĩa là nó chạy ở khắp nơi, kể cả web, với gần như không cần setup — đó chính xác là lý do nó trở nên phổ biến như vậy.
Maintenance: bị tác giả gốc bỏ rơi*, người đã công khai định vị Isar là người kế nhiệm. Rồi Isar cũng đình trệ. Một *Hive Community Edition (Hive CE) giờ đang tiếp tục duy trì nó.
Khi nào nó vẫn phù hợp: nhu cầu thực sự đơn giản — user settings, cached response nhỏ, flag. Nó chưa bao giờ được xây cho complex query, relationship, hay dataset lớn, vậy đừng đẩy nó đến đó.
Chọn Hive CE khi: bạn muốn key-value persistence đơn giản nhất có thể, bạn đã chấp nhận tư thế community-maintenance, và nhu cầu của bạn ở mức khiêm tốn. Cho bất cứ thứ gì vượt quá đó, giá trị so với SharedPreferences là mỏng và khoảng cách so với Drift là lớn.
---
Realm — câu chuyện cảnh báo thứ ba
Realm xứng đáng có phần riêng, vì nó là minh họa rõ ràng nhất cho luận điểm của toàn bộ hướng dẫn này. Đây là một mobile NoSQL database có năng lực mà tính năng tiêu đề là Atlas Device Sync — tự động đồng bộ client-to-cloud được MongoDB hỗ trợ.
Maintenance: MongoDB đã rút phích. Việc khai tử Atlas Device Sync và Realm SDK được thông báo vào tháng 9 năm 2024, với sync đạt end-of-life vào ngày 30 tháng 9 năm 2025. Database on-device vẫn tồn tại như một open-source project — các release realm-dart gần đây thậm chí đã xóa chức năng sync và vá compatibility cho các phiên bản Flutter mới hơn — nhưng nó làm vậy mà không có sự hỗ trợ ongoing của MongoDB. Sync engine, phần mà hầu hết các team thực sự chọn Realm vì nó, đã biến mất và chưa bao giờ được open-source.
Đây là pattern lần thứ ba: các team couple chặt chẽ với Realm Device Sync đang phải migrate sang sync layer bên thứ ba hoặc tự xây dưới một deadline cứng. Nếu bạn có app Realm hiện tại, hãy decouple các Realm call và lên kế hoạch thoát. Đừng bắt đầu project mới trên nó.
---
Phần còn lại, ngắn gọn
---
Bạn có thể không cần database
Trước khi chọn bất kỳ thứ gì ở trên, hãy kiểm tra xem data của bạn có thực sự cần không:
SharedPreferences — data key-value nhỏ: settings, flag, tab đã mở gần nhất. (Chú ý async API hiện đại.)flutter_secure_storage — bất cứ thứ gì nhạy cảm: token, credential. Đừng đặt JWT vào plain key-value store.Một database xứng đáng với sự phức tạp của nó khi bạn có structured data, relationship, query, hoặc yêu cầu offline-first sync. Dưới ngưỡng đó, nó là overhead.
---
Tổng quan nhanh
| Lựa chọn | Model | Maintenance (2026) | Web | Sync tích hợp | Tốt nhất cho |
|---|---|---|---|---|---|
| Drift | SQL / ORM | Healthy | ✅ | ❌ | Hầu hết app; relational + offline-first |
| ObjectBox | NoSQL objects | Healthy (commercial) | ❌ | ✅ | Synced NoSQL, on-device AI |
| sqflite | SQL (raw) | Healthy | ❌ | ❌ | Toàn quyền SQL, không ORM |
| Isar | NoSQL | ⚠️ community fork | ⚠️ | ❌ | Prototype; chấp nhận rủi ro |
| Hive CE | Key-value | ⚠️ community edition | ✅ | ❌ | Key-value đơn giản |
| Realm | NoSQL | ⚠️ không có vendor support; sync EOL | ❌ | ❌ (đã xóa) | Legacy; migrate ra |
| SharedPreferences | Key-value | Healthy (first-party) | ✅ | ❌ | Settings, flag (không phải DB) |
---
Cách chọn, qua một lần duyệt
1. Chỉ là settings/flag/token? → SharedPreferences / flutter_secure_storage. Dừng ở đây.
2. Có relational data, migration, hoặc cần reactive query?* → *Drift.
3. Cần cross-device sync và muốn không tự xây sync layer?* → *ObjectBox.
4. Muốn raw SQL không có ORM?* → *sqflite.
5. Prototype mà tốc độ là ưu tiên và bạn chấp nhận maintenance risk? → Isar (mắt mở).
Đối với đại đa số production app, bạn sẽ đến với Drift — và đó là nơi đúng đắn để đến.
---
Ví dụ thực tế: một starter template được xây dựng trên luận điểm này
Những đánh đổi ở trên không phải là trừu tượng. flutter-starter-template — một Flutter boilerplate open-source, production-ready của Luci Studio — là ví dụ cụ thể của các quyết định trong hướng dẫn này.
Nó được xây offline-first*, và yêu cầu đó đã thúc đẩy lựa chọn database hiện tại của nó. Write commit vào local *ObjectBox store trước, UI cập nhật ngay lập tức, và network được reconcile ở background thông qua một rev_sync engine có thể tái sử dụng — revision-based delta sync, tombstone, và optimistic-concurrency conflict detection — với một Go backend companion. Đó chính xác là trường hợp "chọn ObjectBox khi bạn muốn fast object persistence" từ phần ObjectBox, được hiện thực hóa: nó dựa vào tốc độ của ObjectBox cho write path local-first trong khi tự sở hữu sync layer.
Điều làm nó trở thành minh họa hữu ích cho bài học khác* của hướng dẫn này — rằng database là quyết định sticky đáng giữ cho có thể hoán đổi — là roadmap. ObjectBox là mặc định hiện tại, được chọn để tối ưu performance, nhưng template đang hướng tới việc cung cấp Drift** và *SQLite (qua sqflite) như các lựa chọn storage thay thế. Điều này map rõ ràng lên ba lựa chọn ở đây: ObjectBox cho fast object store, Drift là relational default type-safe, và raw SQLite cho các team muốn toàn quyền SQL.
Kiến trúc đã làm điều này khả thi. ObjectBox entity và binding được tập trung trong một database package duy nhất phía sau một Store wrapper; các tính năng phụ thuộc vào package đó thay vì phụ thuộc trực tiếp vào objectbox, và mọi tính năng truy cập data thông qua Clean Architecture repository interface. Đó là sự encapsulation mà hướng dẫn này liên tục nhấn mạnh — phụ thuộc vào abstraction của chính bạn, không phải raw dependency — và đó là thứ biến việc thêm Drift/SQLite thành một option bổ sung thay vì một cuộc viết lại.
Nó cũng đối mặt trực tiếp với migration risk ở trên. Template cố ý version-control objectbox-model.json và lib/objectbox.g.dart — hai file chứa stable entity/property UID — thay vì coi chúng là throwaway codegen, và một CI step fail build nếu thay đổi @Entity không đi kèm với binding được regenerate. Đó chính xác là kỷ luật mà migration model của ObjectBox đòi hỏi, và nó cũng là lập luận cho swappable persistence boundary: khi phần đau đầu của một database là schema evolution on-device, giữ nó sau repository interface là thứ cho phép bạn offer Drift hoặc SQLite sau này mà không cần đặt cược data người dùng vào một lần regenerate đúng.
Nếu bạn muốn lập luận maintenance-first được thể hiện bằng code thay vì văn xuôi, đây là một tham khảo hợp lý: real offline-first sync, persistence boundary thân thiện với việc thoát, và kế hoạch có chủ đích để cho developer lựa chọn ObjectBox / Drift / SQLite mà hướng dẫn này đã vạch ra.
---
Kết luận
Câu chuyện database Flutter trong những năm gần đây là một câu chuyện cảnh báo: cộng đồng hai lần bị quyến rũ bởi lựa chọn nhanh nhất, và hai lần lựa chọn nhanh nhất ngừng được maintain. Bài học không phải là "tốc độ không quan trọng." Mà là maintenance là một tính năng — có thể là tính năng quan trọng nhất — và nó không bao giờ xuất hiện trong biểu đồ benchmark.
Trong năm 2026, câu trả lời nhàm chán là câu trả lời đúng đắn. Bắt đầu với Drift. Chọn ObjectBox khi bạn cụ thể cần sync. Coi Isar và Hive gốc là legacy bạn migrate ra*, không phải nền tảng bạn xây *trên.
---
Happy coding : )
Loading…