Skip to content

[Question / Feature Request] Using Different Local Storage Library Other than react-native-async-storage (react-native-mmkv) #14533

@ChristopherGabba

Description

@ChristopherGabba

Before opening, please confirm:

JavaScript Framework

React Native

Amplify APIs

Cache

Amplify Version

v6

Amplify Categories

No response

Backend

None

Environment information

 System:
    OS: macOS 15.6.1
    CPU: (10) arm64 Apple M2 Pro
    Memory: 500.70 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 23.4.0 - ~/.nvm/versions/node/v23.4.0/bin/node
    Yarn: 1.22.22 - /opt/homebrew/bin/yarn
    npm: 11.5.2 - ~/.nvm/versions/node/v23.4.0/bin/npm
    bun: 1.2.19 - /opt/homebrew/bin/bun
    Watchman: 2025.04.14.00 - /opt/homebrew/bin/watchman
  Browsers:
    Chrome: 139.0.7258.155
    Safari: 18.6
  npmPackages:
    %name%:  0.1.0 
    @aws-amplify/backend: ^1.11.0 => 1.16.1 
    @aws-amplify/backend-cli: ^1.8.0 => 1.8.0 
    @aws-amplify/react-native: ^1.1.10 => 1.1.10 
    @aws-amplify/rtn-web-browser: ^1.1.4 => 1.1.4 
    @aws-appsync/utils: 2.0.3 => 2.0.3 
    @aws-sdk/client-cognito-identity-provider: 3.799.0 => 3.799.0 
    @aws-sdk/client-dynamodb: 3.799.0 => 3.799.0 
    @aws-sdk/client-sso-oidc: 3.799.0 => 3.799.0 (3.622.0, 3.637.0, 3.624.0, 3.621.0)
    @aws-sdk/client-sts: 3.799.0 => 3.799.0 (3.622.0, 3.879.0, 3.624.0, 3.621.0)
    @aws-sdk/types: 3.775.0 => 3.775.0 (3.609.0, 3.387.0, 3.862.0, 3.398.0, 3.821.0, 3.734.0)
    @aws-sdk/util-dynamodb: 3.799.0 => 3.799.0 
    @babel/core: ^7.20.0 => 7.28.3 
    @babel/plugin-proposal-export-namespace-from: ^7.18.9 => 7.18.9 
    @babel/plugin-proposal-optional-chaining: ^7.0.0 => 7.21.0 
    @babel/plugin-transform-arrow-functions: ^7.0.0 => 7.27.1 
    @babel/plugin-transform-nullish-coalescing-operator: ^7.0.0 => 7.27.1 
    @babel/plugin-transform-shorthand-properties: ^7.0.0 => 7.27.1 
    @babel/plugin-transform-template-literals: ^7.0.0 => 7.27.1 
    @babel/preset-env: ^7.20.0 => 7.28.3 
    @babel/runtime: ^7.20.0 => 7.28.3 
    @config-plugins/ffmpeg-kit-react-native: 9.0.0 => 9.0.0 
    @expo-google-fonts/m-plus-1p: 0.2.3 => 0.2.3 
    @expo-google-fonts/montserrat: 0.2.3 => 0.2.3 
    @expo/config-plugins: ~11.0.5 => 11.0.5 (10.1.2)
    @expo/metro-runtime: ~6.1.0 => 6.1.1 
    @gorhom/bottom-sheet: 5.1.6 => 5.1.6 
    @legendapp/list: ^2.0.0-beta.4 => 2.0.0-next.25 
    @react-native-async-storage/async-storage: 2.2.0 => 2.2.0 
    @react-native-community/netinfo: 11.4.1 => 11.4.1 
    @react-native-menu/menu: ^1.2.4 => 1.2.4 
    @react-navigation/bottom-tabs: 7.4.6 => 7.4.6 
    @react-navigation/native: 7.1.17 => 7.1.17 
    @react-navigation/native-stack: 7.3.25 => 7.3.25 
    @sentry/react-native: ~6.20.0 => 6.20.0 
    @tanstack/query-codemods:  undefined ()
    @tanstack/react-query: ^5.85.5 => 5.85.5 
    @tanstack/react-query-persist-client: ^5.85.5 => 5.85.5 
    @types/i18n-js: 3.8.2 => 3.8.2 
    @types/jest: ^29.2.1 => 29.5.14 
    @types/lodash.filter: ^4.6.9 => 4.6.9 
    @types/node: 22.10.5 => 22.10.5 (24.3.0)
    @types/react: ~19.1.10 => 19.1.12 (18.3.24)
    @types/react-test-renderer: ^18.0.0 => 18.3.1 
    @typescript-eslint/eslint-plugin: ^8.33.1 => 8.41.0 
    @typescript-eslint/parser: ^8.33.1 => 8.41.0 
    @typescript-eslint/utils: ^8.31.1 => 8.41.0 
    ContextAPIMixpanel:  0.0.1 
    MixpanelDemo:  0.0.1 
    MixpanelExample:  0.0.1 
    SimpleMixpanel:  0.0.1 
    aws-amplify: ^6.15.5 => 6.15.5 
    aws-amplify/adapter-core:  undefined ()
    aws-amplify/adapter-core/internals:  undefined ()
    aws-amplify/analytics:  undefined ()
    aws-amplify/analytics/kinesis:  undefined ()
    aws-amplify/analytics/kinesis-firehose:  undefined ()
    aws-amplify/analytics/personalize:  undefined ()
    aws-amplify/analytics/pinpoint:  undefined ()
    aws-amplify/api:  undefined ()
    aws-amplify/api/internals:  undefined ()
    aws-amplify/api/server:  undefined ()
    aws-amplify/auth:  undefined ()
    aws-amplify/auth/cognito:  undefined ()
    aws-amplify/auth/cognito/server:  undefined ()
    aws-amplify/auth/enable-oauth-listener:  undefined ()
    aws-amplify/auth/server:  undefined ()
    aws-amplify/data:  undefined ()
    aws-amplify/data/server:  undefined ()
    aws-amplify/datastore:  undefined ()
    aws-amplify/in-app-messaging:  undefined ()
    aws-amplify/in-app-messaging/pinpoint:  undefined ()
    aws-amplify/push-notifications:  undefined ()
    aws-amplify/push-notifications/pinpoint:  undefined ()
    aws-amplify/storage:  undefined ()
    aws-amplify/storage/s3:  undefined ()
    aws-amplify/storage/s3/server:  undefined ()
    aws-amplify/storage/server:  undefined ()
    aws-amplify/utils:  undefined ()
    aws-cdk: 2.1013.0 => 2.1013.0 
    aws-cdk-lib: 2.194.0 => 2.194.0 
    babel-jest: ^29.2.1 => 29.7.0 
    buffer: 6.0.3 => 6.0.3 (4.9.2, 5.6.0, 5.7.1)
    constructs: ^10.3.0 => 10.4.2 
    date-fns: 4.1.0 => 4.1.0 
    esbuild: ^0.21.1 => 0.21.5 (0.25.9)
    eslint: ^9.28.0 => 9.34.0 
    eslint-config-prettier: 9.1.0 => 9.1.0 
    eslint-config-standard: 17.0.0 => 17.0.0 
    eslint-plugin-import: 2.26.0 => 2.26.0 
    eslint-plugin-n: ^15.0.0 => 15.7.0 
    eslint-plugin-promise: 6.6.0 => 6.6.0 
    eslint-plugin-react: ^7.37.5 => 7.37.5 
    eslint-plugin-react-native: 4.0.0 => 4.0.0 
    expo: 54.0.0-preview.11 => 54.0.0-preview.11 
    expo-application: ~7.0.4 => 7.0.4 
    expo-blur: ~15.0.4 => 15.0.4 
    expo-build-properties: ~1.0.5 => 1.0.5 
    expo-clipboard: ~8.0.4 => 8.0.4 
    expo-constants: ~18.0.5 => 18.0.5 
    expo-contacts: ~15.0.5 => 15.0.5 
    expo-dev-client: ~6.0.6 => 6.0.6 
    expo-device: ~8.0.4 => 8.0.4 
    expo-file-system: ~19.0.5 => 19.0.6 
    expo-font: ~14.0.5 => 14.0.5 
    expo-haptics: ~15.0.4 => 15.0.4 
    expo-image: ~3.0.3 => 3.0.4 
    expo-image-picker: ~17.0.5 => 17.0.5 
    expo-keep-awake: ~15.0.4 => 15.0.4 
    expo-linear-gradient: ~15.0.4 => 15.0.4 
    expo-linking: ~8.0.5 => 8.0.5 
    expo-localization: ~17.0.4 => 17.0.4 
    expo-secure-store: ~15.0.4 => 15.0.4 
    expo-share-intent: 4.1.1 => 4.1.1 
    expo-sharing: ~14.0.4 => 14.0.4 
    expo-sms: ~14.0.4 => 14.0.4 
    expo-splash-screen: ~31.0.6 => 31.0.6 
    expo-store-review: ~9.0.4 => 9.0.4 
    expo-video: ~3.0.7 => 3.0.7 
    expo-video-metadata: 1.5.0 => 1.5.0 
    expo-video-thumbnails: ~10.0.4 => 10.0.4 
    ffmpeg-kit-react-native: 6.0.2 => 6.0.2 
    follow-redirects: 1.15.9 => 1.15.9 
    i18next: 25.2.1 => 25.2.1 
    intl-pluralrules: 2.0.1 => 2.0.1 
    jest: ^29.2.1 => 29.7.0 
    jest-expo: ~54.0.5 => 54.0.5 
    libphonenumber-js: 1.11.19 => 1.11.19 (1.9.47)
    libphonenumber-js-core:  undefined (1.0.0)
    libphonenumber-js-max:  undefined (1.0.0)
    libphonenumber-js-min:  undefined (1.0.0)
    libphonenumber-js-mobile:  undefined (1.0.0)
    libphonenumber-js/build:  undefined ()
    libphonenumber-js/core:  undefined ()
    libphonenumber-js/max:  undefined ()
    libphonenumber-js/max/metadata:  undefined ()
    libphonenumber-js/min:  undefined ()
    libphonenumber-js/min/metadata:  undefined ()
    libphonenumber-js/mobile:  undefined ()
    libphonenumber-js/mobile/examples:  undefined ()
    libphonenumber-js/mobile/metadata:  undefined ()
    lodash: 4.17.21 => 4.17.21 
    lottie-react-native: ~7.3.1 => 7.3.3 
    mixpanel-react-native: 3.1.2 => 3.1.2 
    mixpanelexpo:  1.0.0 
    onesignal-expo-plugin: 2.0.3 => 2.0.3 
    patch-package: 6.4.7 => 6.4.7 
    postinstall-prepare: 1.0.1 => 1.0.1 
    prettier: 2.8.8 => 2.8.8 (2.3.2, 3.6.2, 1.19.1)
    react: 19.1.0 => 19.1.0 (19.2.0-canary-5252281c-20250408)
    react-dom: 19.1.0 => 19.1.0 (19.2.0-canary-5252281c-20250408)
    react-i18next: 15.4.1 => 15.4.1 
    react-native: 0.81.1 => 0.81.1 
    react-native-blurhash: ^2.1.1 => 2.1.2 
    react-native-compressor: ^1.12.0 => 1.12.0 
    react-native-edge-to-edge: ^1.6.2 => 1.7.0 
    react-native-gesture-handler: ~2.28.0 => 2.28.0 
    react-native-get-random-values: 1.11.0 => 1.11.0 
    react-native-ios-context-menu: 3.1.3 => 3.1.3 
    react-native-ios-utilities: 5.1.8 => 5.1.8 
    react-native-keyboard-controller: 1.18.5 => 1.18.5 
    react-native-mime-types: 2.5.0 => 2.5.0 
    react-native-mmkv: 2.12.2 => 2.12.2 
    react-native-nitro-audio-manager: 0.1.3 => 0.1.3 
    react-native-nitro-modules: 0.28.1 => 0.28.1 
    react-native-nitro-screen-recorder: ^0.3.5 => 0.3.5 
    react-native-onesignal: 5.2.13 => 5.2.13 
    react-native-reanimated: ~3.19.1 => 3.19.1 
    react-native-safe-area-context: ~5.6.0 => 5.6.1 
    react-native-screens: ~4.15.0 => 4.15.4 
    react-native-static-safe-area-insets: 2.2.0 => 2.2.0 
    react-native-url-polyfill: 2.0.0 => 2.0.0 
    react-native-vision-camera: 4.7.0 => 4.7.0 
    react-native-vision-camera-face-detector: 1.8.3 => 1.8.3 
    react-native-webview: 13.15.0 => 13.15.0 
    react-native-worklets-core: 1.5.0 => 1.5.0 
    react-native-youtube-iframe: 2.3.0 => 2.3.0 
    react-native-z-view: 0.2.4 => 0.2.4 
    react-test-renderer: 18.2.0 => 18.2.0 (19.1.0)
    ts-jest: ^29.1.1 => 29.4.1 
    ts-node: ^10.9.2 => 10.9.2 
    tsx: ^4.9.4 => 4.20.5 (4.19.4)
    typescript: ~5.9.2 => 5.9.2 (4.4.4, 4.9.5)
    uuid: 11.0.5 => 11.0.5 (9.0.1, 11.1.0, 3.3.2, 7.0.3)
    zeego: 3.0.6 => 3.0.6 
    zustand: 5.0.5 => 5.0.5 
  npmGlobalPackages:
    corepack: 0.30.0
    eas-cli: 16.17.4
    license-checker: 25.0.1
    npm: 11.5.2


Describe the bug

Currently react-native-async-storage is the default dependency for aws-amplify

See docs: https://docs.amplify.aws/react-native/start/quickstart/
Image

It's currently the slowest storage alternative out there in the react-native ecosystem and the community is slowly migrating to react-native-mmkv which is a synchronous local storage system that is much faster.
See benchmarks:

Image

I currently use mmkv for everything except amplify, and I have to keep react-native-async-storage as a dependency in my app, just to serve this one purpose. Is there a way to replace the storage instance / persister to mmkv in Amplify.configure?

Here would be some sort of API to explain it:

const amplifyStorageOverwrite = {
  setItem: (key: string, value: string) => {
    mmkv.set(key, value);
    return Promise.resolve();
  },
  getItem: (key: string) => {
    const value = mmkv.getString(key);
    return Promise.resolve(value ?? null);
  },
  removeItem: (key: string) => {
    mmkv.delete(key);
    return Promise.resolve();
  },
  clear: () => {
    mmkv.clearAll();
    return Promise.resolve();
  },
};

// Add storage configuration to Auth
config.Auth = {
  ...config.Auth,
  localStorage: amplifyStorageOverwrite,
};
Amplify.configure(config)

Tanstack query allows this: https://tanstack.com/query/v5/docs/framework/react/plugins/persistQueryClient#building-a-persister

Expected behavior

Ideally you could just overwrite the get, set, and clear, etc functions to write to mmkv instead, and open up the flexibility away from react-native-async-storage.

I did notice some examples on the React docs on how to do this using different storage mechanisms:
https://docs.amplify.aws/gen1/react/build-a-backend/auth/manage-user-session/#understand-token-management-options

Reproduction steps

N/A

Code Snippet

N/A

Log output

N/A

aws-exports.js

N/A

Manual configuration

N/A

Additional configuration

N/A

Mobile Device

No response

Mobile Operating System

No response

Mobile Browser

No response

Mobile Browser Version

No response

Additional information and screenshots

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions