Shopify Sync
When Sync to Shopify is enabled on a production order, Synplex pushes inventory adjustments to Shopify when quantities are produced against components. This keeps Shopify's available inventory in sync with production activity managed in Synplex.
Sync Toggle
Each production order has a syncProductionOrderToShopify boolean field.
- Shop-level default: set in Settings → Sync production orders to
Shopify by default. When an order is started and this field is not
explicitly set, the backend reads and applies the shop's default
automatically — this happens at the point the order transitions to
in_progress, not at creation. - Per-order: can be set individually on the order before or during creation.
- Sync only fires while the order is
in_progress— changes toquantityProducedon a draft or completed order are not synced.
What Gets Synced and When
Unlike transfer orders, production order sync does not use Shopify's
Inventory Transfer API. Instead, it calls Shopify's
inventoryAdjustQuantities mutation directly on the available bucket,
referencing the production order as the ledger document.
Sync fires when quantityProduced is updated on a component while the
parent order is in_progress and syncProductionOrderToShopify is true.
Each quantityProduced change produces two types of adjustment:
| Mutation type | Target | Delta direction |
|---|---|---|
ADJUST_AVAILABLE_OUTPUT | Finished-goods output variant | Positive — stock increases as units are produced |
ADJUST_AVAILABLE_COMPONENT | Each BOM component variant | Negative — components are consumed during production |
| For disassembly orders the directions reverse: the output variant stock | ||
| decreases and component variants increase as units are disassembled. |
If a BOM or BOM component has no
inventoryItemId, that leg of the adjustment is skipped and a warning is logged — the rest of the batch still processes.
Deduplication Window
Multiple quantityProduced changes landing within the same 5-second
window are collapsed into a single background job execution. The pending
sync logs written during that window are all processed in one batch when
the job runs, rather than firing a separate Shopify API call per save.
This prevents API rate limit pressure when a user saves several component quantity updates in quick succession.
Sync Guards
Before any adjustment is dispatched, Synplex checks:
- Parent production order status must be
in_progress— if not, sync is skipped entirely syncProductionOrderToShopifymust betrueon the parent order — if false, a SKIPPED log is written and no Shopify call is made- Both
inventoryItemGidandlocationGidmust be present on the pending log — if either is missing, the log is permanently markedFAILEDand cannot be retried
Queue and Retry Behaviour
All production order sync mutations run through a background job queue:
| Setting | Value |
|---|---|
| Queue name | shopify-production-sync-{shopId} |
| Max concurrency | 1 per shop |
| Retry count | 3 |
| Initial interval | 60 seconds |
| Backoff factor | 2× |
| Max interval | 5 minutes |
| Jitter | Yes |
| Dedup window | 5 seconds |
On the final retry attempt, a failed log is permanently marked FAILED. | |
| Remaining logs in the same batch continue processing regardless — one | |
| failed adjustment does not abort the rest. |
Sync Log (productionOrderSyncLog)
Every sync attempt — pending, skipped, successful, or failed — is
recorded as a productionOrderSyncLog entry. Log fields include:
| Field | Description |
|---|---|
status | PENDING, SUCCESS, FAILED, SKIPPED |
triggerType | What caused the sync (PRODUCTION_UPDATED, MANUAL_RESYNC, ORDER_COMPLETED) |
mutationType | The adjustment type (ADJUST_AVAILABLE_OUTPUT, ADJUST_AVAILABLE_COMPONENT, SKIPPED) |
delta | Integer quantity adjustment sent to Shopify |
previousQuantityProduced | The component's quantityProduced value before the change |
inventoryItemGid | Shopify GID of the inventory item adjusted |
locationGid | Shopify GID of the location where the adjustment was applied |
referenceDocumentUri | Ledger reference back to the production order (gid://{appHandle}/ProductionOrder/{id}) |
shopifyAdjustmentGroupId | The Shopify adjustment group ID returned on success |
errorMessage | Error detail if the attempt failed |
retryCount | Number of retry attempts made |
How This Differs from Transfer Sync
| Production Order Sync | Transfer Order Sync | |
|---|---|---|
| Shopify API | inventoryAdjustQuantities (available bucket) | Inventory Transfer API |
| Trigger | quantityProduced change on a component | Status transitions and shipment events |
| Sync timing | While order is in_progress | On confirmation, shipment creation, and receipt |
| Dedup window | 5 seconds — rapid saves batched | No dedup — each event fires independently |
| Queue concurrency | 1 per shop | 2 per shop |
| Header field sync | Not applicable | reference and notes on update |
| Cancellation sync | No Shopify call on cancel | TRANSFER_CANCEL mutation if synced |