-
-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Description
Package.json file
{
"@medusajs/medusa": "2.13.1",
"@medusajs/framework": "2.13.1",
"@mikro-orm/core": "6.4.16"
}Node.js version
v22.17.1
Database and its version
PostgreSQL 16 (AWS RDS)
Operating system name and version
Ubuntu 22.04
Browser name
No response
What happened?
PR #14150 fixed product update performance by switching MikroORM's query strategy. However, variant updates are still extremely slow for products with many variants.
We instrumented the variant update flow and found two bottlenecks:
Bottleneck 1: refetchEntity after variant update (the main issue)
The variant POST route refetches the full product using retrieveProductQueryConfig, which includes *variants, *variants.prices, variants.prices.price_rules.*, *variants.options, and *sales_channels.
Profiling on a product with 414 variants:
| Operation | Time |
|---|---|
updateProductVariantsWorkflow (entire workflow) |
3.5s |
refetchEntity with full product config (36 fields) |
11min 51s |
| Total POST response | 11min 54s |
The admin dashboard already fetches variants separately via GET requests using fields=-variants. The POST response doesn't need all variant data.
Bottleneck 2: updateVariants_() loads all sibling variants
updateVariants_() unconditionally loads all sibling variants with options for the checkIfVariantWithOptionsAlreadyExists validation, even when options aren't being changed. The admin UI always sends options in the payload (even unchanged), but the check is only needed when options actually differ.
Reproduction
Dataset: 636 products, 26,028 total variants (max 666 per product).
# Product update: fast after #14150 ✅
curl -X POST /admin/products/{id} -d '{"title": "Updated"}'
# ~100ms
# Variant update: still hangs ❌
curl -X POST /admin/products/{id}/variants/{variant_id} -d '{"title": "Updated"}'
# 11+ minutesExpected behavior
Variant updates should complete in under 5 seconds regardless of sibling variant count.
Actual behavior
Variant updates take 10+ minutes due to the post-workflow refetchEntity loading all variants with prices and options.