# Saleor 3.21.0 — Release & Upgrade Intelligence
- **Product:** Saleor (https://saleor.io)
- **Version:** 3.21.0
- **Released:** May 21, 2025
- **Impact Score:** 7/10
- **Breaking Changes:** Source flagged
- **Canonical Analysis:** https://changelogs.us/saleor/updates/3.21.0/

## Executive Summary (TL;DR)
Saleor 3.21.0. Source highlight: 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!

## Breaking Changes & Deprecations
- ⚠ 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.**
- 🚨 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](https://docs.saleor.io/upgrade-guides/core/3-20-to-3-21).
- ⚠**  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](https://docs.saleor.io/upgrade-guides/core/3-20-to-3-21).

## New Features
- Add `CheckoutCustomerNoteUpdate` mutation.
- Add the `customerNote` field to the `Checkout` type to make it consistent with the `Order` model.
- Add filterable subscriptions for checkout events (`checkoutCreated`, `checkoutUpdated`, `checkoutFullyPaid`, `checkoutMetadataUpdated`).
- Add prior price fields to `VariantPricingInfo`, `ProductPricingInfo`, and `CheckoutLine`.
- Add the `type` field to the `TaxableObjectDiscount` type.
- Add the `productVariants` field to `Product` instead of `variants`.

## Improvements
- Drop the `manager.perform_mutation` method.
- Improve error handling when trying to set invalid metadata. Now, invalid metadata should properly return `error.field` containing `metadata` or `privateMetadata`, instead of generic `input`.
- Improve status calculation for orders with waiting-for-approval fulfillments.

## Bug Fixes
- Fix checkout `line.undiscountedTotalPrice` and `line.undiscountedUnitPrice` calculation.
- Fix GraphQL explorer not displaying docs if the API is hidden behind a reverse proxy.
- Fix webhook `PRODUCT_VARIANT_METADATA_UPDATED` not being sent when the `productVariantUpdate` mutation was called. Now, when `metadata` or `privateMetadata` is included in `ProductVariantUpdateInput`, both `PRODUCT_VARIANT_METADATA_UPDATED` and `PRODUCT_VARIANT_UPDATED` will be emitted (if subscribed).
- Fix the `webhookTrigger` payload type for events related to `ProductVariant`.
- Fix the undiscounted price taxation in order calculations when the Avatax plugin is used.
- Fix a potential crash when checkout metadata is accessed with high concurrency.
