6 min • Dec 2, 2020
It's worth understanding the Firestore limitations and how to overcome them before you start building your next web or mobile application using native or cross-platform solutions like Flutter, React Native, or Kotlin. Read hints on how to use Firestore effectively and not hurt yourself in the process.
5 min • Aug 6, 2020
Whiteboards make it easier to collaborate on designs, teach people new concepts, and express ideas. In this blog post, we explore a possible implementation of a whiteboard using Flutter to create a mobile application and Firestore database as backend.
12 min • Jul 27, 2023
Read about the LeanCode approach to Flutter architecture. We highlight some of the design decisions that should be made when developing a feature in mobile apps. This includes our approach to dependency injection, state management, widget lifecycle, and data fetching.
SQLite in Flutter is a lightweight, embedded relational database used to store structured data locally on a user's device. It allows Flutter apps to persist data in tables, query it using SQL, and work offline without any backend connection.
In Flutter, SQLite is most commonly accessed via the sqflite package on mobile platforms.
SQLite is one of the most reliable ways to handle complex local data in Flutter apps.
It works well for offline-first scenarios, cached API data, and structured datasets that require filtering or sorting. Compared to simple key–value storage, SQLite offers much more control and flexibility.
SQLite runs directly inside the application process and stores data in a local database file. Flutter communicates with it through platform-specific implementations on Android and iOS.
Developers define tables, write SQL queries as strings, and manually map database rows to Dart objects.
Important note: sqflite does not work on Flutter Web by default. Running it on Web usually results in a MissingPluginException. Web support requires extra setup or a different library.
SQLite is an excellent choice for Flutter apps that require structured, relational data storage on the device. It shines when your application relies on multiple entities with relationships, such as users, orders, or inventory items, and you need to query, sort, or join these records efficiently.
SQLite allows complex queries and indexing, which makes it suitable for apps that manage catalogs, offline caches, or transactional data.
Local persistence is another reason to choose SQLite. When network access is intermittent or unreliable, SQLite ensures that users can continue interacting with the app without losing data.
It also provides full control over schema, transactions, and indexing, which is essential for apps with data integrity requirements. Many production apps, such as note-taking apps, offline-first productivity tools, or personal finance trackers, rely on SQLite for its stability, reliability, and wide adoption across mobile platforms.
SQLite may be unnecessary if your app primarily stores simple key–value pairs or session flags, as a lighter solution like SharedPreferences or Hive is easier to set up and maintain.
It can also be overkill for applications targeting Flutter Web, where client-side SQLite support requires additional setup (WASM), and native web-friendly storage like IndexedDB is often more appropriate.
Additionally, if your goal is rapid prototyping or minimal boilerplate, raw SQLite can slow development due to schema definitions, migrations, and manual mapping between database tables and Dart objects.
Apps that benefit from automatic object mapping or ORM-like convenience may prefer solutions such as Drift (built on top of SQLite) or Isar, which provide type-safe APIs and reduce repetitive SQL code.
Using raw SQLite in projects with very simple storage needs or where fast iteration is critical may introduce unnecessary complexity.
Beginners often run into the same issues:
Depending on your needs, common alternatives include:
Hive for simple local storageIsar for fast queries with less boilerplateDrift for type-safe SQLite access with code generation