Skip to content
All blog
Shopify API Integration Migration

Shopify bulk operations and when to use them

David 7 min read

There are two ways to get data out of a Shopify store, and choosing the wrong one is the difference between a historical import that finishes overnight and one that is still running next week.

Ordinary queries are for answering questions now. Bulk operations are for moving volume, and they work in a way that requires a different mental model.

How a bulk operation behaves

You submit a query and get back an identifier rather than data. Shopify runs it in the background, on its own schedule, taking as long as it takes. You check periodically whether it has finished. When it has, you are given a location to download a results file from.

Three things about that are worth dwelling on.

It runs outside the normal request budget. This is the whole point. A bulk operation does not spend the allowance that limits your ordinary queries, so it can return a volume of data no sequence of normal requests could — see Shopify API rate limits and query cost.

It is asynchronous, so your code has to wait properly. Submit, poll for status, download on completion, handle the case where it failed or was cancelled. That is more moving parts than a request that returns data, and each part needs its own error handling.

The result is a file, not a response. It arrives as one record per line, which is efficient to stream and awkward if you were expecting nested objects. Parsing it is its own small piece of work.

One at a time. An app can generally have only one bulk operation running against a store at once, so a scheduler has to queue them rather than firing several in parallel.

The flattening problem

This is the part that catches people, and it is worth understanding before you commission the work.

A normal GraphQL response gives you an order with its line items nested inside it. A bulk result gives you the order on one line and each line item on its own separate line, with a reference back to its parent.

So you receive a stream of mixed record types in no guaranteed grouping, and reassembling them into orders is your job. On a large import that reassembly cannot happen in memory, which means either processing in an order that lets you stream it or staging the records first and joining afterwards.

None of this is difficult. All of it is work that does not exist in the ordinary query path, and it is a common reason a quoted integration takes longer than estimated.

When to use which

The dividing line is volume, and it is not subtle.

Ordinary queries for anything triggered by an event or a person. An order just changed. A user opened a screen. A reconciliation needs one order's detail. All small, all immediate.

Bulk operations for anything sweeping. The initial historical import at go-live. A full catalogue export. A periodic complete reconciliation pull that checks nothing was missed. A month-end sweep of every order in the period.

The failure pattern is trying to do the second with the first. It technically works, it is bounded by the refill rate, and on a store with real history it is the reason an initial sync takes days — see what it takes to build a Shopify connector.

Where this shows up for a merchant

Two places, and both are worth knowing about in advance rather than during.

Go-live. Importing your history is a bulk operation, and it takes hours rather than minutes on a store of any size. This is normal and it should be scheduled deliberately — ideally finishing before you need the system, not while you are trying to use it.

The periodic completeness check. Notifications get missed, and a well-built integration therefore also pulls a full period occasionally and compares it against what it already holds. That sweep is a bulk operation, it usually runs overnight, and it is the mechanism that keeps your books complete rather than approximately complete — see Shopify webhooks and why they are not enough.

If a vendor cannot describe how the initial import works and how long it takes on a store your size, they have not done one at your scale.

The constraint that limits it

Bulk operations solve throughput. They do not solve access.

Anything gated behind a permission is still gated. Orders older than the standard window still need the relevant approval, and requesting them in bulk does not change that — see the Shopify sixty-day order window. Protected customer information still requires approval to read at all — see Shopify access scopes and protected customer data.

And data Shopify never held cannot be exported in any volume. For a Malaysian merchant the transaction fee and settlement fields are empty in a bulk result exactly as they are in a single query, because Shopify Payments is not available here — see what the Shopify Admin API actually returns.

Bulk operations make the reading fast. What is missing stays missing.

Common questions

What is a Shopify bulk operation?

An asynchronous query. You submit it and receive an identifier rather than data, Shopify runs it in the background, and when it completes you download the results as a file with one record per line. It runs outside the normal request allowance, which makes it the only practical way to move a large volume of data out of a store.

When should a bulk operation be used instead of a normal query?

For anything sweeping: the initial historical import, a full catalogue export, a month-end pull of every order in a period, or a periodic completeness check. Normal queries suit anything triggered by an event or a person, where one record is needed immediately. Attempting a large import through ordinary queries works but is bounded by the refill rate and can take days.

Why are bulk results harder to process?

Because they arrive flattened. An order appears on one line and each of its line items on separate lines with a reference back to the parent, in no guaranteed grouping, so reassembling complete orders is the integration's job. On a large import that cannot be done in memory, which means either streaming carefully or staging the records and joining afterwards.

Do bulk operations bypass Shopify permissions?

No. Anything gated stays gated — orders beyond the standard historical window still require the relevant approval, and protected customer information still requires approval to read. Data Shopify never captured, such as gateway fees and settlement detail for a Malaysian store, is absent from a bulk result exactly as it is from a single query.


Related: Shopify API rate limits and query cost · what it takes to build a Shopify connector · the Shopify sixty-day order window


See what you could build

Start a free trial and describe what your business needs in plain language — SmartB Studio builds the module for you.

Start free trial
Get started

No credit card · Cancel anytime · Your data stays yours