The order lands at 11:40 on a Saturday night. Four tins of hemp gummies, paid in full, shipping to an address in Boise.
Idaho is one of the states you cannot send that to. Your store took the money anyway, printed a label option, and sent a cheerful confirmation email. Nothing in Shopify knows which of your products are legal where, so nothing in Shopify had an opinion.
You will spend Monday refunding it and writing an apology that has to sound like a policy rather than a mistake. Then it happens again, because the setting you are about to go looking for does not exist.
Shopify restricts by zone, not by product
Shipping in Shopify is organised around zones. A zone is a list of countries and, inside a country, a list of states or provinces that you are willing to quote rates for. Uncheck Idaho and you have stopped shipping to Idaho. All of it. The gummies, the t-shirts, the sticker packs, the thing your best customer in Boise orders every month.
That is the answer merchants get first, and it is why the follow-up question always arrives about a week later. On November 13, 2023 someone asked the plain version, how to sell in the USA but not in all states, and was told to build a US zone and deselect the states they did not want. Correct, and store-wide, which is the opposite of what a restricted-product merchant needs.
The only product-level lever Shopify gives you is the shipping profile, which the documentation describes as a set of shipping rules for specific products and locations. You get up to 99 custom profiles on top of the general one. Move the restricted items into a profile of their own, then build that profile's zones without the states you cannot serve.
Notice what you have actually built. There is no rule anywhere saying this product may not go to Idaho. There is only an absence: no rate exists, so checkout has nothing to offer. The restriction is a hole in a table, and holes are hard to audit, hard to explain to a new hire, and completely silent when someone widens a zone six months from now.
The workaround, and the two ways it breaks
This approach has been the standing recommendation for years. On June 18, 2021 a merchant asked how to stop CBD shipments reaching four states, and a Shopify moderator answered the same day: make a custom profile for those products and make sure no shipping rates exist for those states. Clear, official, and it holds right up to the moment a customer puts two different kinds of thing in one basket.
The first break is the bill. Shopify's own documentation on combining rates across profiles says the separate shipping rates for each product are combined and a single shipping rate is displayed to your customer at checkout, and that rates with the same name are added together, even those in different shipping profiles. Added together. Not the higher of the two. A cart with one restricted item and one ordinary one pays shipping twice.
A merchant named it on May 8, 2023, in the flat tone of someone who had already argued about it: charging twice as it s the default shopify behaviour, it cannot be changed. Another came back to the same thread on June 17, 2024 to report that customers get double-charged shipping, and added the line that ends most of these threads. After talking to Shopify Support they have no solution.
The second break costs more and gets discussed less. When the restricted profile has no rate to the buyer's state, checkout does not quietly drop that one item. It fails the whole delivery step. The customer is told you do not ship to their address, and the legal half of the basket goes down with the illegal half. You have not blocked a sale you were not allowed to make. You have blocked a customer.
And the setup itself is fragile. On June 18, 2021 another merchant asked how to restrict a set of products to Virginia only, got the profile instructions, and came back on July 6, 2021 with three words that will be familiar to anyone who has tried this: this still isn't working. All fifty states were still showing at checkout. No staff member returned to the thread. Three years later, in June 2024, the answer posted there was the name of a paid app.
The community record
Laid end to end, the threads read like one conversation held five times with different people.
June 18, 2021, CBD into four states: use shipping profiles, answered by a moderator. June 18, 2021, products restricted to Virginia: use shipping profiles, still broken three weeks later. May 1, 2023, what is the best way to restrict certain states from purchasing certain products: profiles, and then the double-charge problem. June 13, 2023, a staff member arrives, asks about plan and carrier setup, and recommends an app. June 18, 2024, another app. October 22, 2025, a merchant needs to exclude specific areas within states and is told, correctly, that it cannot be done natively at all.
The most recent entry is the most telling. On August 7, 2026 a merchant returned to the 2023 thread to point out that checkout extensibility now gives apps a validation hook that avoids the double-charge trap, and framed it exactly right: there is still no native fix. Five years, and the platform answer is the same absence of a rate it was in 2021.
The map moves faster than the setting
Even a perfectly built profile is a photograph of the law on the day you built it.
Take hemp. Federal restrictions on hemp-derived THC products were due to take effect on November 12, 2026, then moved to December 11, 2026 by a continuing appropriations bill the House passed 370 to 48 on September 1, 2026. That is one date change, thirty days of notice, decided in a week. Underneath it sits a state patchwork that rewrites itself every legislative session. Nobody is going to remember to open the shipping settings.
Alcohol is worse, because the line is not the state line. Six states restrict direct-to-consumer shipment into dry territory, and in two of them the geography is real: Alaska has roughly 75 dry communities, Arkansas has 29 dry counties plus 24 that are partly wet and partly dry. Those boundaries are drawn by townships, precincts and local votes, not by postcodes or city limits, and a single local election redraws one.
Shopify cannot express any of it. A merchant asked on October 22, 2025 how to exclude specific areas within states and got the accurate answer the next morning: Shopify's native shipping zones only let you include or exclude entire states or countries, so there isn't a way to blacklist specific postcodes without using a workaround. A second reply said the same thing in fewer words. Shopify only lets you block shipping at the state level.
A shipping zone answers where will you quote a rate. Compliance asks what is this thing, and where is it allowed to arrive. Those are not the same question, and only one of them has a settings page.
What a real check has to know
Strip away the workarounds and the job has four inputs, none of which live in your shipping settings.
What the product is. Not a tag someone remembered to add, but the actual attribute the rule cares about: the cannabinoid, the alcohol by volume, the blade length, the aerosol classification, the nicotine. Your catalog knows it in titles, descriptions, ingredient lists and supplier sheets. Your shipping settings have never read any of that.
Where the order is really going, resolved below the state field when the rule is drawn below it. Then the rule itself, with a date on it, because a rule without a date cannot tell you whether it is stale. And finally a decision point early enough to matter, which means before the charge, not after it.
That last one rules out the tool most merchants reach for. Shopify Flow runs on orders that already exist, so the best it can do is tag, hold or cancel a sale you have already taken. For compliance that is a record of the problem, not a fix. The surface that can actually stop a checkout is a cart and checkout validation function, which runs on Shopify's servers and can block checkout progress when business rules are not met. Shopify's own documentation lists preventing shipping to restricted locations as an example. It is the right enforcement point. It is also an empty box until something tells it what the rules are.
What the automation actually has to do
As a Dugong playbook, in plain prose:
# trigger
Every cart that reaches
checkout, plus a nightly
catalog and rules pass
# steps
1. Classify each product
once: what it is, which
rules touch it
2. Resolve the address
below the state line:
county, township, ZIP
3. Check the cart line by
line, not as a single
basket
4. Block only the restricted
lines, let the rest of
the order check out
5. Say why, in plain words,
at the point where it
fails
6. Re-read the rule set
nightly and surface every
dated change
7. Log every block with the
rule and date that
caused it
Step one is the unglamorous half of the work and the half that decides whether the rest is worth anything. A rule set is useless against a catalog that has not been classified, and classification is exactly the sort of reading job that used to require a person with a spreadsheet and now does not.
Step four is where the money is. The profile workaround treats a cart as one decision, so a restricted item poisons the whole order. Checking line by line turns a lost order into a smaller one. The customer buys the three things you are allowed to send them, sees a clear note about the fourth, and does not go looking for a competitor who will ship all four.
Step five sounds cosmetic and is not. A generic no shipping available at this address message produces a support ticket and, often enough, a second attempt with a friend's address. Naming the item and the reason ends the conversation and leaves you with a record that you told them.
Step six is the one that ages well. When the hemp date moves by thirty days, or a state adds a product category in April, the workflow should notice, show you the change, and wait for you to accept it. An automation that silently starts refusing orders because it read a news item is worse than no automation. Propose, then enforce.
Why this is a compiler problem, not an app problem
Every app in these threads solves one slice. Some hide shipping methods by state code. Some validate postcodes. Some block countries. All of them need you to maintain the list, and none of them know what your products are.
The reason this stays unsolved is that the rule is not really about shipping. It is a sentence about your business, and it sounds like this: we do not send anything containing THC to the states that ban it, we do not send spirits into dry counties, we never send aerosols by air, and if a cart has one of those in it we block the line and sell the rest. That sentence is already complete. What has been missing is anything that can turn it into a check that runs at checkout.
That is the whole argument for describing workflows in language and compiling them. The merchant holds the judgment, which is theirs by law and by licence. The compiler holds the plumbing: the classification pass, the address resolution, the line-level decision, the validation function, the log. Nobody has to translate a compliance policy into an absence of shipping rates and then remember, a year later, why Idaho is missing from a table.
The workflow worth building this week
Start narrow. Take the one product category that actually carries risk, write the rule as a sentence with the states in it, and put the check in front of checkout rather than behind the order. Then add the nightly pass that re-reads the rules, because the date is the part that will catch you out.
Everything else is refinement. But the store stops taking money it cannot keep, and you stop finding out about it at 11:40 on a Saturday night.
If you are a Shopify merchant with a restricted shipping
story, the refund you wrote on a Monday, the cart that
charged twice, the customer who could not buy a t-shirt
because of a tin of gummies, the inbox is open:
field-notes@dugong.live. We are collecting
case studies for the next issue.