Skip to main content

Dynamic complexity cost for metafieldsSet mutation

The metafieldsSet mutation now uses dynamic complexity costing. Instead of a flat cost for every call, a request's cost reflects how many distinct resources metafields were changed. Most apps need no changes, as updating a single resource remains cheap. Apps setting many metafields across many different owners may hit their rate limit faster. Apps are encouraged to batch metafield writes by distinct resource.

What changed

Previously, every metafieldsSet call cost a flat 10 points, regardless of how many metafields or resources it touched.

Now the cost is:

cost = 10 + Σ (number of distinct owners of a type × that type's weight)
  • Base cost: 10 points (unchanged)
  • Per distinct owner: the weight of that owner's type
Owner typeWeight
Order10
Product4
ProductVariant2
Collection1
Customer (including CustomerSegmentMember)1
Shop1
All other owner types0

Each owner is counted once per mutation invocation, however many metafields you set on it. Setting 10 metafields on one product costs the same as setting one.

Because metafieldsSet accepts at most 25 metafields per mutation, the highest possible cost for a single metafieldsSet invocation is 260 points (25 distinct orders).


Note

Cost is calculated per metafieldsSet invocation, not per request. If you use GraphQL aliases to send multiple metafieldsSet mutations in a single request, the base cost of 10 is charged for each alias, and owners are not deduplicated across aliases. A request with three aliases updating the same 25 distinct orders costs 780 points 3 × (10 + 25 × 10).


Example

This request writes to two products and one variant:

mutation {
metafieldsSet(metafields: [
{ ownerId: "gid://shopify/Product/1", namespace: "custom", key: "a", type: "single_line_text_field", value: "a" },
{ ownerId: "gid://shopify/Product/1", namespace: "custom", key: "b", type: "single_line_text_field", value: "b" },
{ ownerId: "gid://shopify/Product/2", namespace: "custom", key: "a", type: "single_line_text_field", value: "c" },
{ ownerId: "gid://shopify/ProductVariant/9", namespace: "custom", key: "a", type: "single_line_text_field", value: "d" }
]) {
metafields { key }
userErrors { field message }
}
}

It has two distinct Product owners (the two inputs for Product/1 count once) and one distinct ProductVariant owner, so it costs 10 + (2 × 4) + (1 × 2) = 20 points.

RequestPrevious costNew cost
5 metafields on 1 product1014
1 metafield each on 2 products and 1 variant1020
25 metafields across 25 metaobjects1010
1 metafield each on 25 orders10260

Who's affected

This change applies to any app that calls the metafieldsSet mutation in the Admin GraphQL API. Apps making high-volume, cross-owner requests (for example, updating 25 distinct orders in one request) will see an increase in query cost and may consume their API rate limit bucket faster. Apps updating single resources or using owner types with a weight of 0 will experience minimal changes to their API consumption.

Why this matters

Setting a metafield isn't finished when the write returns. For every distinct resource whose metafields change, Shopify runs follow-up work in the background: webhooks, cache invalidation, search reindexing, and other per-owner processing. That work scales with the number of resources a request touches, not with the number of metafields it sets.

Under a flat cost, a request setting 25 metafields across 25 different products costs exactly the same as one setting a single metafield on a single product, even though it generated 25 times the downstream work. Bursts of high-fan-out metafieldsSet traffic have saturated the job queues and datastores behind metafields, slowing metafield writes and other API traffic for every app and store sharing that infrastructure.

Pricing by distinct resource lines an app's point spend up with the work its requests actually cause, and stops a single burst from degrading the platform for everyone.

What to do

Most apps need no changes. A request that writes to a single resource, or to resources with a weight of 0, costs between 10 and 20 points.

If your app writes metafields at high volume, follow these optimization strategies:

  1. Group metafields by owner. Additional metafields for the same resource are free, so setting all of one product's metafields in a single call is cheaper than one call per metafield.
  2. Don't split a high-fan-out call to reduce cost. Every call pays the base 10 points, so splitting one request across 25 orders into 25 requests costs more in total, not less.
  3. Check the cost you were charged from the extensions.cost field in the response. Send the Shopify-GraphQL-Cost-Debug=1 header for a per-field breakdown.
  4. Handle throttling by backing off and retrying when THROTTLED is returned.

Related docs

Was this page helpful?