Saleor 3.23: Explicit Delivery Options
Saleor 3.23 replaces implicit shipping webhook triggers with an explicit mutation — giving storefronts full control over when delivery options are fetched and validated.
Checkout is the most performance-sensitive part of any storefront. In Saleor 3.23, we're making a fundamental change to how delivery options work — moving from implicit, behind-the-scenes webhook calls to an explicit, storefront-driven model.
Delivery options should refresh when you decide — not as a side effect of reading checkout data.
The Problem
In previous versions, simply querying fields like shippingMethods or availableShippingMethods on a Checkout object would implicitly trigger synchronous webhooks (SHIPPING_LIST_METHODS_FOR_CHECKOUT, CHECKOUT_FILTER_SHIPPING_METHODS). On top of that, checkout mutations would silently invalidate the shipping cache, causing additional webhook calls.
This meant every checkout query could fire external HTTP requests without the storefront knowing — adding latency, increasing costs, and making performance unpredictable.
What's New
Saleor 3.23 introduces three related changes:
deliveryOptionsCalculate
This is the only place that triggers shipping webhooks. Call it when you decide it is time to refresh options — not on every checkout query.
Checkout.delivery
Replaces the old deliveryMethod and shippingMethod fields with one structure that exposes the assigned
delivery and its shipping method details.
New checkout problems
Instead of silently invalidating or removing delivery methods, Saleor surfaces explicit problem types so the storefront knows what changed and what to do next.
How It Works
The new flow puts the storefront in control:
- Set the shipping address on the checkout
- Call
deliveryOptionsCalculateto fetch available shipping methods - Use the
idfrom the returneddeliverieslist asdeliveryMethodIdincheckoutDeliveryMethodUpdate - Monitor
checkout.problemsfor delivery state changes - Re-call
deliveryOptionsCalculatewhen problems indicate the delivery is stale
For click & collect, you still query checkout.availableCollectionPoints to get warehouse options, then pass the warehouse id to checkoutDeliveryMethodUpdate.
New Checkout Problems
Two new problem types replace the old implicit behavior:
CheckoutProblemDeliveryMethodStale
The assigned delivery method may be outdated — for example, after a voucher is applied, the shipping address changes, or line quantities are updated. The method is still assigned but hasn't been re-validated.
What to do: Call deliveryOptionsCalculate. If the method is still valid, the problem clears. If not, it becomes CheckoutProblemDeliveryMethodInvalid.
This problem does not block checkoutComplete — but if you proceed without resolving it, Saleor will implicitly validate the delivery during completion and return an error if it's no longer valid.
CheckoutProblemDeliveryMethodInvalid
The assigned delivery method is no longer applicable — it may have been deleted or no longer covers the checkout address.
What to do: Call deliveryOptionsCalculate to get valid options, then call checkoutDeliveryMethodUpdate with a new method. This problem blocks checkoutComplete.
Migration Guide
If you're upgrading from 3.22, here's what needs to change:
- Replace
checkout.shippingMethodsandcheckout.availableShippingMethodsqueries with calls to thedeliveryOptionsCalculatemutation - Replace
checkout.deliveryMethodandcheckout.shippingMethodwithcheckout.delivery - Handle the new problems — watch for
CheckoutProblemDeliveryMethodStaleandCheckoutProblemDeliveryMethodInvalidincheckout.problemsand respond accordingly - Update null checks — instead of checking
checkout.deliveryMethod == null, usecheckout.delivery == nullfor "not set" and checkcheckout.problemsfor "no longer valid"
The deprecated fields still work in 3.23 but will be removed in a future release. They continue to trigger implicit webhooks, so migrating early gives you the performance benefits immediately.
For the full upgrade guide, see the 3.22 to 3.23 migration docs.