Shopify Metaobjects in Production: When They Replace an App, and When They Become the Problem
Metaobjects promise a schema-first alternative to bolting on another Shopify app. Here's where they actually hold up in production, and where they quietly become your next migration.
Shopify metaobjects have been out long enough that they've stopped being a curiosity and started being a load-bearing part of real storefronts. We've shipped them for size guides, store locators, editorial content, bundles, ingredient tables, and localized policy pages. Some of those decisions still look smart eighteen months later. Some of them we'd undo tomorrow.
This is a field report on where metaobjects genuinely replace an app or a headless CMS, and where they quietly turn into a problem you'll have to migrate off later.
What metaobjects actually are (and aren't)
A metaobject is a merchant-defined content type with typed fields, stored inside Shopify and queryable through the Storefront and Admin APIs. Think of it as a lightweight CMS collection scoped to your shop. You define a type (e.g. size_guide), add fields (title, body, image, product_reference), and then create entries.
What they are:
- A typed content store, native to Shopify
- Referenceable from products, collections, pages, and other metaobjects
- Available through GraphQL with decent filtering
- Editable by merchants in the Shopify admin, with a reasonable UI
What they are not:
- A full CMS (no versioning, no draft/publish workflow beyond a status flag, no scheduled publishing without an app)
- A relational database (references are one-way and don't cascade)
- A search index (filtering is basic; no full-text)
- Free of limits (there are caps on definitions, fields per definition, and entries)
That last point matters more than the docs make it sound.
Where metaobjects earn their keep
We reach for metaobjects when three things are true:
- The content is structured and repeats across the store
- Merchants need to edit it without a developer
- The volume is measured in hundreds or low thousands, not tens of thousands
A few patterns that have worked well for us:
Size guides and spec tables
Apparel and hardware stores both need structured tables tied to product categories. A size_guide metaobject with name, category, rows (list of a sub-metaobject), and a products reverse-reference is clean, cacheable, and doesn't need a third-party app.
Store locators
A location metaobject with address, geo, hours (as a JSON field), and opening exceptions replaces an entire class of $19/month apps. The Storefront API query is trivial:
query Locations($first: Int!) {
metaobjects(type: "location", first: $first) {
nodes {
handle
fields {
key
value
reference {
... on MediaImage { image { url altText } }
}
}
}
}
}
Editorial modules on PDPs
Instead of stuffing rich content into a product's descriptionHtml, we model pdp_module metaobjects (hero, comparison, FAQ, testimonial) and reference an ordered list of them from the product. The theme or headless frontend renders each module by type. Merchants get composable PDPs without a page builder app burning your LCP.
Localized legal and policy content
A policy_block type with market, locale, body, and effective_date fields, referenced from the footer navigation. Cleaner than duplicating pages per market.
Where they quietly break down
The failure modes are less obvious, and they tend to show up six to twelve months in.
The reverse-reference tax
Metaobject references are one-directional. If a size_guide references products, you can query products from the guide easily. Going the other way — "give me the size guide for this product" — means either duplicating the reference on the product as a metafield, or filtering all guides client-side. We've done both. Both are ugly at scale.
Our rule now: decide the primary query direction before you define the schema, and put the reference on the side that will be queried from most often. If both directions matter, accept the duplication and write a small sync job.
Bulk editing and imports
The admin UI is fine for editing ten entries. It is punishing for editing five hundred. There's no native CSV round-trip for metaobjects the way there is for products. If your merchants need to bulk-update prices, translations, or availability on metaobject entries, you'll end up writing a custom admin tool or using the Bulk Operations API — which is doable, but it's engineering time you didn't budget for.
Search and filtering limits
Storefront API filtering on metaobjects is basic. You can query by type and paginate, but complex filters ("give me all recipe entries tagged vegan, sorted by prep time, containing an ingredient reference to product X") aren't native. You either denormalize fields, pull everything and filter in your app, or index into Algolia/Typesense/Meilisearch. For a headless build, we now assume an external search index for anything past a few hundred entries.
Definition and entry limits
Shopify enforces caps on the number of metaobject definitions per shop and fields per definition, and total entries are not infinite. For most stores this is irrelevant. For a catalog-heavy build — say, a marketplace with 20k vendor profiles as metaobjects — you'll hit walls. Check the current limits in the Shopify docs before you commit; they change.
No native workflow
There's a status (active/draft) flag, and that's it. No approval workflow, no scheduled publish, no diff between versions, no rollback. If your content team is used to Contentful or Sanity, metaobjects will feel primitive. This is the single biggest reason we've walked clients back from "metaobjects for all editorial" toward a hybrid setup.
Metaobjects vs. a headless CMS: how we decide
Roughly, we sort content into three buckets:
- Commerce-adjacent, structured, low editorial ceremony → metaobjects. Size guides, locators, spec tables, PDP modules, FAQ entries.
- Editorial with workflow, scheduling, or heavy media → Sanity or Contentful. Blog, landing pages, campaign hubs, anything with a marketing calendar.
- Truly product-shaped data → products or product metafields, not metaobjects. Bundles are the classic trap; they often want to be products, not a
bundlemetaobject, because they need inventory, pricing, and checkout behaviour.
The hybrid model is not architectural cowardice. It's just recognising that Shopify's content primitives are good at commerce-adjacent structure and mediocre at editorial workflow, and picking the right tool for each.
A schema you won't regret in a year
A few habits that have saved us from rework:
Name types like a database, not a marketing campaign
pdp_module_hero ages better than homepage_2024_launch_block. Types are hard to rename cleanly, and entries carry the type forever.
Keep fields flat where you can
Deeply nested metaobject-to-metaobject references are queryable but painful. Every level of nesting is another round trip or a bigger GraphQL query. Two levels deep is usually fine. Four is a smell.
Use JSON fields sparingly
JSON fields are tempting for hours-of-operation, feature flags, or config. They're also opaque to merchants and unindexable. If a merchant will edit it, make it a typed field. If it's developer-only config, put it in your app, not in a metaobject.
Handle references defensively on the frontend
References can be null (deleted entry, unpublished, wrong type). Every render path needs a fallback:
const sizeGuide = product.metafield?.reference;
if (!sizeGuide || sizeGuide.__typename !== 'Metaobject') {
return null;
}
Broken references silently rendering empty divs is the most common metaobject bug we see in code review.
Plan the migration path out
Before you commit a content type to metaobjects, ask: if we needed to move this to Sanity or Contentful in eighteen months, could we? For most structured data the answer is yes — a Bulk Operations query dumps it to NDJSON and you're done. For anything with heavy inter-entry references, the answer is "painfully". Model accordingly.
What we'd do
If you're standing up a new Shopify build in 2026, start with metaobjects for the obvious wins: locators, size guides, spec tables, PDP modules, structured FAQ. Skip the app subscriptions, keep the data close to the commerce layer, and enjoy the faster Storefront API queries.
Draw the line at editorial content that needs workflow, scheduling, or a real content team. That belongs in a headless CMS, referenced from Shopify by handle or ID. And keep bundles, subscriptions, and anything with inventory in products, not metaobjects — no matter how tempting the schema looks.
If you're already deep in metaobjects and hitting the walls we described, we've helped teams untangle this on both themed and headless builds — start with our e-commerce services or browse more storefront engineering breakdowns on the blog.
Want a team like ours?
72Technologies builds production software for the kind of teams who actually read this blog.
Start a projectKeep reading
Cart Abandonment Recovery on Shopify: What Actually Moves the Needle in 2026
Most cart abandonment recovery advice is stuck in 2019. Here's what we've seen actually recover revenue on Shopify stores in 2026 — and what's a waste of engineering time.
Shopify Collection Pages at 10,000 SKUs: Faceted Filtering Without Killing TTFB
Faceted filtering on large Shopify catalogs quietly destroys collection page performance. Here's how we architect it to keep TTFB under 400ms without a full replatform.
Shopify Functions vs Scripts: What Actually Runs at Checkout in 2026
Scripts are gone, Functions are the new contract. Here's what we learned porting discount logic, delivery customizations, and payment gating to Shopify Functions — and where the model still hurts.
