Now booking enterprise content platform builds for 2026. Contact us

All articles Practice 6 min read

Medusa 2.20.0 ships two security fixes and a relations limit on Store API routes

Medusa 2.20.0 landed on 2 September 2026 with two security fixes, a three-level relations limit on Store API routes, and the removal of the in-memory local search provider. Projects on @medusajs/search-local have a package to replace, and deep `fields` queries have a limit to raise or shorten.


Medusa published v2.20.0 on 2 September 2026. The release carries two changes its notes label as security fixes, four breaking changes, and a storage-format change in the Redis caching provider. For a team running Medusa in production, the breaking changes are the ones that decide when the upgrade happens.

The two security fixes

Payment providers are now validated against the cart’s region. Creating a payment session no longer trusts the payment provider ID passed in the request. The createPaymentSessionsWorkflow and the cart payment validation step verify that the chosen provider is enabled in the cart’s or payment collection’s region, and reject the request otherwise. In the notes’ own words, “Previously a store customer could initiate a payment session with any payment provider installed in the application, even one that was not linked to their region.”

Medusa states the follow-up plainly: “No action is required, but if your storefront relied on passing an arbitrary provider ID, make sure the provider is linked to the region the cart belongs to.”

MFA challenge enforcement on MFA routes. Medusa describes the second fix this way: “An attacker who already had a user’s valid password could use that token to regenerate the recovery codes through POST /auth/mfa/recovery-codes and use one of them to complete the challenge, or enroll and delete MFA factors.” The release tracks whether a user has completed MFA before allowing access to the recovery-codes route.

Medusa attaches no severity rating to either fix. A related change, Store order routes field expansion, blocked field-expansion pivot paths on store order routes to prevent information leakage (#16480); Medusa lists it under Bug Fixes rather than as a security fix.

The breaking changes

Four entries sit under Breaking Changes in the notes.

Relations limit on Store API routes (#16688). Store API routes now reject requests that expand more than three levels of relations in a single query, which the notes tie to the performance cost of deeply nested expansions. A request such as fields=*products.variants.options.values returns a 400 listing the offending fields. Two core Store routes raise that ceiling to four levels, GET /store/products and GET /store/products/:id. Admin routes are unaffected.

The limit is configurable in two places. storeRelationsLimit in projectConfig.http changes it for every Store route; the same key in the query configuration passed to validateAndTransformQuery changes it for one route and takes precedence over the application-wide value. A storefront that queries deep object graphs is the one to check first, because the failure arrives as a 400 on a request that worked in v2.19.

The in-memory local search provider was removed (#16545). @medusajs/search-local, the Orama-backed provider Medusa shipped in v2.19, is gone. Projects have to switch to @medusajs/search-postgres, the Medusa Cloud provider, or a custom provider. This is the entry most likely to stop an upgrade, because the package a project depends on no longer exists.

searchMany moved to the provider interface (#16643). Medusa pushed the method down to the search provider interface so each provider can optimise batch queries internally. Anyone maintaining a custom search provider has to implement it.

MFA routes now require a completed challenge (#16610). This is the breaking-changes entry for the MFA fix described above. Medusa’s wording is that MFA-protected routes now validate that the challenge has been completed before granting access.

db:migrate covers two of these. The notes call for it after upgrading for the relations limit, and again for search, where indexes are no longer created at application startup. One run handles both.

The Redis cache comes back cold

The caching provider changed its storage format, and the notes scope that change to projects using @medusajs/caching-redis. Entries now sit under a 64-bit hash key with a simplified storage mechanism, and entries written by earlier versions cannot be read in the new format, so they are invalidated on upgrade. Medusa says to expect a cold cache after deploying, and that no configuration change is required.

On a store under load, that lands in the deployment window: the first requests after the deploy do the work the cache was doing, until it fills again.

What the release does not change

v2.20.0 adds no new module and changes no workflow API. The additions sit inside the existing shape: fractional inventory quantities with units of measure across the Inventory Module, link modules, API routes and workflows; calculated shipping options in draft orders; and foundational vector search support for Medusa Search.

The Medusa-versus-hosted-platform trade-off is set out in our Medusa and Shopify comparison, and the cost of moving onto Medusa in the Magento to Medusa migration guide.

What to do with this release

Read the four breaking changes against your own project before scheduling anything. A project running @medusajs/search-local has a package to replace before it deploys at all, and a storefront issuing deep fields expansions has queries to shorten or a limit to raise. Custom search providers need searchMany implemented. Anything calling an MFA-protected route has to complete the challenge first, so integrations that hit those routes need checking. Beyond those four, the release asks for one db:migrate run and a deploy window that tolerates a cold cache.

Medusa followed with v2.20.1 on 3 September 2026. Its notes state that the allowed query config on a route and the http.restrictedFields config were not being applied unless the RBAC flag was enabled, and that the release fixes this by removing the RBAC flag requirement (#16704). Medusa’s wording is that it “highly recommend[s] updating to this version as this is a valuable security fix”, so 2.20.1 is the version to upgrade to.

FAQ

  1. Is the Medusa 2.20.0 upgrade urgent?

    Medusa labels two changes in this release as security fixes, and its notes state that no action is required for the payment-provider fix beyond one conditional check: if your storefront relied on passing an arbitrary provider ID, make sure the provider is linked to the region the cart belongs to. The release notes attach no severity rating to either fix. Your timing is set by the breaking changes: a removed package and a new query-depth limit can each stop a deployment. Medusa's follow-up patch v2.20.1, published 3 September 2026, does carry a stated recommendation to update, so target 2.20.1 rather than 2.20.0.

  2. What breaks if our storefront expands too many relations?

    Store API routes now reject a request that expands more than three levels of relations in a single query, and return a 400 error listing the offending fields. A query such as fields=*products.variants.options.values hits that limit. GET /store/products and GET /store/products/:id allow four levels. Admin routes are unaffected. You can raise the ceiling with storeRelationsLimit in projectConfig.http, or per route in the query configuration passed to validateAndTransformQuery, where the per-route value takes precedence.

  3. What does db:migrate do in the 2.20.0 upgrade?

    Two things in this release need it. The relations limit calls for db:migrate after upgrading, and search indexes are no longer created at application startup, so db:migrate is what creates them. Running it once covers both.

  4. What replaces @medusajs/search-local?

    Medusa removed @medusajs/search-local, the Orama-backed in-memory provider it shipped in v2.19, and names three replacements: @medusajs/search-postgres, the Medusa Cloud provider, or a custom provider. A custom provider now also has to implement searchMany, which moved to the search provider interface in this release.

Sources


Author

Paul Utr

Co-founder, Chief Growth Officer

Paul has been launching online platforms since his teens, picking up UX and product design by building them. He led the Mailgun redesign at Netguru and was Principal Designer at Ramp Network through its seed-to-Series-B run. At WAYF he leads design and organisational alignment, and watches how language carries through every product we ship.


Rather have it done for you? WAYF builds commerce platforms on Medusa.js, and can run them after launch under a separate maintenance engagement.

We're booking content platform
engagements for 2026.

Twenty-five minutes to walk through the work and decide if we're the right team for it. Scoping and a fixed price come after.