Releases: saleor/saleor
3.20.90
What's Changed
- Fix race condition between:
- checkout complete process and TransactionEventReport mutation
- TransactionEventReport mutations processed at the same time
by @fowczarek in #17788
- Prefer input email over account email for checkout/order
Previously, we were always usecheckout.user.email
/order.user.email
, now if the email is explicitly provided bycheckoutEmailUpdate
mutation, we will prioritize the provided one.
by @korycins in #17766
Full Changelog: 3.20.89...3.20.90
3.21.2
What's Changed
- Use calculation module for building PaymentData object instead of direct plugin calls by @korycins in #17758
- Use dataloader in checkout resolver by @korycins in #17757
- Telemetry - Add explicit histogram bucket boundaries for metrics by @przlada in #17765
- Add possibility to use weighted shipping tax rate by @korycins in #17730
Full Changelog: 3.21.1...3.21.2
3.21.1
What's Changed
- Prevent race condition in TransactionEventReport resulting in invalid order status and payments amounts in (#17749) by @fowczarek
- Fix error when providing tracking as null to orderFulfill in #17738 by @korycins
Full Changelog: 3.21.0...3.21.1
3.20.89
Prevent race conditions in TransactionEventReport, resulting in invalid order status and payments amounts in #17742 by @fowczarek
Full Changelog: 3.20.88...3.20.89
3.21.0
Welcome to the Saleor 3.21 Release! This release is full of exciting updates — including a few major highlights, numerous improvements to the GraphQL API, and dozens of bug fixes. Read on to explore what’s new!
🔦 OpenTelemetry-based Distributed Observability
Due to the added complexity of composable architectures, observability and monitoring become critical for diagnosing issues and sometimes even determining if the system is operational. Observing each individual system independently may not provide all the answers, as in practice, there are cases where a solution is not transactional despite all of its individual services reporting “status green.” We recognize this challenge, and this release is our attempt to begin addressing it.
Historically, Saleor's observability layer relied on OpenTracing. It was highly detailed in terms of APM-level tracing output, but provided no support for metrics, which had to be calculated on the receiving end of telemetry. It also provided no easy way to correlate data from a large multi-service environment.
Saleor 3.21 replaces the old OpenTracing standard with its successor and the current industry standard, OpenTelemetry. It comes with support for metrics, and indeed includes some of the most valuable performance metrics. It also paves the way for adding logs and events, something future releases of Saleor will take advantage of.
⚠ This is a breaking change, so if you use the old OpenTracing feature in your custom deployment, you will need to move to an OTEL-capable collector.
We've also split the tracing telemetry stream into data that is generally useful for Saleor users and data that is useful for people working on the codebase. You can now subscribe to the "public" stream of telemetry and get the full picture without all the internal optimization details like individual SQL queries.
This is a huge step in cross-stack observability as it enables telemetry data to be streamed in OTLP format to your preferred monitoring solution, like Datadog or New Relic. Thanks to supporting the W3C Trace Context, signals from multiple services hosted by different vendors can be connected to tell the whole story of a page view that originates in your storefront, crosses into Saleor's core (perhaps numerous times due to parallel queries being executed), and then invokes a number of synchronous apps before a response is returned to the storefront for rendering.
Telemetry streaming for Saleor Cloud customers is currently in closed beta, so get in touch with our support for details about availability.
See the documentation for more information.
🔂 Sync webhooks circuit breaker
This feature may look small on the surface, but it can be a key factor in smoothly handling large events, like promotions during high season.
When enabled, the circuit breaker feature temporarily shuts down the app that generates a large number of webhook errors. This prevents the queue from clogging the whole stack and helps keep the store operational, even in high-stress conditions.
Before enabling the feature, you can set it up during a dry run, during which you can select which events should be only monitored and which should be blocked if the error threshold is hit.
The feature is disabled by default, so no breaking change will be introduced with the upgrade.
Find more details in the documentation.
💪 Strong validation of non-GraphQL APIs
Beyond the GraphQL API, Saleor includes several other APIs that traditionally lacked built-in validation — unlike GraphQL, which provides it out of the box. These include app manifest exchanges during app installation, custom JSON endpoints or sync webhooks that expect structured responses from apps.
In this release, we’re starting to address that gap by introducing strong validation to these APIs. In the first phase, we’re focused on sync webhooks, which are essential for integrating external shipping methods, payment gateways, and tax providers. For these webhooks, we’ve added response validation to ensure correct data types, string length constraints or min/max checks for numeric fields. If validation fails, Saleor will handle it gracefully depending on the webhook type:
- For shipping webhooks, log a warning and continue processing without the app response.
- For tax and payment webhooks, store errors in the appropriate model fields, such as
Checkout.tax_error
,Order.tax_error
, orTransactionEvent.message
, and break the checkout/order processing.
Full list of webhooks with support for strong validation:
- Shipping webhooks:
CHECKOUT_FILTER_SHIPPING_METHODS
ORDER_FILTER_SHIPPING_METHODS
SHIPPING_LIST_METHODS_FOR_CHECKOUT
- Tax webhooks:
CHECKOUT_CALCULATE_TAXES
ORDER_CALCULATE_TAXES
- Payment and transaction webhooks:
LIST_STORED_PAYMENT_METHODS
PAYMENT_GATEWAY_INITIALIZE_SESSION
TRANSACTION_INITIALIZE_SESSION
TRANSACTION_PROCESS_SESSION
TRANSACTION_CHARGE_REQUESTED
TRANSACTION_CANCEL_REQUESTED
TRANSACTION_REFUND_REQUESTED
Support for additional sync webhooks and custom endpoints is coming soon. In the future, we also plan to publish a static JSON Schema, similar to schema.graphql
for GraphQL API, to provide a fully documented and tooling-friendly format for these APIs. The best part? Validation is powered by Pydantic, a favorite in the Python community — making it fast, expressive, and easy to work with.
🛒 Configurable address storing strategy in checkout
Saleor 3.21 introduces more flexibility in how customer addresses are saved during checkout handling addresses in checkout. This release adds new saveBillingAddress
and saveShippingAddress
flags, giving you fine-grained control over whether shipping or billing addresses should be stored in a customer’s address book. This is how it works:
- Flags are only relevant when completing a checkout or draft order for a logged-in user.
- By default, Saleor still saves addresses for checkouts but not for draft orders — this behavior remains unchanged unless overridden.
- The new flags are now supported in these mutations:
checkoutCreate
,checkoutShippingAddressUpdate
,checkoutBillingAddressUpdate
,draftOrderCreate
,draftOrderUpdate
. - Flags must be provided together with a valid address input; otherwise, an error is raised.
Note that these settings are ignored for Click & Collect delivery methods — shipping addresses are not saved in those cases.
See the documentation for more details.
🚨 Breaking changes
⚠ Saleor 3.21 includes several breaking changes, such as dropping deprecated or unused plugins and plugin manager methods, changed API behavior - e.g. making certain fields required or altering returned values in specific cases. Below is a list of all the breaking changes. You’ll find a complete list of breaking changes below. For a detailed explanation of each change and guidance on how to adapt your code, refer to the Upgrade Guide.
Plugins
- Drop the invoicing plugin. For an example of a replacement, see https://docs.saleor.io/developer/app-store/apps/invoices.
- Drop the deprecated "Stripe (Deprecated)" payment plugin. If your codebase refers to
mirumee.payments.stripe
, you will need to migrate to the supported plugin,saleor.payments.stripe
. - Drop the
manager.perform_mutation
method. - Drop the
change_user_address
method from the plugin manager.
GraphQL API
- The
accountRegister
mutation no longer returns theID
of a user. - The
requestPasswordReset
mutation will not fail if thechannel
was not provided for non-staff users. - The
transactionId
argument ofOrderGrantRefundCreateInput
is now required. - Behavior change:
invoiceRequest
mutation no longer throws an error if only the app withINVOICE_REQUESTED
webhook is installed (without the invoice plugin). - Security update - the following mutations no longer reveal if an email is registered:
accountRegister
,confirmAccount
,requestPasswordReset
,setPassword
.
Metadata
- Behavior change:
transactionUpdate
now merges inputmetadata
andprivateMetadata
with existing values, instead of replacing them. MANAGE_ORDERS
permission is now required to update metadata onOrder
andOrderLine
types.
Webhooks
draftOrderUpdate
mutation no longer triggers theDRAFT_ORDER_UPDATED
webhook if no changes were made.orderUpdate
mutation no longer triggers theORDER_UPDATED
webhook if no changes were made.- Sync webhooks are no longer triggered during read-only queries. The following GraphQL queries no longer invoke sync webhooks or plugins for tax/shipping:
- Checkout queries
checkouts
,checkoutLines
,me.checkouts
:- No longer trigger
CHECKOUT_CALCULATE_TAXES
- No longer trigger
SHIPPING_LIST_METHODS_FOR_CHECKOUT
- No longer trigger
CHECKOUT_FILTER_SHIPPING_METHODS
- No longer trigger
- Orders queries
orders
,draftOrders
,me.orders
:- No longer trigger
ORDER_CALCULATE_TAXES
- No longer trigger
ORDER_FILTER_SHIPPING_METHODS
- No longer trigger
- Checkout queries
Miscellaneous
- Google Cloud Platform (GCP): The environment variable for private storage (e.g., webhook event delivery payloads) was renamed from
GS_MEDIA_BUCKET_NAME
toGS_MEDIA_PRIVATE_BUCKET_NAME
.
GraphQL API
- Checkout:
- Add
CheckoutCustomerNoteUpdate
mutation. - Add the
customerNote
field to theCheckout
type to make it consistent with theOrder
model. - Fix checkout
line.undiscountedTotalPrice
andline.undiscountedUnitPrice
calculation.- R...
- Add
3.20.88
What's Changed
- Make token generator class configurable by @wcislo-saleor in #17700
Full Changelog: 3.20.87...3.20.88
3.20.87
What's Changed
- Implementation of resource limits. by @fowczarek in #17685
Full Changelog: 3.20.86...3.20.87
3.19.99
3.19.98
3.20.86
What's Changed
- Enhance
TransactionEvent
handling; ensure that request event is correctly updated with all response data in case*_REQEST
event is returned in webhook response by @IKarbowiak in #17676 - Properly return CANCEL fulfilments in order resolver for app [3.20] by @lkostrowski in #17679
- Change
DEFAULT_MAX_DIGITS
to 20 by @IKarbowiak in #17678
Full Changelog: 3.20.85...3.20.86