> For the complete documentation index, see [llms.txt](https://docs.pyck.cloud/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.pyck.cloud/shopify-app/routing.md).

# Sending data to several pyck tenants

Directing products, customers and orders at particular pyck tenants

Audience: Logistics Manager

One Shopify store can sync to several pyck tenants at once — a live warehouse and a test tenant, or two warehouses in different regions. Each of them is a **connection**, and each connection has a short **label** such as `production`, `stage` or `eu-prod`.

By default every tenant gets everything. Labels are how you narrow that down.

## The default: everything goes everywhere

A product, customer or order that carries no label at all is **broadcast** — delivered to every connection that is switched on and accepts broadcast.

That is the right behaviour most of the time. If you only have one connection, this is all that ever happens and you can stop reading here.

If no switched-on connection accepts broadcast, a record without a label goes nowhere: the sync fails and Activity says "No active pyck connection accepts broadcast entities."

## Narrowing with a label

Put a label on a record and it stops broadcasting. It goes to exactly the connections you named, and nowhere else. Naming a connection reaches it even if that connection has broadcast switched off.

There are two ways to write a label, and you can use either.

| Way                      | Where you set it                                                                                                          | Looks like         |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------- | ------------------ |
| The **pyck route** field | The pyck route field on the product, customer or order page in the Shopify admin. It is a list, so you can enter several. | `stage`            |
| A **tag**                | The record's tags                                                                                                         | `pyck-route-stage` |

Both do the same job. Use whichever fits how you already work — the field is easier to read at a glance, tags are easier to apply in bulk. Upper and lower case do not matter in either.

## The two ways add up — neither overrules the other

This is the part that surprises people.

The two signals are **combined**, not ranked. A record carrying the field `stage` and the tag `pyck-route-demo` goes to **both** `stage` and `demo`.

There is no way to say "ignore the tag, use the field". To stop a record reaching a tenant, remove the label that names it. Adding a different label somewhere else only adds a destination.

### Orders also inherit from their customer

An order also goes wherever its customer's labels point:

* the customer's `pyck-route-…` tags, read together with the order;
* the labels recorded for the customer the last time that customer synced. This is how the customer's **pyck route** field reaches the order.

So an order tagged `pyck-route-demo`, placed by a customer labelled `stage`, is delivered to **both**. Again, they add up.

Two things follow from this. A customer's pyck route field only reaches their orders after the customer has synced, so it does not work while customer sync is switched off. And a label on the customer that matches no connection stops every order of that customer, just like a label on the order itself.

## A label nobody recognises stops the sync

If you write a label that matches no connection on your store — a typo like `pyck-route-stagg`, or a connection that was deleted — the record **does not sync at all**. It is not partially delivered, and it does not quietly fall back to broadcast.

That is deliberate. You wrote a label because you wanted to restrict where the record goes. Treating an unrecognised label as "send it everywhere" would do the exact opposite of what you asked for and put your data in tenants you meant to exclude. Failing loudly is the safer answer.

The same applies to a label that names a connection you have switched off: the sync fails and says so, rather than delivering somewhere you did not name.

You will see the failure in **Activity**, with the offending label named: "Unknown pyck route label(s): …" or "Inactive pyck connection(s) named: …". Fix the label and the record syncs on its next change, or choose **Sync now** on the Home page.

A pyck route field the app cannot read, or one with an empty entry, stops the sync in the same way, with a message that the field "could not be resolved".

## Being sent an order and owning it are different things

Several tenants can hold the same order. Only the production connection may ship it.

When an order syncs, it is recorded with an **owner** only if the production connection is among its destinations: then production owns it. Every other tenant holding that order is a copy. A copy has the data so it can be displayed or tested against, and it can never ship the order: if it tries to report the order as shipped, it is refused. This is what stops one order being packed and posted twice, and what keeps a test tenant from marking one of your real orders as shipped.

There is one exception: an order that already existed in Shopify before the app first saw it — every order **Sync now** brings over, and an older order that is changed for the first time after you installed the app. If production is switched on, production owns such an order and receives it, even if its labels name only other tenants. Orders like this were placed before pyck routed anything, so production is assumed to be handling them. Test orders are never treated this way.

An order that does not reach a switched-on production connection has **no owner at all**. That is the normal state of every order while production is switched off, which is how you run a test tenant before going live. See [Running a test tenant before go-live](/shopify-app/test-tenant.md). Nobody can ship such an order until a sync routes it to production.

**Ownership is frozen once it is set.** Re-labelling an order afterwards moves where copies are delivered, but it does not move the owner — an order already being picked does not change hands mid-pick. The owner keeps receiving the order's updates even after the labels no longer name it, so a cancellation or address change still reaches the warehouse picking it. Ownership is only recalculated if the owning connection is deleted, switched off, or stops being the production connection. It then moves to production if the order reaches it, and to nobody otherwise.

An order whose owner has been switched off cannot be shipped by anyone until it syncs again. A copy does not inherit an order by outliving its owner.

## Test orders never reach production

An order Shopify marks as a test — placed through the Bogus gateway or Shopify Payments test mode — is excluded from the production connection no matter what labels it carries. It still reaches your other tenants, which is usually the point of placing it. Because it never reaches production, nobody owns it and nobody can ship it.

If production is the only place a test order would go — for example on a store with a single connection — it goes nowhere, and Activity shows a failed sync: "Every routed connection was excluded by the test-order rule."

## Only production writes stock back

Stock only ever travels back to Shopify from the production connection. A staging or demo tenant's quantities are not real, and two tenants writing the same Shopify numbers would overwrite each other. See [Warehouse stock](/shopify-app/stock.md).

## Summary

| Situation                                                 | Where it goes                                                                                                     |
| --------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| No label anywhere                                         | Every switched-on connection that accepts broadcast                                                               |
| No label, and no switched-on connection accepts broadcast | Nothing — the sync fails and is listed in Activity                                                                |
| Field says `stage`                                        | `stage` only                                                                                                      |
| Tag says `pyck-route-stage`                               | `stage` only                                                                                                      |
| Field says `stage`, tag says `pyck-route-demo`            | Both `stage` and `demo`                                                                                           |
| Order tagged `demo`, its customer labelled `stage`        | Both `demo` and `stage`                                                                                           |
| Label names only a non-production connection              | That connection, as a copy. No owner — unless it is an order that existed before the app first saw it (see above) |
| Label matches nothing                                     | Nothing — the sync fails and is listed in Activity                                                                |
| Label names a switched-off connection                     | Nothing — the sync fails and is listed in Activity                                                                |
| Test order                                                | Everywhere it is routed, except production. No owner. If that leaves nothing, the sync fails                      |
| Production is switched off                                | The other switched-on connections, as copies. No owner                                                            |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.pyck.cloud/shopify-app/routing.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
