Shopify Metaobjects vs Metafields: When to Use Which (2026)

A wholesale apparel client pasted the same 18-row size chart JSON into 247 product metafields in November 2024. When the size standard updated in March 2026, the merchant edited the size chart on one product, asked the team to “roll it out,” and 246 PDPs went stale. The migration to a single metaobject took 90 minutes. The merchant now edits once, every PDP updates on the next request.

TL;DR: Metafields hold a typed value (text, number, file, JSON) on one Shopify resource. Metaobjects hold structured records that get referenced from many resources. Use metafields when the data is unique to one product, customer, or order. Use metaobjects when the same record gets reused or when editors need to manage the dataset in one place.

Why this matters for your store:

  • Duplicated values across hundreds of products cost merchant time on every update. Size charts, material taxonomies, and shipping rules are the three most common offenders.
  • A reference-based architecture lets editors update once, propagate everywhere. The alternative is a tooling project to bulk-edit metafields, which most stores never ship.
  • The wrong data model in Shopify is fixable, but the migration cost grows with catalog size. Picking the right model on day one saves a contractor day per 100 products you would otherwise re-migrate.

What a Shopify metafield actually is

A metafield is a single typed value attached to one Shopify resource. The resource can be a product, variant, customer, order, page, blog, blog post, collection, or the shop itself. The metafield has a namespace (custom, seo, theme, or your own), a key (the field name), and a value of one of the supported types: single_line_text_field, multi_line_text_field, number_integer, number_decimal, boolean, date, date_time, url, file_reference, json, rich_text_field, dimension, weight, volume, rating, color, and the reference types product_reference, variant_reference, collection_reference, and metaobject_reference.

In Liquid:

{# templates/product.liquid #}
{{ product.metafields.custom.material }}
{{ product.metafields.custom.shipping_class.value }}

For the rules around when .value is required (and when it returns blank because of metafield type), see my reference on the Shopify .value accessor for metafields. The short version: rich text, JSON, references, and any field accessed inside {% if %} need .value. Plain text and numbers in interpolation do not.

Metafields are scoped to the owning resource. A product metafield called custom.material lives on one product. Setting it on product A does not set it on product B. To share the value across products, you either duplicate it on every product (the wholesale apparel antipattern above) or you move to metaobjects.

For broader Liquid context including how render tag scope interacts with metafield access, see my Shopify Liquid development guide.

What a Shopify metaobject actually is

A metaobject is a structured record made of multiple typed fields, defined once and instantiated as standalone entries. Think of a metaobject definition as a class and each entry as an instance.

A size_chart metaobject definition might have fields:

  • name (single line text)
  • chart_image (file reference)
  • measurements (JSON)
  • last_updated (date)

Each instance (entry) of size_chart is a standalone record:

  • size_chart_xs_xl_unisex (entry 1, with values for the four fields above)
  • size_chart_eu_apparel (entry 2, different values)
  • size_chart_kids_4_12 (entry 3, different values)

Any product references the right entry via a single metaobject_reference metafield:

{# templates/product.liquid #}
{% assign chart = product.metafields.custom.size_chart.value %}
{% if chart != blank %}
  <h3>{{ chart.name }}</h3>
  <img src="{{ chart.chart_image | image_url: width: 800 }}" alt="{{ chart.name }} size chart">
  <pre>{{ chart.measurements }}</pre>
{% endif %}

The product holds a pointer. The metaobject holds the data. Edit the metaobject entry once, every product that points to it updates.

Metaobjects shipped on every plan with the 2023 Editions release. There is no plan-gated barrier. Basic Shopify stores get the same metaobject feature set as Plus, with higher per-resource ceilings on Plus.

The 7 use cases mapped to the right tool

Use case 1: product-specific copy a merchant edits per SKU. Use a metafield. The value is unique per product and has no reuse value.

Use case 2: a size chart shared across 50+ apparel SKUs. Use a metaobject. One entry, one edit, one rollout.

Use case 3: a custom shipping deadline a merchant adjusts seasonally per product. Use a metafield. The deadline is per-product and changes independently.

Use case 4: a list of authorized resellers shared across the entire shop. Use a metaobject. The resellers list is global, structured (name, region, URL), and changes as a unit.

Use case 5: a team member record (name, photo, bio, LinkedIn) referenced from the About page, the careers page, and individual press articles. Use a metaobject. The record is structured and reused.

Use case 6: a single piece of structured PDP data (warranty length, color hex). Use a metafield. The value is per-product, simple, and rarely reused.

Use case 7: a navigation taxonomy (material categories, room categories) used across collection filters and product detail pages. Use a metaobject. The taxonomy is shared infrastructure.

For implementation patterns of structured PDP data inside Custom Liquid sections, see my 10 Shopify Custom Liquid section examples post, which includes a metaobject-driven testimonial carousel as one of the templates.

Migrating 247 metafields to 1 metaobject: the FDB pattern

The apparel client from the hook had 247 size-chart metafields, one per product, each holding 4-8KB of JSON. The migration took 3 steps.

Step 1: define the metaobject in the admin. Settings > Custom data > Metaobjects > Add definition. Add the same fields the old metafield held (name, chart_image, measurements JSON, last_updated). This step is a 5-minute admin task.

Step 2: write a Matrixify export of every product’s custom.size_chart metafield. The export lands as a CSV with one row per product and one column per metafield. From that CSV, dedupe the JSON values to a set of unique size charts. On the wholesale client, 247 metafields collapsed to 11 unique charts.

Step 3: write a Matrixify import that creates 11 metaobject entries (from the 11 unique JSON values), then a second import that updates each product to reference the matching entry. The second import populates a new custom.size_chart_ref metafield of type metaobject_reference on each product. Once the theme reads from size_chart_ref instead of the old size_chart, the old metafield can be deleted.

Total time on a 247-product catalog: 90 minutes including testing. Total time saved on the next size standard update: 2.5 hours of editor work per release. The migration paid back inside the next product update cycle.

The pattern that breaks: looping over hundreds of metaobject entries inline

Metaobjects do not change the cost model of Liquid loops. If a section iterates over 200 metaobject entries inline, you pay 200 metaobject reads.

{# DON'T: 200 entry reads on every page load #}
<ul>
  {% for entry in shop.metaobjects.materials.values %}
    <li>{{ entry.name }} . {{ entry.density }} g/cm3</li>
  {% endfor %}
</ul>

The fix is the same as any other loop. Cap with limit: and break early once you have what you need. For the full set of break and continue patterns, see my Shopify Liquid for loop break and continue reference.

{# DO: capped iteration with early exit #}
{% assign rendered = 0 %}
<ul>
  {% for entry in shop.metaobjects.materials.values limit: 24 %}
    {% unless entry.featured %}{% continue %}{% endunless %}
    <li>{{ entry.name }} . {{ entry.density }} g/cm3</li>
    {% assign rendered = rendered | plus: 1 %}
    {% if rendered >= 8 %}{% break %}{% endif %}
  {% endfor %}
</ul>

How to decide on your next data field

Three questions, three minutes per field.

  1. Is this value unique to one resource, or does it repeat? Unique to one resource means metafield. Repeats across resources means metaobject.

  2. Will an editor need to update it in one place and have the change propagate? Yes means metaobject. No means metafield is fine.

  3. Does the value have internal structure (multiple typed fields), or is it a single value? Multiple fields means metaobject (or a JSON metafield, but metaobjects beat JSON for editor UX). Single value means metafield.

If any answer points to metaobject, the cost of using a metafield instead grows linearly with the catalog. Better to set up the metaobject definition on day one and reference it from a metaobject_reference metafield than to refactor 200 products in month nine.

The takeaway:

  • Use metafields for values unique to one product, customer, order, or page.
  • Use metaobjects for structured records reused across many resources or managed as a dataset.
  • Reference metaobjects from products via a metaobject_reference metafield, not a copied value.
  • Migrate large metafield duplicates to metaobjects with the Matrixify export-dedupe-import pattern.
  • Apply the same limit: and break discipline to metaobject loops that you apply to product loops.

Frequently Asked Questions

What is the difference between Shopify metafields and metaobjects?

A metafield is a single typed value (text, number, JSON, file, reference) attached to one Shopify resource: a product, variant, customer, order, page, blog, or shop. A metaobject is a structured record made of multiple typed fields, defined once and instantiated as standalone entries you reference from any resource. Metafields hold values; metaobjects hold reusable records. Use metafields when the data belongs uniquely to one product. Use metaobjects when the same record gets referenced from many products or sections.

When should I use a metaobject instead of a product metafield?

Use a metaobject when the same structured record gets referenced from multiple products, sections, or templates. Common cases: a `size_chart` reused across 200 apparel SKUs, a `material` taxonomy reused across furniture lines, a `team_member` record referenced from About, Press, and Careers pages. The DRY principle is the same as code: if you would otherwise paste the same JSON value into 200 product metafields, one metaobject definition with 1 referenced metaobject entry per product is cleaner and editable in one place.

Can I migrate existing metafields to metaobjects in Shopify?

Yes, with a 3-step pattern. First, define the metaobject schema in the admin. Second, write a script (Matrixify or the GraphQL Admin API) that creates one metaobject entry per unique value found across the existing metafield set. Third, write a second script that replaces each product's metafield value with a reference to the matching metaobject entry. The migration is non-destructive if you keep both fields populated during the rollout, then sunset the old metafield in the theme code once the reference path is verified.

Are metaobjects available on every Shopify plan?

Yes. Metaobjects ship on Basic, Shopify, Advanced, and Plus as of the 2023 Editions release. The free-form storefront and admin UI is identical across plans. Plus stores get a higher per-resource limit and bulk operations APIs. The Liquid access pattern (`shop.metaobjects.namespace.entries`) is the same on every plan.

How do metaobjects affect Shopify storefront performance?

Metaobjects render server-side via Liquid like every other Shopify resource. The render cost is roughly equivalent to a product metafield access for a single entry. Where metaobjects pay back is in source-of-truth consolidation: changing a size chart in one metaobject entry updates 200 PDPs that reference it, without a deploy. Performance regressions only appear when a section loops over hundreds of metaobject entries inline. The fix in that case is the same as any other loop: cap with `limit:` and break early.

Book Strategy Call