Moving from @capacitor/preferences
@capacitor/preferences holds string values in UserDefaults, SharedPreferences and, on the web, localStorage. For a handful of string settings it's the simplest choice, and the Capacitor team maintains it. Move when preferences are one store among several, or you're tired of JSON.stringify around every call.
The calls
| @capacitor/preferences | Strata Storage |
|---|---|
Preferences.set({ key, value }) | storage.set(key, value, { storage: 'preferences' }) |
Preferences.get({ key }) returns { value } | storage.get(key, { storage: 'preferences' }) returns the value |
Preferences.remove({ key }) | storage.remove(key, { storage: 'preferences' }) |
Preferences.keys() returns { keys } | storage.keys(undefined, { storage: 'preferences' }) returns the array |
Preferences.clear() | storage.clear({ storage: 'preferences' }) |
Values don't have to be strings. Objects go in and come back as objects.
Setup and copy
Native adapters register at run time, and they need npx cap sync after you install the package. Without it the native module never reaches your iOS and Android projects.
import { Capacitor } from '@capacitor/core';
import { Preferences } from '@capacitor/preferences';
import { defineStorage } from 'strata-storage';
import { registerCapacitorAdapters } from 'strata-storage/capacitor';
const target = Capacitor.isNativePlatform() ? 'preferences' : 'localStorage';
export const storage = defineStorage({ defaultStorages: [target, 'memory'] });
export async function moveFromPreferences(): Promise<void> {
await registerCapacitorAdapters(storage);
if (await storage.get<boolean>('moved:preferences')) return;
const { keys } = await Preferences.keys();
for (const key of keys) {
const { value } = await Preferences.get({ key });
if (value !== null) await storage.set(key, value);
}
await storage.set('moved:preferences', true);
}
This copies each value as the string it was. If you stored JSON, call JSON.parse on it first so you don't carry the stringifying forward.
Don't assume the old and new keys are the same entries, even though both end up in UserDefaults or SharedPreferences. Copy, then read back.
Check it on a device
A browser run exercises localStorage, not the native path. Install a build holding old data, update to the new one, and read a moved key on both iOS and Android (device verification). Remove the plugin in a later release.
@capacitor/preferences as we checked it
Last checked 7 Nov 2026. "Not stated" means the pages we checked don't mention it, not that the library can't do it. Check @capacitor/preferences yourself, or see the side-by-side page.
| Store or capability | @capacitor/preferences | Strata Storage |
|---|---|---|
| localStorage | Partly. Used as the fallback when running as a PWA, not chosen directly (source, 7 Nov 2026) | Yes |
| IndexedDB | Not stated on the pages we checked | Yes |
| sessionStorage | Not stated on the pages we checked | Yes |
| Cookies | Not stated on the pages we checked | Yes |
| URL parameters as a store | Not stated on the pages we checked | Yes |
| iOS Keychain | Not stated on the pages we checked | Yes |
| Android secure storage (Keystore-backed) | Not stated on the pages we checked | Yes |
| Native preferences (UserDefaults / SharedPreferences) | Yes (source, 7 Nov 2026) | Yes |
| Web and native stores behind one API | Partly. One API over one store per platform, string values only; the page says it is not meant to be used as a local database (source, 7 Nov 2026) | Yes |
| No runtime dependencies | Yes. @capacitor/core is a peer dependency (source, 7 Nov 2026) | Yes |
| Package fact | @capacitor/preferences | Strata Storage |
|---|---|---|
| Licence | MIT (source) | MIT (source) |
| npm version | 8.0.1 | 3.1.4 |
| Bundle size | 264 bytes gzipped, 354 minified, version 8.0.1, 7 Nov 2026. JavaScript side only; the native code is not counted by bundlephobia (source) | 21,468 bytes gzipped, 79,645 minified, version 3.1.4, 7 Nov 2026 (source) |
| Weekly downloads | 1,624,508, 31 Oct 2026 to 6 Nov 2026 (source) | 486, 31 Oct 2026 to 6 Nov 2026 (source) |