Database guide
Expo and React Native Database Best Practices
The right database design for an Expo app starts with data ownership and connectivity requirements, not with a library name. Production apps need a clear split between local device data, cached server data and the authoritative backend.
Choose storage by data ownership
Use SecureStore for small secrets, AsyncStorage for non-sensitive preferences, SQLite for structured local or offline data, and a hosted database when data must be shared across users or devices. These tools solve different problems and often coexist in the same app.
Treat the backend as the source of truth for shared product data. A local cache should improve speed and offline behavior without silently becoming a second authoritative database.
Design the schema before the screens
Use stable identifiers, explicit ownership columns and timestamps that support synchronization. Add database constraints for rules that must remain true regardless of which client writes the data.
Index columns used for filtering, joins and access-control policies, but confirm improvements with real query plans. Every index speeds some reads while adding storage and write cost.
- Use migrations for every production schema change
- Keep development, staging and production schemas reproducible
- Make destructive changes backward-compatible before removing old fields
- Test both forward migration and recovery procedures
Enforce security in the backend
Client-side checks improve the interface but do not protect data. Enforce authorization in API endpoints or database policies and default to denying access until a rule explicitly allows it.
With Supabase, enable Row Level Security on exposed tables and test policies for anonymous users, signed-in owners and non-owners. Never ship service-role keys or privileged database credentials inside a mobile bundle.
Make offline synchronization explicit
Offline-first behavior requires an operation queue, retry policy, idempotent writes and a documented conflict strategy. Last-write-wins can be acceptable for preferences but dangerous for inventory, money or collaborative records.
Store synchronization metadata separately from product data and expose connection, pending and failed states in the interface. Users should know when a change is only on their device.
Protect reliability and performance
Paginate large collections, select only required fields and avoid one network request per rendered row. Use cache invalidation deliberately and collect slow-query evidence before adding complexity.
Backups are useful only when restoration is tested. Define retention, recovery objectives and monitoring for failed migrations, policy errors and unusual query volume before the app depends on production data.
Related technical documentation
Continue with the implementation details in these Expo Boilerplate docs:
Where Expo Boilerplate fits
Expo Boilerplate is built for developers who want a production-ready React Native foundation without spending the first weeks of a project wiring common infrastructure. It gives you a practical starting point for app features, monetization, analytics, notifications and release preparation.
FAQ
What database should I use with Expo?
Use SQLite for structured local data and offline workflows, or a backend such as Supabase when data must sync across users and devices. AsyncStorage is appropriate for small non-sensitive preferences, not relational product data.
Is AsyncStorage secure for authentication tokens?
AsyncStorage is not designed as encrypted secret storage. Use Expo SecureStore or the secure mechanism recommended by your authentication provider for sensitive tokens.
Does an Expo app need database migrations?
Yes when a local or remote schema changes after release. Versioned migrations make changes reproducible and let older app versions coexist safely while users upgrade.