Backups

Step-by-Step: Backing Up and Restoring Shopify Metaobjects (Definitions and Entries)

A metaobject import has no undo. What a usable backup covers (definitions, entries and the links that point at them), and how to restore after a bad import or onto a new store.

There’s no rollback for a metaobject import. Once a value is overwritten, the old one is gone unless you saved it first, and Shopify’s help docs say plainly that deleting an entry can’t be undone. So “we’ll fix it if something goes wrong” really means “we’ll retype it from memory”.

A usable backup is three things, not one: the definition (the schema), the entries (the data), and the references on products and collections that point at those entries. CSV handles the second very well and the first badly. Here’s how to back up all three, and the restore steps for the three situations you’ll actually face.

What a backup has to cover

Part What’s in it Best format Why it matters
Definition Type, name, field keys and types, required flags, validations, capabilities, access, display-name field JSON Without it you can’t recreate the schema that the entries need
Entries Handle, every field value, status CSV, one file per definition The data itself; what most people mean by “backup”
Inbound references Which products and collections point at which entries CSV keyed by handles Deleting an entry removes it everywhere it’s used; recreating it doesn’t put those links back

The third row is the one people forget. Shopify’s help docs are explicit: when you delete an entry, it’s removed from anywhere it’s published or used in your store. Recreate it from a backup and it gets a new ID, so every product that used to point at it is now pointing at nothing.

Back up entries as CSV

One export per definition, named so you can find it later:

text

backups/
  2026-10-12/
    size_guide-2026-10-12.csv
    care_instructions-2026-10-12.csv
    designer-2026-10-12.csv
    definitions-2026-10-12.json
    product-references-2026-10-12.csv

When to take one:

  • Before every import. No exceptions, including “small” ones.
  • Before a theme or app change that touches custom data.
  • On a schedule for definitions that several people edit in the admin.

Check each export when you take it: it opens cleanly, the handle column has no blanks, and the number of rows matches the number of entries the admin shows for that definition. A backup you haven’t opened is a hope, not a backup.

Back up definitions as JSON, not CSV

A definition is nested: fields have validations, the definition has capabilities and access settings. Flattening that into a CSV loses information, so save it as the JSON the API gives you:

graphql

query DefinitionsBackup {
  metaobjectDefinitions(first: 50) {
    nodes {
      type
      name
      description
      displayNameKey
      access { admin storefront }
      capabilities {
        publishable { enabled }
        translatable { enabled }
        renderable { enabled }
        onlineStore { enabled }
      }
      fieldDefinitions {
        key
        name
        description
        required
        type { name }
        validations { name value }
      }
    }
  }
}

Save the response as definitions-YYYY-MM-DD.json. If you have more than 50 definitions, page through with after.

Two notes on ownership:

  • App-owned definitions (types starting $app:) can be declared in your app’s shopify.app.toml and kept in version control. That file is already a backup.
  • Merchant-owned definitions (the ones created under Settings > Custom data) can’t be declared in TOML; Shopify creates them through the admin or the GraphQL API only. The JSON export is their backup.

Back up the references that point at entries

If products point at entries through a metafield (for example custom.size_guide), export that relationship in a form that survives a restore: the product’s handle and the entry’s handle, not their IDs.

csv

product_handle,metafield,entry_type,entry_handle
slim-fit-chinos,custom.size_guide,size_guide,northline-slim-trousers
denim-jacket,custom.size_guide,size_guide,northline-regular-jackets
linen-shirt-blue,custom.care,care_instructions,linen-cool-wash

Your product export tool or a short API script can produce this. With handles on both sides, you can re-link products to entries on the same store or a new one.

Restore A: a bad import on the same store

The most common case. An import wrote wrong values into existing entries.

  1. Find the last good export, the one taken right before the bad import.
  2. Re-import it. Every row’s handle matches an existing entry, so every entry is updated back to its saved values. One exception to check: fields that were empty in the backup but filled by the bad import. If your tool skips empty cells instead of clearing the field, clear those by hand.
  3. Remove the extras. Re-importing doesn’t delete entries the bad import created. Export the definition now, put the good file in a sheet named Before, and flag handles that weren’t in it with =COUNTIF(Before!A:A,A2)=0. Every TRUE is an entry that didn’t exist before the bad import. Delete those in the admin, or with the API’s metaobjectDelete if there are many.
  4. Check the storefront on a few pages that use the restored data.

Restore B: entries were deleted

Deleted entries can’t be undeleted, so they have to be recreated:

  1. Import the entries from the backup CSV. Their handles no longer exist, so each row creates a new entry with the same handle and field values.
  2. Re-link products using the references backup. The recreated entries have new IDs, so every product metafield that pointed at the old ones has to be set again, by handle.
  3. Check list fields specifically. A list reference that contained a deleted entry has lost that item; re-add it.

Restore C: moving to a new or cloned store

Order matters, because references can only point at things that already exist:

  1. Definitions, recreated from the JSON backup.
  2. Products, collections and files, with the same handles as the source store.
  3. Entries that don’t reference other entries (size-chart rows, materials, designers).
  4. Entries that reference other entries (charts that use rows, collection stories that use designers).
  5. Product and collection metafields that point at entries, from the references backup.

Use handles all the way through. GIDs from the old store don’t exist on the new one; handles do, as long as you created things with the same handles. GIDs vs handles explains why this is the only approach that survives a move.

Run a restore drill once

The first time you restore shouldn’t be during an incident. On a development store:

  1. Take a full backup: definitions, entries, references.
  2. Break something on purpose. Import a file with a wrong column; delete three entries.
  3. Restore, following the steps above.
  4. Time it, and write down every step that wasn’t obvious.

Most teams find their gap in step 1: the definition or the references were never backed up, only the entries. Better to find that on a dev store.

For the checks that stop most restores from being needed, see catching bad metaobject data before import. For how definitions, entries and references fit together in a well-structured store, see the guide to structuring custom data on Shopify.

Stop typing metaobjects in one at a time.

Export a definition to see the exact columns, fill it in your spreadsheet, and every row is checked before anything touches your store.