Expo sqlite adapter falling back to asyncstorage, but react-native-sqlite-storage does work.
Before opening, please confirm:
- [x] I have searched for duplicate or closed issues and discussions.
- [x] I have read the guide for submitting bug reports.
- [x] I have done my best to include a minimal, self-contained set of instructions for consistently reproducing the issue.
JavaScript Framework
React Native
Amplify APIs
DataStore, GraphQL API, Authentication, Storage
Amplify Version
v6
Amplify Categories
storage, api
Backend
Amplify CLI
Environment information
System:
OS: Linux 6.15 Arch Linux
CPU: (16) x64 AMD Ryzen 9 6900HS with Radeon Graphics
Memory: 27.06 GB / 38.40 GB
Container: Yes
Shell: 5.9 - /usr/bin/zsh
Binaries:
Node: 18.16.1 - ~/.nvm/versions/node/v18.16.1/bin/node
Yarn: 1.22.19 - ~/.nvm/versions/node/v18.16.1/bin/yarn
npm: 9.5.1 - ~/.nvm/versions/node/v18.16.1/bin/npm
Browsers:
Firefox: 141.0
npmGlobalPackages:
@aws-amplify/cli: 13.0.1
@githubnext/github-copilot-cli: 0.1.36
@google/gemini-cli: 0.1.9
@sitespeed.io/throttle: 5.0.1
amplify-cli: 1.0.0
corepack: 0.17.0
eas-cli: 16.12.0
graphql-language-service-cli: 3.3.33
npm: 9.5.1
prettier: 3.5.3
react-js-to-ts: 1.4.0
serve: 14.2.4
yo: 5.0.0
Describe the bug
I have an Expo app set up with DataStore configured to use the expo sqlite adapter. It was while investigating another issue (#13269) that I realised there was no AmplifyDatastore database being created in the app data directory. Instead it was falling back to asyncstorage. I verified this by reading RKStorage and seeing entries for DataStore.
There was no error message or indication that it wasn't using sqlite in the logs when debug logging was enabled. Although I might have been grepping for the wrong terms.
Instead I followed the instructions to use react-native-sqlite-storage and it is now creating the AmplifyDatastore database. It also has fixed the issue 13269 as mentioned above.
Expected behavior
When using the Expo sqlite adapter I expect it to use sqlite and not asyncstorage.
Reproduction steps
I wasn't able to make a minimal reproduction with a new amplify and expo project as I was coming across unrelated blockers. However I can share some commits that show what I've done on my own project to change from the expo adapter to the react native one.
These are the relevant entries in package.json
"@aws-amplify/datastore-storage-adapter": "^2.0.42",
"@aws-amplify/ui-react-native": "^1.2.20",
"aws-amplify": "^5.3.11",
Code Snippet
Change in packages: https://github.com/platelet-app/platelet-mobile/pull/17/commits/95f4a295aef44af0df345ae5803885dc85336fe0
Change in DataStore.configure: https://github.com/platelet-app/platelet-mobile/pull/17/commits/f7039a73da4314243278e62101d9fdbfb0b62b40
I'm also using this function to clean up old data in asyncstorage that shouldn't be there: https://github.com/platelet-app/platelet-mobile/pull/17/commits/9c12ce48d66139a7d35c3ca420a72f29e0a7942d
I didn't merge these changes to master yet so this is the repository still with broken expo adapter: https://github.com/platelet-app/platelet-mobile
Log output
I tried to include it, but GitHub says it's too long.
aws-exports.js
No response
Manual configuration
No response
Additional configuration
No response
Mobile Device
Android emulator, iPhone 16
Mobile Operating System
No response
Mobile Browser
No response
Mobile Browser Version
No response
Additional information and screenshots
{
"name": "mobile",
"version": "1.0.0",
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo run:android",
"ios": "expo run:ios",
"web": "expo start --web",
"test": "jest --watch --testTimeout=60000",
"test:ci": "jest --testTimeout=60000",
"test:debug": "node --inspect-brk ./node_modules/jest/bin/jest.js --runInBand --testTimeout=100000000"
},
"dependencies": {
"@aws-amplify/datastore-storage-adapter": "^2.0.42",
"@aws-amplify/ui-react-native": "^1.2.20",
"@azure/core-asynciterator-polyfill": "^1.0.2",
"@expo/metro-runtime": "~4.0.1",
"@react-native-async-storage/async-storage": "1.23.1",
"@react-native-community/netinfo": "11.4.1",
"@react-native/gradle-plugin": "^0.72.11",
"@react-navigation/bottom-tabs": "^6.5.8",
"@react-navigation/material-bottom-tabs": "^6.2.16",
"@react-navigation/native-stack": "^6.9.13",
"@reduxjs/toolkit": "^1.9.5",
"@sentry/react-native": "~6.10.0",
"amazon-cognito-identity-js": "^6.3.1",
"aws-amplify": "^5.3.11",
"core-js": "^3.31.1",
"expo": "~52.0.47",
"expo-dev-client": "~5.0.20",
"expo-file-system": "~18.0.12",
"expo-splash-screen": "~0.29.24",
"expo-status-bar": "~2.0.1",
"expo-updates": "~0.27.4",
"faker": "5.5.3",
"moment": "^2.29.4",
"moment-timezone": "^0.5.43",
"promise": "^8.3.0",
"react": "18.3.1",
"react-content-loader": "^6.2.1",
"react-native": "0.76.9",
"react-native-get-random-values": "~1.11.0",
"react-native-paper": "^5.14.5",
"react-native-paper-dates": "^0.18.12",
"react-native-safe-area-context": "4.12.0",
"react-native-screens": "~4.4.0",
"react-native-sqlite-storage": "^6.0.1",
"react-native-svg": "15.8.0",
"react-native-url-polyfill": "^2.0.0",
"react-redux": "^8.1.1",
"redux-saga": "^1.2.3"
},
"devDependencies": {
"@babel/core": "^7.24.0",
"@testing-library/jest-native": "^5.4.2",
"@testing-library/react-native": "^12.1.3",
"@types/jest": "^29.5.11",
"@types/lodash": "^4.14.202",
"@types/react": "~18.3.12",
"jest-expo": "~52.0.6",
"mock-async-storage": "^2.2.0",
"typescript": "~5.3.3"
},
"private": true,
"description": "Mobile version of Platelet",
"repository": {
"type": "git",
"url": "git+https://github.com/platelet-app/platelet-mobile.git"
},
"author": "Theo Cranmore",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/platelet-app/platelet-mobile/issues"
},
"homepage": "https://github.com/platelet-app/platelet-mobile#readme"
}
Hello @duckbytes,
thank you for reaching out to us. We will investigate this issue and update you as soon as we have more insights.
Hello @duckbytes, I was not able to reproduce the problem. The adapater is using sqlite for me.
Since you mentioned running into some blockers when trying to create a minimal test case, would you be willing to share what those blockers were? That way we can help you work through them and get a reproducible example to further investigate your issue.
Thank you!
hey @adrianjoshua-strutt thanks for looking into it.
I've managed to get a reproduction working and uploaded it here: https://github.com/duckbytes/sqlite-datastore
Key thing is I've fixed my datastore-storage-adapter version at 2.0.42 because of this bug https://github.com/aws-amplify/amplify-js/issues/12801. If I use the latest version I still get that import error.
If you run that project and tap the button, it'll save some entries to datastore. I have built it with EAS and installed it as a development build. Then I run npx expo start to load the app on my emulator.
In Android Studio I look at the files in Device Explorer:
If I download the RKStorage file and run sqlite3 RKStorage then SELECT * from catalystLocalStorage; I can see entries made by DataStore.
I'm hopeful if your attempt to reproduce it is working, we can compare package versions installed and find out what I need to change.
Another thing to note is that this reproduction is expo sdk 53 but my main project is on 52. But it does seem to still happen on 53.
I have uncommented Amplify.configure because syncing was giving my an auth error for some reason. I don't think it's needed to sync to the API to recreate this bug. Certainly when I have syncing set up and working on my main project, the bug still occurs.
Hey @adrianjoshua-strutt could you please share the package.json in your reproduction so I can compare to mine?
Hey @adrianjoshua-strutt are you able to share anything from your reproduction please? Just a copy paste would be enough so I can compare. No matter what I try, I can't get the expo adapter to create a database in my reproduction.
Let me know if it isn't possible to share and I'll do a release on my app that uses the react native adapter instead.
This is what I've found after doing some more investigation today.
In amplify this line https://github.com/aws-amplify/amplify-js/blob/main/packages/datastore-storage-adapter/src/ExpoSQLiteAdapter/ExpoSQLiteDatabase.ts#L32 uses openDatabase
According to the docs the only available functions in current versions of expo-sqlite are openDataBaseSync and openDataBaseAsync https://docs.expo.dev/versions/latest/sdk/sqlite/#sqliteopendatabaseasyncdatabasename-options-directory
In my reproduction I was able to open a database using openDataBaseSync and I could see the database being created in the projects data directory under files/SQLite.
The version of expo-sqlite is fixed at 10.1.0 in the package.json of the adapter package. I tried fixing my project to this version, but I get build errors: Plugin with id 'maven' not found.. I think this version is just too old to work with any current version of the Expo SDK.
If I simply remove the expo-sqlite package from my project I get an error: Unable to resolve "expo-sqlite" from "node_modules/@aws-amplify/datastore-storage-adapter/dist/aws-amplify-datastore-sqlite-adapter-expo.min.js". There don't seem to be any references to it as a dependency in package-lock.json.
It seems like the fix is to update the adapter package to use openDataBaseSync or openDataBaseAsync, but I'm not sure if the package gets updates any more.
@duckbytes Great investigation on identifying the root cause! You're absolutely right - the issue is that ExpoSQLiteAdapter is using the deprecated openDatabase API while modern Expo SDK versions (14+) have moved to openDatabaseSync and openDatabaseAsync.
This explains why DataStore silently falls back to AsyncStorage - when the old API isn't found, it doesn't error out but just uses the fallback storage mechanism.
I've been working on a fix that addresses this by:
- Updating ExpoSQLiteAdapter to detect which API is available at runtime
- Using the modern async methods (
openDatabaseAsync,withTransactionAsync,getAllAsync, etc.) when available - Falling back to the WebSQL-style API for backward compatibility with older Expo versions
- Also fixing the export issue - ExpoSQLiteAdapter was implemented but never exported from the package
I'll raise a PR now with these changes. This should resolve the issue for Expo SDK 50+ users while maintaining compatibility for those on older versions.