Shopify’s mid-September ship: six updates, plus Events that need a code look
TL;DR
Shopify packed mid-September with admin UI, metafield costing, Catalog media filters, Functions metafields, CLI store commands, and multi-barcode variants. Then Events changed payloads and triggers. Classic webhooks are fine; Events subscribers should migrate.

Mid-September was busy on shopify.dev/changelog. In a little over a week Shopify shipped admin UI changes, API pricing tweaks, Catalog and Functions improvements, CLI store lifecycle commands, and multi-barcode variants. On 16 September they also tightened Events payloads and subscription configuration: action required if you use Events (classic webhooks are unaffected).
Here is what matters if you build or operate Shopify apps.
1. The Shopify admin has a new look
From 15 September, the refreshed admin rolls out progressively: new colour, type, spacing, and frame; search, notifications, and store picker move into a collapsible side nav; Sidekick becomes a floating chat.
For extensions: Admin UI and App Home UI extensions pick up the new styles automatically. No extension code change required for appearance.
For embedded App Home: your current look stays until you opt into Polaris 2.0 (release candidate coming). Polaris Web Components 1.1 is the current RC; major versions on the Polaris CDN are explicit, so merchants should not see a half-migrated app. If you are still off Polaris Web Components, migrate there first so adopting 2.0 is a smaller jump.
During rollout, the same app can sit next to old or new admin chrome depending on the shop. Design screenshots and support docs accordingly.
2. metafieldsSet now costs by distinct owner
The flat 10-point metafieldsSet call is gone. Cost is now base 10 + weighted distinct owners (changelog):
| Owner type | Weight | | --- | --- | | Order | 10 | | Product | 4 | | ProductVariant | 2 | | Collection / Customer / Shop | 1 | | Other | 0 |
Extra metafields on the same owner are free for costing. Fan-out across many orders or products is expensive (up to 260 points for 25 distinct orders). Aliased mutations each pay the base cost and do not dedupe owners across aliases.
Do: batch all metafields for one resource in one call, read extensions.cost, use Shopify-GraphQL-Cost-Debug: 1 when debugging, and back off on THROTTLED. Don’t split one high-fan-out write into many calls to “save” points: you pay the base 10 repeatedly and usually spend more.
Most single-resource writers feel little change. Sync jobs that spray metafields across dozens of owners in one mutation need a second look.
3. Catalog search can filter by media type
The Catalog API now returns video and 3D assets (not only images) on search_catalog, get_product, and lookup_catalog, and accepts catalog.filters.media with image, video, and/or model_3d (AND semantics).
Useful for AR try-on, 3D viewers, and camera-first shopping: filter once, get asset URLs in the same response, skip fetch-inspect-discard. Video and 3D need the draft Shopify global Catalog extension (dev.shopify.catalog.global) in the agent profile; stable still returns images only until the next UCP release.
Existing queries keep working. Unrecognised media types are ignored and reported in result.messages[].
4. Delivery options expose metafields to Functions
On API version 2026-10, CartDeliveryOption gains metafield(namespace:, key:) so Delivery Customization (and any function that sees delivery options) can read structured data attached when the option was generated (changelog).
That replaces brittle “encode meaning in the title/handle” patterns. Ownership rules still apply: your app-reserved namespace and unprefixed shared namespaces are readable; another app’s reserved namespace resolves to null. Metafields on delivery options are checkout-scoped, not persisted after checkout.
No action if you do not query the field. If you do, bump the function input query to 2026-10 and treat the metafield as an explicit contract between generator and customizer.
5. Create and delete dev stores from Shopify CLI
CLI 4.8 adds shopify store create dev, shopify store list, shopify store info, and shopify store delete. Combined with existing Admin API and bulk ops in the CLI, you can script create → populate → reset loops for apps and themes, including from coding agents with the AI Toolkit.
Organizations now have a 250 limit on dev stores (client transfer and collaborator stores do not count). Clean up with list + delete before you hit the ceiling.
6. Variants support multiple barcodes
Variants can carry up to 20 barcodes via the barcodes connection and inputs on productSet / productVariantsBulkCreate / productVariantsBulkUpdate (changelog). Optional types (UPC, EAN, ISBN, GTIN, ASIN) are validated; untyped values store as sent.
The singular barcode field is deprecated but working: reads return the first barcode; writes update the first and leave the rest. Sending barcodes replaces the whole set. Product/variant filters match any barcode on the variant.
If you sync identifiers to ERP, marketplace, or POS feeds, move reads to barcodes before merchants add a second code, or you will silently see only one value.
Action required: Events payloads and subscriptions
Updates to Events payloads and subscription configuration landed on 16 September 2026. Classic webhook subscriptions are unaffected. If you subscribe through Events, plan a small migration.
fields_changed is now shaped by change type
The flat string array becomes an object with added, updated, and removed. You can tell a nested resource was added versus a leaf value updated without an extra query. Example: adding a variant keeps Product action: "update" and puts the variant path under fields_changed.added.
Update handlers to read fields_changed.added / .updated / .removed instead of iterating a single array.
Parent triggers need an explicit .*
Leaf triggers such as product.variants.price are unchanged. Parent “everything under this path” subscriptions must use a terminal wildcard, e.g. product.variants.* instead of product.variants. Existing subscriptions keep working until you next deploy shopify.app.toml; update parent triggers then. Matching behaviour and volume for equivalent subscriptions should stay the same.
Delivery headers trimmed
Events deliveries no longer send shopify-event-id or shopify-resource-id. Bump Shopify API packages; remove any custom validation that depended on those headers.
triggers required on update
Subscriptions with the update action must include at least one trigger going forward. Existing subscriptions continue to work as expected.
Shopify’s community migration thread has examples and a place to ask questions.
What we are doing at Reiwa Dev
For our own apps (RWA: Waitlist Flow, Shiftify, True Profit Analytics, Rollback Hero):
- Confirm Events vs classic webhooks per app; migrate Events payload parsing and TOML triggers where needed.
- Audit high-volume
metafieldsSetpaths for fan-out cost. - Keep App Home on a path to Polaris Web Components / 2.0 so admin refresh does not leave us looking dated.
- Treat multi-barcode as a product sync concern for any catalog-touching code.
- Use CLI store commands in agent and CI workflows where they replace manual Dev Dashboard clicks.
Platform velocity is high right now. The wins are real (better admin UX, clearer Events diffs, richer Catalog media, saner Functions contracts). The cost is staying close to the changelog and shipping small migrations before the next deploy forces them.
If you want help reviewing Events handlers, metafield write patterns, or Polaris readiness on a Shopify app, book a consultation.