# Write metafields with metafieldsSet

> Create or update up to 25 metafields on any resource in one atomic call with metafieldsSet, with compareDigest to avoid overwriting newer values.

Page: https://lintelagency.com/resources/graphql/metafields-set

## In short

To write metafields, call the metafieldsSet mutation with a list of inputs: ownerId, namespace, key, type and value. It creates the metafield if it doesn’t exist and updates it if it does. One call takes up to 25 metafields across any owners and is atomic: if one fails, none are saved. Pass compareDigest to update only when the stored value hasn’t changed.

## Facts

- **API:** Admin GraphQL API
- **Operation:** metafieldsSet
- **Access scope:** Write access to the owner resource, such as products or customers
- **Replaces (REST):** POST /admin/api/products/{id}/metafields.json and PUT /admin/api/metafields/{id}.json
- **API version:** 2026-10
- **Last checked:** 2 November 2026

## How to use it

1. Build one input per value: ownerId (any resource with metafields), namespace, key, type and value. The value is always a string, also for JSON, numbers and lists.
2. If a metafield definition exists for that namespace and key, you can leave out type; otherwise it’s required.
3. Send SetProductMetafields and check userErrors; nothing is saved when it isn’t empty.
4. For safe updates, read compareDigest first and send it back. Send compareDigest: null to write only if the metafield doesn’t exist yet.

## Code

### metafields-set.graphql

```graphql
mutation SetProductMetafields($metafields: [MetafieldsSetInput!]!) {
  metafieldsSet(metafields: $metafields) {
    metafields {
      id
      namespace
      key
      type
      value
      compareDigest
    }
    userErrors {
      code
      field
      message
    }
  }
}
```

### metafields-set.variables.json

```json
{
  "metafields": [
    {
      "ownerId": "gid://shopify/Product/1234567890",
      "namespace": "custom",
      "key": "material",
      "type": "single_line_text_field",
      "value": "100% linen"
    },
    {
      "ownerId": "gid://shopify/Product/1234567890",
      "namespace": "custom",
      "key": "care_guide",
      "type": "multi_line_text_field",
      "value": "Wash at 30°C.\nDo not tumble dry.",
      "compareDigest": null
    }
  ]
}
```

### metafields-set.response.json

```json
{
  "data": {
    "metafieldsSet": {
      "metafields": [
        {
          "id": "gid://shopify/Metafield/1111111111",
          "namespace": "custom",
          "key": "material",
          "type": "single_line_text_field",
          "value": "100% linen",
          "compareDigest": "<digest from the response>"
        },
        {
          "id": "gid://shopify/Metafield/1111111112",
          "namespace": "custom",
          "key": "care_guide",
          "type": "multi_line_text_field",
          "value": "Wash at 30°C.\nDo not tumble dry.",
          "compareDigest": "<digest from the response>"
        }
      ],
      "userErrors": []
    }
  }
}
```

## Limits and edge cases

- At most 25 metafields per call and a 10 MB request.
- Leaving out namespace uses your app’s reserved namespace, not custom.
- Values must match the type: list types take a JSON array as a string, references take GIDs, and the request fails when one doesn’t parse.
- To remove a metafield, use the metafieldsDelete mutation.

## Questions

### How do I update a product metafield with GraphQL?

Call metafieldsSet with the product’s GID as ownerId, plus namespace, key, type and the new value. It updates the existing metafield in place.

### Can I set metafields on different products in one call?

Yes. Each input has its own ownerId, so one call can write up to 25 metafields across many resources.

### What is compareDigest for?

It stops you from overwriting a value someone else changed after you read it. If the stored value no longer matches the digest, the mutation returns an error instead of saving.

## Shopify documentation

- [metafieldsSet](https://shopify.dev/docs/api/admin-graphql/latest/mutations/metafieldsSet)
- [Metafield data types](https://shopify.dev/docs/apps/build/custom-data/metafields/list-of-data-types)

## Related

- [Create a metafield definition](https://lintelagency.com/resources/graphql/create-metafield-definition)
- [Read metafields and metaobjects with the Storefront API](https://lintelagency.com/resources/graphql/storefront-metafields-and-metaobjects)
- [Configuring Functions with metafields, so rules change without deploys](https://lintelagency.com/journal/configuring-functions-with-metafields)

License: MIT. Free to use in your own store and in client work.
