Migration guide18 min read

Migrate Your Shopify App for Market-Driven Shipping

A developer migration guide for Shopify's market-driven shipping: detect the shipping model, audit GraphQL reads and writes, move merchant config to the Markets API, and keep app-owned delivery profiles working.

Migrate Your Shopify App for Market-Driven Shipping cover image
By Jeroen BoersPublished August 3, 2026Updated August 3, 202618 min read

Editorial note

Platform contracts and the market-driven shipping preview were verified first-hand on a Shopify Plus development store with the feature preview enabled on August 3, 2026, at Admin API version 2026-07. This guidance reflects preview behavior, which changes before general rollout, so re-verify field names, scope names, coversAllItems behavior, rollout dates, and the current stable API version against official Shopify documentation at implementation time.

What market-driven shipping changes

Market-driven shipping moves where a merchant's shipping configuration lives. The buyer still sees delivery options at checkout, but the API that owns and expresses those options is changing. If your app reads or writes a merchant's shipping rules, that change reaches your code, and this guide is the migration path.

This guidance was verified first-hand on a Shopify Plus development store with the market-driven shipping feature preview enabled on August 3, 2026, at Admin API version 2026-07. Everything described here is preview behavior. Preview contracts change before general rollout, so treat exact field names, scope names, and dates as things to re-verify against Shopify's documentation at implementation time.

Merchant configuration moves to Markets

Under market-driven shipping, merchant-owned shipping configuration moves from the DeliveryProfile API to the Markets API. It is exposed through Market.delivery.shipping, where DeliveryOptionDefinition objects carry fields such as freeDeliveryMinimumValue, isActive, includedLocations, and includedCollections. The merchant now manages shipping per market rather than through a single global delivery-profile structure.

App-owned delivery profiles remain a separate contract

App-owned delivery profiles do not move. They continue to use the existing DeliveryProfile API. This is the most important boundary in the migration: the Markets API owns the merchant's configuration, while the DeliveryProfile API still owns the profiles your app creates and manages. The two models are separate contracts, not two views of the same data.

On the same preview store, an app-created DeliveryProfile scoped to a single product variant coexisted with the merchant's market-driven configuration. The general, or default, profile held the other variants, the app-owned profile held its one variant, and Market.delivery.shipping.isEnabled remained true throughout. That confirms the two ownership models run side by side rather than replacing one another.

Why legacy reads can become stale and writes can become no-ops

The risk during rollout is silent divergence. When a shop is on market-driven shipping, its authoritative shipping configuration is in the Markets API. Code that keeps reading merchant shipping rules from DeliveryProfile can return an incomplete or stale picture, because the merchant is no longer editing configuration there. Writes aimed at merchant configuration through the legacy path can effectively become no-ops for the merchant-owned surface.

Draw the presentation boundary early

Market-driven shipping changes the underlying shipping model and its ownership. It is not a checkout-presentation feature. Reshaping how options are displayed still belongs to the

Delivery Customization Function

, which owns option presentation and not the shipping model underneath it. Keep those two responsibilities in separate parts of your design.

Does your app need to change?

Not every app is affected. Sort your app into one of three categories before you plan any work, because the category decides how much migration you owe.

App-owned-profile-only apps

If your app only creates and manages its own delivery profiles through the DeliveryProfile API and never reads or writes the merchant's shipping configuration, the migration surface is small. The verified coexistence test supports this: the app-owned profile kept working while market-driven shipping was enabled. You still need to confirm your profiles behave as expected on a market-driven store, but you are not moving your configuration to a new API.

Merchant-profile readers

If your app reads the merchant's shipping configuration—rates, thresholds, zones, or included locations—to display, sync, or reason about it, you are affected. Once a shop is on market-driven shipping, the authoritative source for that data is the Markets API. A reader that stays on DeliveryProfile for merchant configuration risks returning a partial or stale view.

Merchant-profile writers

If your app writes the merchant's shipping configuration—creating or editing rates, thresholds, or zones on the merchant's behalf—you have the largest migration. Writes to merchant-owned configuration move to the Markets API, and that path requires new scopes and, therefore, merchant reauthorization. Plan this category first, because it carries the consent step and the highest chance of a silent no-op if left on the legacy path.

App categoryInteracts withMigration surfaceNew scope required?
App-owned-profile-onlyIts own DeliveryProfile objectsConfirm behavior on market-driven storesNo new scope beyond existing delivery-profile access
Merchant-profile readerMerchant shipping configuration (read)Add Markets API or Contextual Product Feeds read pathread_markets or read_product_listings
Merchant-profile writerMerchant shipping configuration (write)Move writes to the Markets API with consentread_markets plus write_markets

An app can fall into more than one category. If it does, treat each category's migration separately so that a low-risk reader change does not get blocked behind a writer's reauthorization work.

Audit your GraphQL operations

Before you write migration code, inventory what your app actually touches. The audit tells you which category applies and how much reauthorization you owe.

Fields and mutations to search for

Search your codebase for every operation that reads or writes shipping configuration. Start with references to deliveryProfile, deliveryProfiles, deliveryProfileCreate, deliveryProfileUpdate, and the profile fields that describe locations, zones, and method definitions. Then search for anywhere your app already reads Market, so you know your current Markets coverage.

Separate the results into two lists: operations that touch the merchant's configuration and operations that touch your app's own profiles. Only the first list migrates to the Markets API. The second list stays on DeliveryProfile. Mixing the two lists is the most common way a migration accidentally breaks an app's own profiles.

How to determine profile ownership

For each delivery profile your code reads or writes, decide who owns it. A profile your app created and manages is app-owned and stays on the DeliveryProfile API. A profile that represents the merchant's own general shipping configuration is the surface that moves to the Markets API on a market-driven store. When in doubt, trace how the profile was created: if your app created it, your app still owns it.

Detect the shop's shipping model programmatically rather than guessing. On the preview store, this query distinguished the two worlds reliably:

QueryMarket-driven preview storeLegacy (non-preview) store
Market.delivery.shipping { isEnabled optionDefinitionsCount { count } }isEnabled true, option definitions presentisEnabled resolved null, config stayed in DeliveryProfile

Treat Market.delivery.shipping.isEnabled as the reliable programmatic detection approach: branch on it to decide whether to read merchant configuration from the Markets API or from DeliveryProfile. As an alternative signal you can inspect ShopFeatures or feature-preview status, but verify the exact current field name against Shopify's documentation at implementation time, because field names can change before general rollout.

Scopes and reauthorization inventory

Finish the audit with a scope plan. Reading merchant configuration through the Markets API needs read_markets, or read_product_listings if you read through Contextual Product Feeds. Writing merchant configuration needs read_markets plus write_markets. App-owned profile writes need no additional scope beyond your existing delivery-profile access. Any new scope forces merchant reauthorization and consent, so record which stores need it and stage the request. See

Shopify's access-scope documentation

for the current scope names and consent behavior.

Reader migration paths

Readers have two supported ways to obtain merchant shipping configuration on a market-driven store, plus a branch that keeps legacy stores working during rollout.

Contextual Product Feeds

If your app already consumes Contextual Product Feeds, or primarily needs the buyer-facing, market-contextual view of options, that path can supply the market-aware data with the read_product_listings scope. This suits readers that care about what a buyer in a given market would see rather than the raw merchant configuration objects.

Direct Markets API reads

For readers that need the merchant's configuration structure itself, query it directly through Market.delivery.shipping. The DeliveryOptionDefinition objects there carry the fields your reader previously pulled from delivery profiles, such as freeDeliveryMinimumValue, isActive, includedLocations, and includedCollections. This path uses the read_markets scope and gives you the per-market configuration model. Consult the

Markets API reference

for the current field set.

Branching on shop shipping model

During rollout you will have both market-driven and legacy stores installed at once, so a reader cannot commit to one API globally. Branch per shop on Market.delivery.shipping.isEnabled: when it is true, read merchant configuration from the Markets API; when it resolves null, read from DeliveryProfile as before. Keep the branch in one place so the rest of your app receives a normalized view regardless of which model the shop is on. If you already structure Admin GraphQL calls carefully, the patterns in the

Shopify Admin GraphQL patterns in Rails

guide apply directly to keeping this branch versioned and testable.

The same Admin GraphQL query returns Market.delivery.shipping.isEnabled true with option definitions on a market-driven-preview store and null on a legacy store

The same query returns isEnabled: true with option definitions on a market-driven-preview store and null on a legacy store, where configuration stays in the DeliveryProfile API. Verified August 3, 2026 at Admin API 2026-07; reverify the exact field name before implementation.

Writer migration paths

Writers carry the reauthorization step, so plan them deliberately. Keep app-owned writes and merchant-owned writes on separate paths.

App-owned profiles and coversAllItems

Writes to your app's own delivery profiles stay on the DeliveryProfile API and need no additional scope. The verified coexistence test showed an app-owned profile scoped to one variant working alongside market-driven configuration, with the default profile holding the remaining variants. When you scope an app-owned profile to specific variants, review how the general profile and coversAllItems interact so your profile covers exactly the items you intend and no others. Re-verify coversAllItems behavior against the

DeliveryProfile reference

at implementation time, because preview behavior can shift.

Markets API writes

Writes to the merchant's shipping configuration move to the Markets API on a market-driven store. Express rules as DeliveryOptionDefinition objects with the appropriate fields rather than as legacy method definitions. On the test store, for example, a free-shipping rule was represented as a single option definition carrying freeDeliveryMinimumValue, where the legacy model expressed the same intent as separate discrete DeliveryProfile method definitions. Your writer needs to map its internal representation onto whichever shape the target store expects.

Merchant consent and new scopes

Markets API writes require read_markets plus write_markets, and adding those scopes forces merchant reauthorization. Sequence this so the merchant grants consent before your writer attempts a Markets API write, and handle the interim state where a shop is market-driven but has not yet reauthorized. Until consent lands, a writer should avoid silently attempting merchant configuration writes on the legacy path, since those can become no-ops for the merchant-owned surface.

Build a safe transition layer

Rollout spans many months, so your app needs a transition layer rather than a hard cutover. The goal is one internal model that both shipping worlds map into and out of.

Legacy and market-driven adapters

Put an adapter behind a single interface. One adapter reads and writes merchant configuration through DeliveryProfile for legacy stores; the other reads and writes through the Markets API for market-driven stores. Select the adapter per shop using Market.delivery.shipping.isEnabled. The rest of your app should not know which adapter answered. This keeps the branch in one testable place and lets you retire the legacy adapter after the platform-wide transition completes.

Rate-parity assertions

Add assertions that an equivalent rule produces an equivalent buyer-facing outcome across both representations. On the test store, the market-driven free-shipping rule used a single option definition with freeDeliveryMinimumValue set to $70, so the Standard option was one price below the threshold and free at or above it—verified by crossing the threshold. The legacy model expressed the same intent as separate method definitions, and the buyer-facing outcomes were equivalent for the equivalent rule.

Treat the observed shape as one store's example

The $70 threshold and the single-option-definition shape were observations from one preview test store, not universal Shopify defaults. Write your parity assertions against the rule your app configures, not against these specific numbers, and confirm the option-definition shape for the store you are migrating.

Feature flags, telemetry, and rollback

Gate the market-driven path behind a feature flag so you can enable it per shop, watch it, and turn it off without a deploy. Emit telemetry that records which adapter served each shop, how detection resolved, and whether reauthorization completed. Keep a rollback path back to the legacy adapter for shops that are still legacy, and make sure rollback does not attempt to write merchant configuration on a store that has already moved to market-driven shipping.

Preview test matrix

Test the migration on a store with the feature preview enabled before you touch production. The matrix below covers the cases most likely to expose a broken branch. All of it is preview behavior, so re-verify against current documentation as the preview evolves.

Mixed product and location carts

Build carts that span the default profile and an app-owned profile, and carts that pull from multiple includedLocations. The coexistence test used exactly this shape: an app-owned profile held one variant while the default profile held the rest, with market-driven shipping enabled. Confirm your detection branch and adapters produce the right options for each slice of the cart.

B2B and regional markets

Because configuration is now per market, exercise more than one market. Test B2B and regional markets so you confirm your reader and writer resolve the correct Market.delivery.shipping for the buyer's context rather than assuming a single global configuration.

App rates plus merchant rates

Verify that app-owned rates and merchant-owned rates present together correctly, since the two ownership models coexist. If your app also configures combined or per-line shipping behavior, the companion

combined shipping rates guide

covers those interactions, and the

Buy Now, Ship Later guide

and

preorders guide

are worth checking if your app splits or defers fulfillment across these rates.

Rollout timeline and compatibility

Rechecked against Shopify's documentation on August 3, 2026: the feature preview and stable APIs were available in July 2026, merchant rollout begins in October 2026, and all shops are expected to transition by July 2027. The current stable API version referenced here is 2026-07.

Re-verify the timeline before you ship

These dates describe a preview and a phased rollout. Re-verify the rollout dates, eligibility, and the current stable API version against the

feature-preview documentation

before publishing or merging, since preview timelines change.

The practical consequence for your app is a long coexistence window. Between October 2026 and July 2027 you will have both legacy and market-driven stores installed simultaneously, so the per-shop detection branch and the transition layer are not optional niceties—they are how your app stays correct while the fleet migrates. Keep the legacy adapter in place until the transition completes, then remove it deliberately rather than assuming a single global cutover date. Shopify's

upgrade guide

is the authority for the current migration steps.

Failure modes to monitor after launch

After you enable the market-driven path, watch for the failure modes that come from the two shipping worlds diverging. None of these are performance claims; they are correctness signals to instrument.

  • Stale merchant reads: code still reading merchant configuration from DeliveryProfile on a market-driven store, returning an incomplete or outdated view. Alert when detection says market-driven but a read used the legacy path.

  • Silent write no-ops: merchant configuration writes sent on the legacy path to a market-driven store that effectively do nothing to the merchant-owned surface. Confirm writes land by reading back through the Markets API.

  • Missing reauthorization: a shop that became market-driven but never granted write_markets, leaving writers unable to persist merchant configuration. Track consent state per shop.

  • Detection drift: a shop whose isEnabled value changed after rollout without your app re-detecting it. Re-run detection rather than caching the model indefinitely.

  • App-owned profile regressions: an app-owned profile that stopped covering the variants you intended. Re-check coversAllItems and the default-profile interaction on affected stores.

For each signal, decide who is paged and what the recovery step is—re-detect, request consent, or fall back to the legacy adapter for a still-legacy shop—before launch rather than during an incident.

Sources and update triggers

This guide uses Shopify's official documentation as the authority for platform contracts. The first-hand observations—the detection query behavior, the verified coexistence of an app-owned profile with market-driven configuration, and the option-definition shape—were tested on a Shopify Plus development store with the market-driven shipping feature preview enabled on August 3, 2026, at Admin API version 2026-07. They reflect preview behavior, which can change before general rollout.

Upgrade your app for market-driven shipping, the feature-preview documentation, the Markets API reference, the DeliveryProfile reference, and the access-scope documentation were checked on August 3, 2026.

Review this guide when Shopify changes the market-driven rollout dates or eligibility, the exact detection field name, the Market.delivery.shipping or DeliveryOptionDefinition field set, the read_markets, write_markets, or read_product_listings scope behavior, coversAllItems semantics, or the current stable Admin API version. Before you publish or merge, re-verify the rollout dates, exact field and scope names, and the stable API version, and re-label any behavior that is still in preview.

Frequently asked questions

Does every Shopify app need to change for market-driven shipping?

No. Apps that only create and manage their own delivery profiles can continue to use the DeliveryProfile API. Apps that read or write the merchant's shipping configuration are the ones that need to migrate, because that configuration moves to the Markets API when market-driven shipping applies to a shop.

How do I detect whether a shop uses market-driven shipping?

On the preview store, querying Market.delivery.shipping { isEnabled optionDefinitionsCount { count } } returned isEnabled true with option definitions present where market-driven shipping applied, while on a legacy store Market.delivery.shipping.isEnabled resolved null and configuration stayed in DeliveryProfile. Treat this as the reliable programmatic signal, and verify the exact current field name against Shopify docs at implementation time.

Do app-owned delivery profiles still work under market-driven shipping?

Yes. In a verified test on the preview store, an app-created delivery profile scoped to a single product variant coexisted with the merchant's market-driven configuration, and Market.delivery.shipping.isEnabled stayed true. App-owned profiles remain a separate contract from merchant-owned configuration.

What access scopes does market-driven shipping require?

Reading merchant configuration through the Markets API uses read_markets, or read_product_listings through Contextual Product Feeds. Writing merchant configuration uses read_markets plus write_markets. App-owned profile writes need no additional scope beyond your existing delivery-profile access. Any new scope forces merchant reauthorization, so plan the consent step.

Is the buyer-facing shipping math changing?

For an equivalent rule, the migration changes where and how configuration is represented and owned, not the buyer-facing math. On the test store a free-shipping rule was expressed as a single option definition with freeDeliveryMinimumValue, versus separate legacy method definitions, but the buyer outcome was equivalent for the equivalent rule. That value was the test store's setting, not a Shopify default.

When does market-driven shipping roll out?

Rechecked against Shopify docs on August 3, 2026: the feature preview and stable APIs were available in July 2026, merchant rollout begins October 2026, and all shops are expected to transition by July 2027. Re-verify these dates against official documentation before you publish or merge, because preview timelines change.

Recommended reading

Keep exploring the playbook

Shopify Admin GraphQL patterns in Rails cover image
Developer guide
Guides
18 min readUpdated March 12, 2026

Shopify Admin GraphQL patterns in Rails

Production patterns for using the Shopify Admin GraphQL API from Rails, including service boundaries, pagination strategy, throttling, partial failure handling, and when to switch to bulk operations.

guidesShopify developerAdmin GraphQL API

Need an owned Shopify app workflow?

We design and build custom Shopify apps with reliable backends, webhooks, and operational escape hatches.

Discuss an app project