Settings & billing

The campaign storage limit

A technical storage cap that can silently stop active campaigns and discounts from reaching your storefront — even when you're under your plan limit.

There are actually two different limits that can stop a campaign from working. One is your plan's active-campaign limit (how many campaigns you're allowed to run at once). The other — the subject of this page — is a storage limit that has nothing to do with your plan. It's a hard size cap on the data the app saves to your store, and you can hit it even when you're well under your plan's campaign count. When you do, a campaign can look perfectly active inside the app but never appear for shoppers, or a discount can quietly fail to apply.

This page explains what that storage limit is, why it matters, how the app already works hard to keep you under it, what pushes you toward it, and exactly how to recover if you go over.

What this limit is

To show your offers on the storefront, the app saves your active-campaign configuration and your automatic-discount data into Shopify metafields. A metafield is a small storage slot attached to your shop (and to each discount). Your storefront and the discount engine read these slots to know which offers to show and which discounts to apply.

Shopify caps the size of a single metafield value at roughly 10,000 bytes (about 10 KB). To stay safely inside that ceiling, the app caps its own writes at 9,990 characters — leaving a small margin so a write never gets rejected by Shopify at the very edge.

The app gives you a way to see exactly how full this storage slot is. A usage check (the shop/metafield-limit endpoint, surfaced in the app's UI) returns four values:

FieldMeaning
limitThe byte ceiling the app checks against — 10,000 bytes.
currentSizeHow many bytes your current active-campaign configuration occupies right now.
isExceededtrue if your configuration has gone over the limit.
percentageHow full the slot is, as a percentage — this is the number to watch.

This limit is about the size of your configuration in bytes, not the number of campaigns. A handful of very complex campaigns can fill the slot faster than a larger number of simple ones. It is entirely separate from — and stacks on top of — your plan's active-campaign cap.

Why it matters

Think of the metafield as a fixed-size box. Every active campaign's configuration has to fit inside it for the storefront to read it. When your combined active-campaign configuration grows past the limit, the next write can't be saved — so the storefront simply doesn't receive that extra configuration.

The result is a confusing-looking failure:

  • A campaign can be Active in the app but not render on the storefront, because its configuration didn't make it into the metafield.
  • A discount can fail to apply, because the discount's own metafield (which the discount engine reads to decide which variants get discounted) couldn't hold all the data.

Crucially, this happens independently of your plan limit. You might be on a plan that allows 25 active campaigns and only have 8 active — fully within your plan — and still hit the storage limit because those 8 campaigns carry a lot of configuration between them.

This is the classic "but it says Active!" situation. If a campaign is Active in the app, passes its health checks, is within your plan's count limit, and still doesn't appear on the storefront, storage size is the prime suspect. Check your usage percentage before anything else.

How the app already protects you

The app does several things automatically to fit as much as possible inside the 10 KB box. You don't configure any of these — they're built in — but knowing they exist helps you understand why some changes shrink your usage more than others.

It compresses every campaign

Before writing to your shop metafield, the app compresses each active campaign by replacing long field names with short keys. Internally, names like funnel, settings, conditions, markets, rulesGroups, rules, and selector become one- or two-letter keys. This is invisible to you and dramatically reduces the byte size of each campaign without changing any behavior.

It excludes promo-code conditions from the storefront

Conditions that use promo-code rules are deliberately left out of the storefront metafield. Promo codes are evaluated server-side (privately, behind the app's proxy) rather than on the shopper's browser. This keeps promo-code logic off the storefront entirely — which both protects it and saves space in the metafield.

It splits oversized discount data across multiple discounts

Automatic-discount data also lives in metafields, capped at the same 9,990-character ceiling. When the data for a single automatic discount would exceed that limit, the app splits the conditions across multiple Shopify automatic-discount nodes so each stays under the cap. It distributes conditions into buckets that fit, creates new discount nodes as needed, and deletes ones it no longer needs. This means very large discount setups still work — they're just spread across more discount nodes behind the scenes.

These protections buy you a lot of headroom, but they're not infinite. If your configuration is large enough, you can still exceed the limit even with compression and splitting in effect.

What drives your size up

If your usage percentage is creeping toward 100%, one or more of these is usually the cause. They're listed roughly in order of how much weight they typically add:

DriverWhy it adds size
Many active campaignsEvery active campaign's configuration is written into the same shared box. More active campaigns = more bytes, even after compression.
Complex, multi-rule conditionsEach rule group and rule (subtotal thresholds, product matchers, etc.) is stored. Deeply nested or multi-branch conditions are heavier than a single simple rule.
Large product / variant selectorsA condition that targets many specific products or variants stores every selected ID. Wide selectors are one of the biggest, most avoidable space hogs.
Many markets / customer-tag rulesMarket targeting and customer-tag rules are stored per campaign. Long lists of markets or tags add up across all your active campaigns.
Lots of translatable contentTranslated storefront text (titles, descriptions, button labels) for each campaign is written to a shop metafield too. Many languages and long strings increase the footprint.

Because compression and promo-code exclusion already run automatically, the levers you control are the ones in this table: how many campaigns are active, how complex their conditions are, how wide their selectors are, and how much translatable text they carry.

Symptoms and how to read your usage

Watch for these signs that you're at or over the storage limit:

  • A campaign is Active in the app, passes health checks, and is under your plan's count limit — but doesn't appear on the storefront.
  • A discount that should apply doesn't, or applies inconsistently.
  • A newly activated campaign or a recent edit doesn't show up, while older campaigns still work — a tell-tale sign the new configuration couldn't be written.

To check, open the storage-usage indicator in the app and read the usage percentage:

  • Comfortably below 100% — you have headroom; new campaigns should write cleanly.
  • Approaching 100% — you're at risk; the next campaign or a more complex edit may not fit. Trim before adding more.
  • At or over 100% (isExceeded is true) — new configuration is already being rejected. Some active campaigns or discounts may not be reaching the storefront right now.
Screenshot: The app's storage-usage indicator showing the percentage of the campaign metafield that is currently in useAdd a real image by setting the `src` prop.
Read the usage percentage before adding or expanding campaigns — if it's near 100%, trim first.

How to fix it when you're near or over the limit

The goal is simple: reduce the byte size of your active-campaign configuration, then re-sync so the smaller configuration is written to the storefront. Work through these from easiest to most impactful.

Deactivate or delete unused campaigns

Set any campaign you don't currently need to Inactive, or delete it outright. Only Active campaigns are written to the storefront metafield, so flipping a campaign to Inactive immediately frees its share of the box. This is usually the fastest single win.

Simplify conditions and selectors

Open your heaviest campaigns and reduce condition complexity: collapse multiple overlapping rules into fewer rules, and narrow wide product/variant selectors. Targeting a collection or a small set of products is far lighter than enumerating hundreds of individual variants.

Reduce the number of variants targeted

If a campaign targets a large list of specific variants, cut it down to the variants that actually matter. Variant lists are one of the largest contributors to size, so trimming them frees the most space per edit.

Trim translatable content

Remove translations you don't need and shorten overly long translated strings. Each language's text for each campaign adds to the footprint, so pruning unused languages or verbose copy reclaims space.

Re-sync your campaigns

After trimming, run a manual campaign sync in the app. This re-reads all your campaigns and rewrites every metafield target with the now-smaller configuration. Until you re-sync, the storefront keeps serving the old (oversized or stale) data — the sync is what actually pushes your changes live.

After you re-sync, re-open the storage-usage indicator and confirm the percentage has dropped and isExceeded is back to false. That's your confirmation that the new configuration fit and was written successfully.

Edge case: a partial write can leave the storefront stale

The app writes to several metafield targets in parallel, and it's built to tolerate partial failures — so if one write fails, the others can still succeed. That resilience has a side effect worth understanding.

A metafield write can partially fail, leaving your storefront state stale. Because the writes don't all-or-nothing together, one target can end up out of step with the others — for example, your campaign data updates but the cart-validation or translatable-content target doesn't. The symptom looks just like a storage-limit problem: a campaign or discount behaves as though a recent change never happened.

The fix is the same lever you use for the storage limit: run a manual campaign sync. A sync re-reads all campaigns from scratch and rewrites every metafield target together, bringing them back into agreement and clearing out any stale state left by a partial write. If a campaign or discount is behaving oddly after an edit and your usage percentage is healthy, a manual sync is the first thing to try.

Quick recap

  • The storage limit is a ~10 KB (10,000-byte) cap on the metafield that holds your active-campaign configuration; the app writes up to 9,990 characters.
  • It's separate from your plan's active-campaign limit — you can hit it while under your plan.
  • Over the limit, an Active campaign may not render and a discount may not apply.
  • The app already compresses campaigns, excludes promo-code conditions from the storefront, and splits large discount data across multiple discounts.
  • Watch the usage percentage; if it nears 100%, deactivate/simplify/trim, then re-sync.
  • After a partial write, a manual sync rewrites every target and clears stale storefront state.

On this page