# How do split shipments and partial fulfillments in historical order data migrate to Shopify's fulfillment-order model without breaking the audit trail?

Reviewed by Martin Dejnicki, Director of SEO & AI Search · facts verified October 11, 2026 · canonical: https://deploi.ca/shopify/faq/split-shipments-partial-fulfillments-migration

## Short answer

Split shipments migrate as one fulfillment per shipment, not as the original fulfillment orders. Shopify creates fulfillment orders itself, and "It is not possible to manually create fulfillment orders" ([shopify.dev](https://shopify.dev/docs/api/admin-graphql/latest/objects/FulfillmentOrder), October 2026). Each fulfillment keeps its quantities and tracking but is dated at import, so add a fulfillment event to carry the original ship or delivery date ([shopify.dev](https://shopify.dev/docs/api/admin-graphql/latest/input-objects/FulfillmentEventInput), October 2026).

- **Fulfillment orders:** Created by Shopify only, at order creation. Shopify's routing assigns each order's items to locations after the order is created, and apps can't create fulfillment orders themselves (October 2026) ([Shopify developer docs, FulfillmentOrder](https://shopify.dev/docs/api/admin-graphql/latest/objects/FulfillmentOrder))
- **A migrated fulfillment's date:** The import date. Shopify's fulfillment input takes no date; Matrixify says an imported fulfillment "will be dated at the moment when it is being imported" (October 2026) ([Shopify developer docs, FulfillmentInput](https://shopify.dev/docs/api/admin-graphql/latest/input-objects/FulfillmentInput); [Matrixify, Import and Export Orders from Shopify in bulk with Matrixify](https://matrixify.app/documentation/orders/))
- **A fulfillment event's date:** Any time you supply. An event records "The time at which this fulfillment event happened", with statuses such as carrier picked up or delivered (October 2026) ([Shopify developer docs, FulfillmentEventInput](https://shopify.dev/docs/api/admin-graphql/latest/input-objects/FulfillmentEventInput); [Shopify developer docs, FulfillmentEventStatus](https://shopify.dev/docs/api/admin-graphql/latest/enums/FulfillmentEventStatus))
- **Fulfilled line items:** Never move to another location. Shopify: they "will always remain assigned to the original location", so the shipping location has to exist before the order imports (October 2026) ([Shopify developer docs, fulfillmentOrderMove](https://shopify.dev/docs/api/admin-graphql/latest/mutations/fulfillmentOrderMove))

## Deploi's call

Decide per cohort, not per order. We split historical orders into closed and open at the cutover date. We reproduce split-shipment detail only for the open cohort, where operations still needs it. The closed cohort gets one fulfillment carrying every tracking number, plus a link to the archive. That decision belongs to the operations lead, in writing, before the import is built.

**CUSTOMIZE: Rebuild each shipment as its own fulfillment when**

- The order is still open at cutover, so operations will work from it in Shopify.
- A carrier claim or service-level dispute can still name a shipment. Add a dated event to each fulfillment, which records "The time at which this fulfillment event happened" ([shopify.dev](https://shopify.dev/docs/api/admin-graphql/latest/input-objects/FulfillmentEventInput), October 2026).
- The shipping location exists in Shopify before the import, because fulfilled line items "will always remain assigned to the original location" ([shopify.dev](https://shopify.dev/docs/api/admin-graphql/latest/mutations/fulfillmentOrderMove), October 2026).
- Shopify will be the order source of truth after cutover. [Deploi's split shipments record](https://deploi.ca/shopify/build-vs-buy/split-shipments-multi-origin) keeps Shopify in that role with fulfillment state synced back, even beside an order management system (October 2026).

**WAIT: Import one fulfillment per order while**

- The order was delivered and closed before cutover.
- The [order creation input](https://shopify.dev/docs/api/admin-graphql/latest/input-objects/OrderCreateOrderInput)'s single [fulfillment](https://shopify.dev/docs/api/admin-graphql/latest/input-objects/OrderCreateFulfillmentInput) fits: all line items, one location, one carrier and every tracking number (shopify.dev, October 2026).
- The legacy warehouse or third-party logistics (3PL) provider is gone, and nobody will ask which one shipped.

## Why can't historical fulfillment orders be imported as they were?

Historical fulfillment orders can't be imported as they were, because Shopify generates fulfillment orders itself. In Shopify's words, a fulfillment order "represents either an item or a group of items in an Order that are expected to be fulfilled from the same location" ([shopify.dev](https://shopify.dev/docs/api/admin-graphql/latest/objects/FulfillmentOrder), October 2026). The same reference says "a background worker performs the order routing process which determines which locations will be responsible for fulfilling the purchased items" ([shopify.dev](https://shopify.dev/docs/api/admin-graphql/latest/objects/FulfillmentOrder), October 2026). It adds: "It is not possible to manually create fulfillment orders" ([shopify.dev](https://shopify.dev/docs/api/admin-graphql/latest/objects/FulfillmentOrder), October 2026).

That routing is the point. Fulfillment orders are Shopify's answer to a question it asks itself: where should this ship from? A historical order already knows where it shipped from, so the routing has nothing to decide and every reason to decide it differently. So a migration fits each historical shipment onto the fulfillment orders Shopify creates, rather than importing the old ones.

## What can a migrated split shipment keep, and what does it lose?

A migrated split shipment keeps what shipped, how many and under which tracking number. It loses its own timestamps and the old platform's status history.

**What each historical shipment keeps or loses when it becomes a Shopify fulfillment**

| Historical fact | Kept? | How |
| --- | --- | --- |
| Which line items shipped together | Yes | One fulfillment per historical shipment, created against Shopify's fulfillment orders |
| Quantities per shipment | Yes | Each fulfillment lists its line items and quantities |
| Carrier and tracking numbers | Yes | Tracking company, number and URL on each fulfillment |
| The date each shipment left or arrived | Partly | The fulfillment is dated at import; a fulfillment event carries the historical date |
| Which location shipped it | Yes, if the location exists before the import | Move unfulfilled line items to that location, which must stock the item, then fulfill them |
| The old platform's fulfillment statuses and holds | No | Shopify keeps its own fulfillment order statuses |

Sources: [Shopify developer docs, FulfillmentOrder](https://shopify.dev/docs/api/admin-graphql/latest/objects/FulfillmentOrder); [Shopify developer docs, FulfillmentEventInput](https://shopify.dev/docs/api/admin-graphql/latest/input-objects/FulfillmentEventInput); [Shopify developer docs, FulfillmentInput](https://shopify.dev/docs/api/admin-graphql/latest/input-objects/FulfillmentInput); [Shopify developer docs, fulfillmentOrderMove](https://shopify.dev/docs/api/admin-graphql/latest/mutations/fulfillmentOrderMove); [Matrixify, Import and Export Orders from Shopify in bulk with Matrixify](https://matrixify.app/documentation/orders/). Verified October 10, 2026.

For a closed order, one fulfillment can stand in for every shipment. The order creation input's fulfillment "will apply to all line items" ([shopify.dev](https://shopify.dev/docs/api/admin-graphql/latest/input-objects/OrderCreateOrderInput), October 2026) and names one location ([shopify.dev](https://shopify.dev/docs/api/admin-graphql/latest/input-objects/OrderCreateFulfillmentInput), October 2026). It takes every tracking number "if you're shipping the items in an order in several boxes", but Shopify applies one tracking company to all of them ([shopify.dev](https://shopify.dev/docs/api/admin-graphql/latest/input-objects/OrderCreateFulfillmentInput), October 2026). So the shortcut keeps the tracking numbers and loses which items shipped together.

## How does the audit trail change after migration?

The audit trail changes from chronological to compositional after migration. Before cutover it says this carton left this warehouse on this date. After cutover it says these three units were fulfilled under this tracking number against this order, on the import date. Matrixify, for example, says an imported fulfillment "will be dated at the moment when it is being imported" ([Matrixify](https://matrixify.app/documentation/orders/), October 2026).

The dates survive only where you write them back as fulfillment events. An event records "The time at which this fulfillment event happened" ([shopify.dev](https://shopify.dev/docs/api/admin-graphql/latest/input-objects/FulfillmentEventInput), October 2026), and its statuses include carrier pickup and delivery ([shopify.dev](https://shopify.dev/docs/api/admin-graphql/latest/enums/FulfillmentEventStatus), October 2026). For most audit purposes the composition is enough, because the usual question is "did the customer receive what they paid for" rather than "on which Tuesday".

Where the chronological record is genuinely required, say for a carrier claim or a service-level dispute, keep the old record, in the old format, for as long as the obligation runs. That's [the same answer return records get](https://deploi.ca/shopify/faq/returns-rma-records-migration-loop-aftership).

## In what order should locations and orders migrate?

Locations migrate first, then products, customers and orders, because Shopify assigns fulfillment orders to the locations that exist when each order is created. Shopify's own guide covers the rest of the sequence: "Import your products first, then your customers, and then any historical orders" ([Shopify Help Center](https://help.shopify.com/en/manual/migrating-to-shopify), October 2026).

Getting the location wrong is expensive to undo:

- **The import picks a default.** Matrixify, for example, says that if you leave the location empty, "the app will assume the first location from your Locations" ([Matrixify](https://matrixify.app/documentation/orders/), October 2026).
- **Fulfilled items never move.** Shopify can move unfulfilled line items to another location, but "Line items which have already been fulfilled can't be re-assigned and will always remain assigned to the original location" ([shopify.dev](https://shopify.dev/docs/api/admin-graphql/latest/mutations/fulfillmentOrderMove), October 2026). So the fix is a re-import of the affected orders.

## When should you not reproduce split shipments at all?

You shouldn't reproduce split shipments when the order is closed, the detail has no reader, or the rebuild costs more than the record is worth.

> **When not to do this**
> - **When the order was delivered and closed.** One fulfillment carrying every tracking number is the honest simplification. Record it as a deliberate choice in the migration mapping document, so nobody discovers it later.
> - **When nobody will ask which warehouse shipped.** If someone will, create the legacy location, import its history, then deactivate it, since a deactivated location "can't fulfill orders". Shopify says deactivated locations "don't count toward your location limit", which is 10 on Basic, Grow and Advanced and 200 on Plus. Deactivating "doesn't affect inventory quantities", so leave no stock there ([Shopify Help Center](https://help.shopify.com/en/manual/inventory-and-locations/locations/setup), October 2026).
> - **When the third-party logistics (3PL) provider is also changing.** Historical shipments attributed to a 3PL location that now belongs to a different provider will confuse that provider's own reconciliation.
> - **When order volume is very large and the value is presentational.** Rebuilding several shipments per order multiplies application programming interface (API) calls per order, so price it before committing.

Open orders that include discontinued products need one step first: [migrate each backordered product as a real variant](https://deploi.ca/shopify/faq/discontinued-products-open-backorders-migration). A line with no variant is a custom item. Shopify doesn't track custom items as inventory, and they can't go to automated fulfillment or shipping apps ([Shopify Help Center](https://help.shopify.com/en/manual/fulfillment/managing-orders/create-orders/create-draft), October 2026).

## Deploi's point of view

**Where we disagree.** Migration scopes treat fulfillment fidelity as a quality measure and try to reproduce every shipment. The constraint that makes this a losing trade is documented and rarely quoted: you cannot create a fulfillment order, and you cannot date a fulfillment. So maximum effort buys a reconstruction whose fulfillments carry the import date and whose real dates survive only as separately written events, which reads as precise and is not. A smaller import plus a retained archive is more truthful and costs less.

**What this page adds.** that fulfillment orders are generated by Shopify's routing worker and cannot be created or backdated, and that locations therefore have to exist before orders import, because fulfilled line items never move to another location afterwards.

## When this answer changes

- Shopify lets apps create or backdate fulfillment orders, or adds a date to its fulfillment input.
- Shopify allows fulfilled line items to move to another location.
- Shopify changes its location limits (10 on Basic, Grow and Advanced, 200 on Plus) or starts counting deactivated locations against them.
- Matrixify changes how it dates imported fulfillments or which location it assumes.

## Sources

1. [Shopify developer docs, FulfillmentOrder](https://shopify.dev/docs/api/admin-graphql/latest/objects/FulfillmentOrder), checked October 10, 2026
2. [Shopify developer docs, OrderCreateOrderInput](https://shopify.dev/docs/api/admin-graphql/latest/input-objects/OrderCreateOrderInput), checked October 11, 2026
3. [Shopify developer docs, OrderCreateFulfillmentInput](https://shopify.dev/docs/api/admin-graphql/latest/input-objects/OrderCreateFulfillmentInput), checked October 11, 2026
4. [Shopify developer docs, FulfillmentEventInput](https://shopify.dev/docs/api/admin-graphql/latest/input-objects/FulfillmentEventInput), checked October 11, 2026
5. [Shopify developer docs, FulfillmentInput](https://shopify.dev/docs/api/admin-graphql/latest/input-objects/FulfillmentInput), checked October 10, 2026
6. [Shopify developer docs, fulfillmentOrderMove](https://shopify.dev/docs/api/admin-graphql/latest/mutations/fulfillmentOrderMove), checked October 10, 2026
7. [Shopify developer docs, FulfillmentEventStatus](https://shopify.dev/docs/api/admin-graphql/latest/enums/FulfillmentEventStatus), checked October 10, 2026
8. [Shopify Help Center, Setting up and managing locations](https://help.shopify.com/en/manual/inventory-and-locations/locations/setup), checked October 11, 2026
9. [Matrixify, Import and Export Orders from Shopify in bulk with Matrixify](https://matrixify.app/documentation/orders/), checked October 10, 2026
10. [Shopify Help Center, Migrate to Shopify](https://help.shopify.com/en/manual/migrating-to-shopify), checked October 10, 2026
11. [Shopify Help Center, Creating draft orders](https://help.shopify.com/en/manual/fulfillment/managing-orders/create-orders/create-draft), checked October 11, 2026
12. [Deploi Build vs. Buy, Split Shipments on Shopify: Build Routing Rules or Buy an OMS?](https://deploi.ca/shopify/build-vs-buy/split-shipments-multi-origin), checked October 10, 2026, Deploi research
