Back to Blog
FlutterDatabase

Toàn cảnh local database cho Flutter năm 2026

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.

d7ac5adf-8c08-474f-845a-f2d71867fd58.png

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

  • Mặc định chọn Drift. SQL-backed, type-safe, được maintain tích cực, reactive, tích hợp isolate threading, chạy được mọi nơi kể cả web. Đây là lựa chọn an toàn, nhàm chán, đúng đắn cho hầu hết các app.
  • Chọn ObjectBox nếu bạn muốn một NoSQL object store nhanh có sẵn engine Data Sync, để không phải tự tay xây sync cho thiết bị.
  • Dùng sqflite khi bạn muốn kiểm soát SQLite trực tiếp và không cần ORM.
  • Tránh Isar và Hive gốc cho các project mới. Cả hai đã dừng phát triển. Community fork có tồn tại, nhưng một fork là gánh nặng bạn tự gánh, không phải tính năng bạn được nhận.
  • Với settings/cache, bạn không cần databaseSharedPreferences 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:

  • Compile-time safety. Các table và query của bạn sinh ra Dart type-safe. Lỗi bị bắt lúc build time với lint mô tả rõ ràng, không phải lúc runtime trên điện thoại người dùng.
  • Reactive theo thiết kế. Bất kỳ query nào cũng trở thành một stream tự cập nhật, kể cả các join phức tạp qua nhiều table — nền tảng cho một UI offline-first gọn gàng.
  • Threading tích hợp sẵn. Drift là thư viện persistence Flutter lớn duy nhất có hỗ trợ isolate đầy đủ. Package 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.
  • Migration đáng tin cậy. Schema versioning, migration tooling, và test helper xác nhận migration không phụ thuộc vào phần còn lại của stack.
  • Cross-platform thực sự. Android, iOS, macOS, Windows, Linux, và web.
  • Đá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:

  • Data Sync tích hợp sẵn. Giữ data nhất quán giữa các thiết bị và ranh giới online/offline là phần khó nhất của offline-first. ObjectBox ship một giải pháp thay vì bắt bạn tự xây sync queue và xử lý conflict từ đầu.
  • Ergonomics object-first. Bạn persist Dart object trực tiếp; không SQL, không manual mapping.
  • Vector search on-device. Hữu ích nếu bạn làm on-device AI / RAG / similarity search — đây là niche, nhưng là niche có thật trong năm 2026.
  • Rất nhanh trên các dataset lớn, có index.
  • Đá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.jsonobjectbox.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

  • Floor — thêm một SQLite ORM (annotation + DAO), bề mặt nhỏ hơn Drift một cách có chủ đích. Ổn, nhưng hệ sinh thái yên tĩnh hơn và ít momentum hơn.
  • Sembast — pure-Dart NoSQL document store. Ổn cho các app vừa muốn linh hoạt mà không cần SQL; cộng đồng nhỏ hơn.
  • Không cái nào trong số này là sai, nhưng trong năm 2026 không cái nào đánh bại "Drift cho relational, ObjectBox cho synced-NoSQL" cho một production app mới.

    ---

    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.
  • In-memory — state dẫn xuất hoặc chỉ tồn tại trong session không cần chạm đĩa.
  • 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ọnModelMaintenance (2026)WebSync tích hợpTốt nhất cho
    DriftSQL / ORMHealthyHầu hết app; relational + offline-first
    ObjectBoxNoSQL objectsHealthy (commercial)Synced NoSQL, on-device AI
    sqfliteSQL (raw)HealthyToàn quyền SQL, không ORM
    IsarNoSQL⚠️ community fork⚠️Prototype; chấp nhận rủi ro
    Hive CEKey-value⚠️ community editionKey-value đơn giản
    RealmNoSQL⚠️ không có vendor support; sync EOL❌ (đã xóa)Legacy; migrate ra
    SharedPreferencesKey-valueHealthy (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.jsonlib/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 : )

    Enjoyed this read?

    0likes

    Found this helpful?

    Support my work.

    If this post saved you time or taught you something, you can buy me a coffee. Every bit keeps me writing and shipping.

    Support my work.

    If this post saved you time or taught you something, you can buy me a coffee. Every bit keeps me writing and shipping.

    TP BankVietnam

    Scan with any VN banking app

    Show QRHide QR
    Scan to support via Vietnamese bank (VietQR)Scan to pay
    PayPalGlobal

    Pay with your PayPal account

    Support via PayPal
    Show QRHide QR
    Scan to support via PayPalScan to pay
    GitHubGlobal

    Visa / Mastercard · one-time or monthly

    Sponsor on GitHub
    Show QRHide QR
    Scan to sponsor on GitHubScan to pay
    Comments

    Loading…

    END OF SHEET — LET'S BUILD

    Got a hard problem? Let's talk.