Shopify Functions

Subject: Metafield and Functions payload size limits prevent wholesale pricing for large product catalogs — requesting guidance on recommended architecture

Hi Shopify Support,

We are building a wholesale pricing app for B2B merchants. We are hitting size limits in two places and would like guidance on the recommended architecture for large stores.


Problem 1: Shop metafield size limit — storefront price display

We store wholesale plan configuration as a json type shop metafield (namespace: easywholesale, key: discount_cache, storefront access: PUBLIC_READ). Our Theme App Extension JavaScript reads this metafield and displays wholesale prices to eligible logged-in customers.

For each plan we store the list of product handles covered by the plan so the storefront JS can do instant price lookups without per-product API calls. A store with 15 collections can easily have 10,000+ product handles. Once the metafield JSON exceeds ~220KB, Shopify returns userErrors and the write fails — wholesale prices stop displaying on the storefront entirely.


Problem 2: Checkout discount function — plan data size limit

We use a Shopify Function (discount extension) to apply wholesale discounts at checkout. The function reads plan configuration from metafields on the global discount node to determine which customers and products are eligible. For large stores with many products across multiple plans, the combined plan data that the function needs to read also approaches size limits, causing the function to receive incomplete eligibility data and not apply the correct discount.


Our specific questions:

  1. What is the recommended way to make large product datasets (10,000+ handles) available to storefront JavaScript without per-product API calls at page load? Is there a storage option larger than the json metafield limit (e.g. Files API with public access)?

  2. For Shopify Functions, what is the input payload size limit and can it be increased for Partner apps? What is the recommended approach for functions that need to evaluate eligibility against a large product catalog?

  3. Is there an official pattern for wholesale/B2B pricing apps serving large catalogs on the storefront and at checkout? Other apps appear to handle this — are they using a different API or storage mechanism?

  4. Would product-level metafields (one metafield per variant storing its plan eligibility) be the recommended approach to avoid these combined-size problems? What are the rate limits for writing metafields across 50,000+ products when a plan changes?

App details:

  • App type: Public app (Shopify App Store)
  • Extensions: Theme App Extension + Shopify Function (discount type)
  • Storefront access: PUBLIC_READ shop metafield

Hi @Developer_EasyComm, most of what you’re hitting is documented, intentional platform behavior rather than bugs. Direct answers below.

Start here (Q3 — the B2B pattern): If your merchants use native B2B (companies/company locations), the platform-native mechanism is B2B catalogs + price lists: create a catalog (catalogCreate), attach a price list (priceListCreate), then add fixed variant prices to that price list (priceListFixedPricesAdd). Pricing resolves server-side, so it sidesteps both the metafield cap and the Functions 10,000-byte cap entirely, with correct prices on the storefront and at checkout and no function or lookup of your own — see Manage B2B catalogs. Note the plan limits: Basic/Grow/Advanced support B2B but cap you at 3 active catalogs, while Plus is unlimited with direct company-location assignment — many plans on a non-Plus store will hit that fast. The patterns below apply where native B2B doesn’t cover your pricing model (DTC customers, or eligibility logic beyond fixed/percentage pricing).

Metafield size (Problem 1): json metafields cap at 128KB (64KB for most types). Apps writing JSON before April 1, 2026 should be grandfathered at the old 2MB; new apps needing >128KB can request an exception via the form in the Metafield limits doc. Your ~220KB failure matches neither cap — worth checking which API version you write on, since 128KB only applies from 2026-04+.

Serving a large static handle list (Q1 — Files API): Upload the JSON as a generic file (stagedUploadsCreate with resource: FILE, then fileCreate), store the returned CDN URL in a small url metafield, and have your Theme App Extension JS fetch from the CDN. Keeps the metafield tiny, cheaper than an App Proxy, and fits a per-plan static list. Note the CDN URL is world-readable — same as your current PUBLIC_READ metafield, so not a regression. Use an App Proxy instead for per-customer pricing computed at request time, or the Storefront API to avoid shipping the whole catalog to the client.

Functions input (Problem 2 + Q2): Per the Function APIs docs: input 128 kB (scales above 200 line items), input query max 3000 bytes, output 20 kB, cost budget 30, and any single metafield value over 10,000 bytes returns as null — the likely cause of your incomplete eligibility data. These are fixed limits with no per-app exception, so reduce what the function reads: scope metafields to the level the function evaluates (per-product/variant the input query targets) rather than one combined blob on the discount node.

Per-variant metafields + rate limits (Q4): Per-variant metafields keep each function read under 10,000 bytes. For 50,000+ products, use metafieldsSet (25 per call) and/or bulk operations, pace against standard Admin API rate limits, and run plan changes as an async bulk job rather than a synchronous fan-out.