Upgrading From 3.20 To 3.21
To follow the zero-downtime strategy when upgrading to 3.21, It is recommended to first migrate to latest 3.20.X and turn on the Celery worker to process all data migrations asynchronously. Otherwise, you will need to downtime your solution to ensure correct data migration.
Authentication required for changing Order
and OrderLine
metadata​
The updateMetadata mutation for Order
and OrderLine
now requires the MANAGE_ORDERS
permission.
Once an order is created, customers cannot edit its metadata. However, merchants and apps with the necessary permissions can modify this data.
Fetching metadata remains unchanged.
Merging metadata in transactionUpdate
mutation​
The transactionUpdate mutation now merges the provided metadata and private metadata with existing values, instead of overwriting them. To delete a specific metadata entry, use the deleteMetadata mutation. For private metadata, use the deletePrivateMetadata mutation.
Deprecated manager.perform_mutation
method​
Note: This change only affects open-source Saleor users with custom plugins overriding the perform_mutation
plugin method.
As part of gradual plugin deprecation, Saleor 3.20 deprecates the perform_mutation
plugin hook. This method allowed to customize the mutation execution flow and call arbitrary logic during mutation execution. From now on, we recommend building such customizations via apps by reacting to webhooks triggered by mutations. The perform_mutation
plugin method will be removed in Saleor 3.21.
Deprecated WebhookPlugin
and webhook-related plugin hooks​
Note: This change only affects open-source Saleor users with custom plugins that override webhook-related plugin hooks (see the list below).
The WebhookPlugin
is deprecated in Saleor 3.20 and will be removed in Saleor 3.21, as all webhook-related functionality will be moved from plugin to core modules. Rationale behind this change is that webhooks are essential part of Saleor and should be available out of the box, without the need for additional plugins. As a result, multiple plugin manager hooks will be deprecated, as they are only used by the WebhookPlugin
.
If you have custom plugins that override any of the following plugin hooks, you should migrate your custom logic to Saleor App that listens to webhooks.
The list of deprecated plugin hooks is as follows:
account_change_email_requested
account_confirmation_requested
account_confirmed
account_delete_requested
account_deleted
account_email_changed
account_set_password_requested
address_created
address_deleted
address_updated
app_deleted
app_installed
app_status_changed
app_updated
attribute_created
attribute_deleted
attribute_updated
attribute_value_created
attribute_value_deleted
attribute_value_updated
category_created
category_deleted
category_updated
channel_created
channel_deleted
channel_metadata_updated
channel_status_changed
channel_updated
checkout_created
checkout_fully_paid
checkout_metadata_updated
checkout_updated
collection_created
collection_deleted
collection_metadata_updated
collection_updated
customer_created
customer_deleted
customer_metadata_updated
customer_updated
draft_order_created
draft_order_deleted
draft_order_updated
event_delivery_retry
fulfillment_approved
fulfillment_canceled
fulfillment_created
fulfillment_metadata_updated
get_shipping_methods_for_checkout
get_taxes_for_checkout
get_taxes_for_order
gift_card_created
gift_card_deleted
gift_card_export_completed
gift_card_metadata_updated
gift_card_status_changed
gift_card_updated
invoice_delete
invoice_sent
list_stored_payment_methods
menu_created
menu_deleted
menu_item_created
menu_item_deleted
menu_item_updated
menu_updated
order_bulk_created
order_cancelled
order_created
order_expired
order_fulfilled
order_fully_paid
order_fully_refunded
order_metadata_updated
order_paid
order_refunded
order_updated
page_created
page_deleted
page_type_created
page_type_deleted
page_type_updated
page_updated
payment_gateway_initialize_session
payment_gateway_initialize_tokenization
payment_method_initialize_tokenization
payment_method_process_tokenization
permission_group_created
permission_group_deleted
permission_group_updated
product_created
product_deleted
product_export_completed
product_media_created
product_media_deleted
product_media_updated
product_metadata_updated
product_updated
product_variant_back_in_stock
product_variant_created
product_variant_deleted
product_variant_metadata_updated
product_variant_out_of_stock
product_variant_stock_updated
product_variant_updated
promotion_created
promotion_deleted
promotion_ended
promotion_rule_created
promotion_rule_deleted
promotion_rule_updated
promotion_started
promotion_updated
sale_created
sale_deleted
sale_updated
shipping_price_created
shipping_price_deleted
shipping_price_updated
shipping_zone_created
shipping_zone_deleted
shipping_zone_metadata_updated
shipping_zone_updated
shop_metadata_updated
staff_created
staff_deleted
staff_set_password_requested
staff_updated
stored_payment_method_request_delete
thumbnail_created
transaction_cancelation_requested
transaction_charge_requested
transaction_initialize_session
transaction_item_metadata_updated
transaction_process_session
transaction_refund_requested
voucher_code_export_completed
voucher_codes_created
voucher_codes_deleted
voucher_created
voucher_deleted
voucher_metadata_updated
voucher_updated
warehouse_created
warehouse_deleted
warehouse_metadata_updated
warehouse_updated
checkout.shippingMethods
and checkout.availableShippingMethods
do not return external shipping methods if their currency differs from the checkout's currency​
If an app subscribed to SHIPPING_LIST_METHODS_FOR_CHECKOUT
returns an external shipping method with a currency different from the checkout's currency, Saleor will filter out that shipping method. As a result, external shipping methods with a different currency than the checkout's currency will not be returned via the API (in the checkout.shippingMethods and checkout.availableShippingMethods fields).
Any potential currency validation for external shipping methods on the frontend / app side is no longer necessary.
Blocked external calls for checkout and order bulk queries​
To enhance performance and efficiency, bulk queries that fetch multiple checkout or order objects will no longer trigger external calls to third-party services. The following synchronous webhooks will be affected:
CHECKOUT_CALCULATE_TAXES
webhooksORDER_CALCULATE_TAXES
webhooksSHIPPING_LIST_METHODS_FOR_CHECKOUT
webhooksCHECKOUT_FILTER_SHIPPING_METHODS
webhooksORDER_FILTER_SHIPPING_METHODS
webhooks
External calls from the AvataxPlugin will also be skipped.
Instead of recalculating taxes externally, the system will return pre-stored prices from the database. Additionally, only built-in shipping methods will be returned. The CHECKOUT_FILTER_SHIPPING_METHODS
and ORDER_FILTER_SHIPPING_METHODS
webhooks will not be triggered, and all built-in shipping methods will be listed as available.
Any external shipping methods assigned to the checkout will still be visible through denormalized data stored in the database.
Affected queries​
The following queries will not trigger external calls:
checkouts(...)
me.checkouts(...)
checkoutLines(...)
orders(...)
me.orders(...)
draftOrders(...)
Example of impacted queries​
{
checkouts(first: 10) {
edges {
node {
id
deliveryMethod {
... on ShippingMethod {
id
name
}
}
shippingMethods {
id
name
}
totalPrice {
gross {
amount
}
}
}
}
}
}
{
orders(first: 100) {
edges {
node {
deliveryMethod {
... on ShippingMethod {
id
name
}
}
shippingMethods {
id
name
}
total {
gross {
amount
}
}
}
}
}
}
The checkout
and order
queries will still work as before. If tax information is outdated, external calls will be made to recalculate taxes. External shipping methods and filters will be fetched if necessary.
checkout.privateMetadata
no longer stores external-shipping-method-id
​
The external-shipping-method-id
is no longer stored within checkout.privateMetadata
. To retrieve this ID, use the checkout.deliveryMethod
field instead.
checkoutDeliveryMethodUpdate
and checkoutShippingMethodUpdate
mutations do not trigger CHECKOUT_UPDATED
webhook or tax invalidation when adding the same method already assigned​
Previously, the checkoutDeliveryMethodUpdate
and checkoutShippingMethodUpdate
mutations would trigger the CHECKOUT_UPDATED
webhook and invalidate taxes regardless of whether the same delivery method was already assigned to the checkout.
Starting from version 3.21, if the same method that is already assigned to the checkout is provided, the CHECKOUT_UPDATED
webhook will not be triggered, and taxes will not be invalidated.
From Saleor's perspective, nothing has changed, as the checkout remains in the same state as it was before the mutation was called.
Introduced price freeze period for editable orders​
In previous versions, all editable orders (those with DRAFT
and UNCONFIRMED
statuses) refreshed their base prices
by fetching them from the current product catalog during each recalculation.
Additionally, all discounts were applied based on the latest reward values.
To ensure price consistency over time, regardless of updates to the product catalog, Saleor has introduced a price freeze period.
During this period, order lines use denormalized base prices instead of retrieving them from the catalog.
More details can be found here
- Draft orders: the base prices are frozen for 24 hours by default. This duration can be modified using the
Channel.draftOrderLinePriceFreezePeriod
setting. - Unconfirmed orders: the base prices remain frozen indefinitely, and this setting is not configurable.
- Other orders: remain unchanged and cannot be recalculated.