Summary
We are requesting the ability for POS UI Extensions to perform “background” or non-blocking actions, particularly for complex addToCart sequences. Currently, high-volume merchants experience significant friction because the main UI thread (or at least the user flow) is blocked while the extension performs necessary data manipulation (splitting lines, attaching attributes) and waits for Shopify Functions (Cart Transform) to execute.
Context & Use Case
Our POS integration powers complex retail workflows (e.g., cafes, quick-service restaurants) where speed is critical. A common workflow involves:
- Customisation: User selects complex modifiers for a product (e.g., “Latte” with “Soy Milk”, “Extra Hot”, “Vanilla Syrup”).
- Add to Cart: The extension creates a line item with specific properties.
- Transformation: We use the Cart Transform API (Shopify Functions) to split this single “Latte” line item into its component parts for inventory tracking (1x Latte, 1x Soy Milk Surcharge, 1x Vanilla Syrup).
- Repeat: The user often taps “Add and Order More” to immediately start customising the next item for the same customer.
The Problem
The current architecture forces a synchronous wait on every “Add to Cart” action.
When a user taps “Add to Cart”:
- The Extension calculates payload.
cart.lines.addorcart.bulkUpdateis called.- Network request to Shopify.
- Cart Transform Function runs (Backend logic).
- Cart is recalculated and returned to POS.
- Only then is control returned to the user.
For a busy barista ringing up 5 drinks in a row, waiting ~500ms-1s+ per item for the cart execution to settle is a significant degradation in UX compared to native POS speed.
Proposed Solution
We propose two potential enhancements to the POS UI Extensions API:
1. Optimistic / Background addToCart
Allow extensions to flag a cart operation as “background” or “optimistic”.
// Proposed API Sketch
api.cart.lines.add(lines, { background: true });
Behavior:
- The promise resolves immediately (or very quickly), allowing the UI to unblock.
- The actual cart update and recalculation happens asynchronously.
- If an error occurs (e.g., out of stock), a global toast or error banner notifies the user after the fact, but the happy path is instant.
2. POS Background Workers
Introduce a “Headless” or “Background” target for POS Extensions that can process a queue of tasks.
- Use Case: The UI Extension pushes a “job” (e.g.,
{ type: 'ADD_COMPLEX_ITEM', payload: ... }) to the worker. - The UI Extension immediately resets its form for the next item (“Add and Order More”).
- The Worker processes the job in the background, making the necessary API calls to update the cart.
Why this matters
- Parity with Native Performance: Native POS buttons feel instant. Extensions feel sluggish by comparison when doing anything non-trivial.
- High-Volume Compatibility: This feature is essential for QSR (Quick Service Restaurant) and high-volume retail environments where every second counts.
- “Add and Order More” Flows: This specific UI pattern relies heavily on the ability to “fire and forget” the previous item to focus on the next one.
Example Code (Current vs Desired)
Current Blocking Flow
const handleAddToCart = async () => {
setIsLoading(true); // Blocks UI
// 1. Prepare complex attributes
const attributes = calculateAttributes(state);
// 2. Perform blocking update
await api.cart.bulkUpdate({
lineItems: [...currentItems, newItem]
});
// User waits here... ⏳
setIsLoading(false);
closeModal(); // User finally free to move on
};
Desired Non-Blocking Flow
const handleAddToCart = () => {
// 1. Prepare complex attributes
const attributes = calculateAttributes(state);
// 2. Fire and forget (Background Action)
api.cart.bulkUpdate({
lineItems: [...currentItems, newItem]
}, { mode: 'background' });
// 3. Immediate return to user
resetForm(); // User immediately starts next item 🚀
toast.show("Item added in background");
};
We believe this functionality would unlock a new tier of professional, high-speed apps on Shopify POS.