The 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 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 type | Weight |
|---|---|
Order | 10 |
Product | 4 |
| 2 |
Collection | 1 |
Customer (including ) | 1 |
Shop | 1 |
| All other owner types | 0 |
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 accepts at most 25 metafields per mutation, the highest possible cost for a single invocation is 260 points (25 distinct orders).
Cost is calculated per invocation, not per request. If you use GraphQL aliases to send multiple 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).
Cost is calculated per invocation, not per request. If you use GraphQL aliases to send multiple 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).
Note: Cost is calculated per <code><span class="PreventFireFoxApplyingGapToWBR">metafields<wbr/>Set</span></code> invocation, not per request. If you use <a href="https://shopify.dev/docs/api/usage/graphql-basics/queries#aliases">GraphQL aliases</a> to send multiple <code><span class="PreventFireFoxApplyingGapToWBR">metafields<wbr/>Set</span></code> 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 <code>3 × (10 + 25 × 10)</code>.
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 count once) and one distinct owner, so it costs 10 + (2 × 4) + (1 × 2) = 20 points.
| Request | Previous cost | New cost |
|---|---|---|
| 5 metafields on 1 product | 10 | 14 |
| 1 metafield each on 2 products and 1 variant | 10 | 20 |
| 25 metafields across 25 metaobjects | 10 | 10 |
| 1 metafield each on 25 orders | 10 | 260 |
Who's affected
This change applies to any app that calls the 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 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:
- 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.
- 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.
- Check the cost you were charged from the
extensions.costfield in the response. Send theheader for a per-field breakdown. - Handle throttling by backing off and retrying when
THROTTLEDis returned.