Skip to main content

Storage API

The Storage API provides persistent local storage for POS UI extensions, allowing you to store, retrieve, and manage extension data that persists across user sessions, device restarts, and extension target state changes. Data is stored locally on the POS device in an isolated namespace specific to your extension.

The API supports key-value storage with automatic JSON serialization, type safety through TypeScript interfaces, and built-in error handling for storage constraint violations. It also provides reactive access to stored values through shopify.storage.current, so one extension target can react when another target updates a key.

  • Data caching: Cache product information and pricing data to reduce API calls.
  • Preferences: Store user preferences like theme settings and workflow customizations.
  • Contextual data: Pass data between tile and action (modal) targets during workflows.
  • Session data: Maintain temporary session data that survives navigation and cart changes.
  • Cross-target communication: React to changes with shopify.storage.current when another target of your extension writes to them.
Support
Targets (23)

The shopify global object provides persistent local storage for extension data. Access the following properties on shopify to store, retrieve, and manage key-value data that persists across sessions.

Anchor to clear
clear
() => Promise<void>
required

Clears all data from storage, removing all key-value pairs.

Anchor to current
current
<BaseStorageTypes>
required

Reactive access to storage values as Subscribables.

Each key is exposed as a ReadonlySignalLike<T | undefined>, enabling cross-target reactivity. One extension target can subscribe to a key and react when another target updates it via set() or delete().

The value property provides synchronous, reactive access to the current stored value. It is not preloaded: storage hydrates asynchronously, so value is undefined until the key has been loaded. The subscribe() method registers a callback that fires whenever the value changes, including changes made by other extension targets within the same app.

Anchor to delete
delete
<StorageTypes extends BaseStorageTypes = BaseStorageTypes, Keys extends keyof StorageTypes = keyof StorageTypes>(key: Keys) => Promise<boolean>
required

Deletes a specific key from storage and returns true if the key existed, false if it didn't exist. Returns false for non-existent keys rather than throwing an error. Commonly used for cleaning up temporary workflow data, removing expired cache entries, or handling user preference changes.

Anchor to entries
entries
<StorageTypes extends BaseStorageTypes = BaseStorageTypes, Keys extends keyof StorageTypes = keyof StorageTypes>() => Promise<[Keys, StorageTypes[Keys]][]>
required

Retrieves all stored key-value pairs as an array of tuples, preserving original data types. Returns all data at once which may impact memory usage with large datasets. Commonly used for debugging storage contents, implementing data export features, or performing bulk operations across stored data.

<StorageTypes extends BaseStorageTypes = BaseStorageTypes, Keys extends keyof StorageTypes = keyof StorageTypes>(key: Keys) => Promise<StorageTypes[Keys]>
required

Retrieves the value associated with a key, returning undefined if the key doesn't exist. Always handle the undefined case by providing fallback values or conditional logic. Commonly used for loading user preferences, retrieving cached data, or accessing contextual information passed between extension targets.

<StorageTypes extends BaseStorageTypes = BaseStorageTypes, Keys extends keyof StorageTypes = keyof StorageTypes>(key: Keys, value: StorageTypes[Keys]) => Promise<void>
required

Stores a value under the specified key, overwriting any existing value. Values must be JSON-serializable and return StorageError when storage limits are exceeded. Commonly used for storing user preferences, caching API responses, or passing contextual data from tiles to modals.

Examples

jsx

import {render} from 'preact';
import {useState, useEffect} from 'preact/hooks';

export default async () => {
render(<Extension />, document.body);
}

function Extension() {
const [itemCount, setItemCount] = useState(0);

useEffect(() => {
const initializeData = async () => {
const count = 10;
for (let i = 0; i < count; i++) {
await shopify.storage.set(`key-${i}`, `value-${i}`);
}
setItemCount(count);
};

initializeData();
}, []);

return (
<s-tile
heading="POS smart grid"
subheading="preact Extension"
itemCount={itemCount}
onClick={async () => {
await shopify.storage.clear();
shopify.toast.show('All data cleared');
setItemCount(0);
}}
/>
);
}

  • Design consistent key naming: Use hierarchical names like settings.user.theme or cache.products.${id} to organize data.
  • Validate retrieved data: Check structure and types after get() since data may be outdated. Provide defaults and handle missing properties.
  • Plan for data evolution: Include version fields and implement migration logic to handle schema updates between versions.
  • Keep sensitive data out: Never store passwords, API keys, or sensitive information. Use Session API for secure backend communication.
  • Assign one writer per key: When you use storage for cross-target communication, have a single target own writes to each key. Multiple targets writing the same key can race and overwrite each other's values.

  • POS UI extensions can store up to a maximum of 100 entries.
  • The maximum key size is ~1 KB and the maximum value size is ~1 MB.
  • Data persists even when extension targets are disabled or removed.
  • Stored extension data is automatically cleared after 30 days of inactivity. The inactivity timer is reset only by write operations (set); read operations (get) do not affect the timer.

Was this page helpful?