Skip to content

fix(caching-redis): read ioredis options from redisOptions for consistency with other Redis modules - #16101

Merged
kodiakhq[bot] merged 2 commits into
medusajs:developfrom
mvanhorn:fix/16099-caching-redis-nested-redis-options
Jul 21, 2026
Merged

fix(caching-redis): read ioredis options from redisOptions for consistency with other Redis modules#16101
kodiakhq[bot] merged 2 commits into
medusajs:developfrom
mvanhorn:fix/16099-caching-redis-nested-redis-options

Conversation

@mvanhorn

Copy link
Copy Markdown
Contributor

Summary

What — What changes are introduced in this PR?

The caching-redis provider now reads its ioredis options from a nested redisOptions object, the same shape cache-redis, locking-redis and event-bus-redis already use. The module's own options (ttl, prefix, compressionThreshold) are no longer forwarded to the Redis client. Top-level ioredis options continue to work and now log a deprecation warning. Fixes #16099.

Why — Why are these changes relevant or necessary?

Configuring the Redis cache is currently a coin flip. redisOptions is the shape every other Redis module in the repo accepts, and it is the shape workflow-engine-redis explicitly tells you to migrate to, but in caching-redis it is the one shape that does nothing. connection.ts destructured with a rest element and spread the remainder into the client, so redisOptions arrived at ioredis as a literal redisOptions key that it ignores, and the setting was dropped without a word:

const { redisUrl, ...redisOptions_ } = moduleOptions
const redisOptions: RedisOptions = { ...defaults, ...redisOptions_ }

The same line has a second effect in the other direction, as the triage bot noted on the issue: ttl, prefix and compressionThreshold are module options consumed elsewhere (connection.ts registers prefix; redis-cache.ts reads compressionThreshold), and they were being handed to a Redis client that has no use for them.

The nested shape is not a preference here, it is settled convention in this repo. workflow-engine-redis deprecates its flat options key with the words "Use redisOptions instead for consistency with other modules" and warns at runtime. caching-redis is the module that did not follow.

How — How have these changes been implemented?

types/index.ts gains redisOptions?: RedisOptions. The flat inheritance is kept behind a @deprecated-annotated alias so existing configs still typecheck.

loaders/connection.ts pulls the module's own keys out explicitly, prefers the nested object, falls back to the deprecated flat rest, and warns once when the fallback is used:

const {
  redisUrl,
  redisOptions: newRedisOptions,
  ttl: _ttl,
  prefix: _prefix,
  compressionThreshold: _compressionThreshold,
  ...deprecatedRedisOptions
} = moduleOptions

if (!newRedisOptions && Object.keys(deprecatedRedisOptions).length) {
  logger_.warn("[caching-redis] Passing ioredis options at the top level ... is deprecated. Please use `redisOptions` instead for consistency with other modules.")
}

const redisOptions: RedisOptions = {
  ...defaults,
  ...(newRedisOptions ?? deprecatedRedisOptions),
}

This mirrors workflow-engine-redis/src/loaders/redis.ts, which implements newRedisOptions ?? deprecatedRedisOptions plus a warning for exactly this migration. @medusajs/caching-redis is published at 2.17.2, so dropping the flat path outright would break deployments already passing it. Happy to take the breaking change instead if you would rather, since the package is young.

Testing — How have these changes been tested, or how can the reviewer test the feature?

New src/loaders/__tests__/connection.spec.ts, 9 tests, ioredis mocked to capture the constructor arguments. No Redis server required.

cd packages/modules/providers/caching-redis && yarn test

The tests pin the bug rather than restate the implementation. Reverting connection.ts and types/index.ts to their current state on develop while keeping the new tests fails 5 of 9:

Test Without the fix
forwards the redisOptions object to the ioredis client keepAlive is undefined (the reported bug)
does not forward module options to the ioredis client ttl: 60 reaches ioredis
lets redisOptions override a default got medusa-cache-redis, wanted custom-connection
still supports top-level ioredis options, with a deprecation warning no warning logged
prefers redisOptions over deprecated top-level options flat wins, got 1, wanted 10000

The other 4 pass with and without the change, which is the point: they cover the invariants this PR preserves (built-in defaults kept, no warning on the redisOptions path, prefix still registered, redisUrl still required).

Also run: full package suite 11/11 pass (the 9 new plus the existing redis-cache.spec.ts), prettier --check clean. tsc --build reports 4 TS2307 Cannot find module '@medusajs/framework/...' errors from unbuilt workspace deps, but the identical set appears on an untouched tree including in files this PR does not touch, so it is environmental and this change adds none.


Examples

// medusa-config.ts
module.exports = defineConfig({
  modules: [
    {
      resolve: "@medusajs/caching",
      options: {
        providers: [
          {
            resolve: "@medusajs/caching-redis",
            id: "redis-cache",
            options: {
              redisUrl: process.env.CACHE_REDIS_URL,
              ttl: 60,
              prefix: "mc:",
              // Now applied. Previously ignored by ioredis.
              redisOptions: {
                keepAlive: 10000,
                connectionName: "my-cache",
              },
            },
          },
        ],
      },
    },
  ],
})

The previous flat form still works, and logs a deprecation warning pointing at redisOptions:

options: {
  redisUrl: process.env.CACHE_REDIS_URL,
  keepAlive: 10000, // deprecated, still honored
}

Checklist

Please ensure the following before requesting a review:

  • I have added a changeset for this PR (@medusajs/caching-redis: patch)
  • The changes are covered by relevant tests
  • I have verified the code works as intended locally
  • I have linked the related issue(s) if applicable

Additional Context

Closes #16099. Reported by @thaind-taureau, who diagnosed the root cause and the exact lines; the triage bot independently confirmed both halves of the defect.

Prior art for the shape, all in this repo:

  • packages/modules/cache-redis/src/loaders/index.ts: const { redisUrl, redisOptions } = options then ...(redisOptions ?? {})
  • packages/modules/providers/locking-redis/src/loaders/index.ts: same
  • packages/modules/event-bus-redis/src/loaders/index.ts: same
  • packages/modules/workflow-engine-redis/src/loaders/redis.ts: newRedisOptions ?? deprecatedRedisOptions plus the deprecation warning this PR copies

The connection loader destructured module options with a rest element and
spread the remainder into the ioredis client. A nested redisOptions object
was therefore passed through as a literal redisOptions key, which ioredis
ignores, while the module's own ttl, prefix and compressionThreshold keys
were forwarded to the client instead.

Read redisOptions explicitly and keep the module options out of the client,
matching cache-redis, locking-redis and event-bus-redis. Top-level ioredis
options keep working and now log a deprecation warning, the same shim
workflow-engine-redis uses for this migration.

Fixes medusajs#16099
@mvanhorn
mvanhorn requested a review from a team as a code owner July 17, 2026 11:50
@changeset-bot

changeset-bot Bot commented Jul 17, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 769090b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 79 packages
Name Type
@medusajs/caching-redis Patch
@medusajs/medusa Patch
@medusajs/test-utils Patch
@medusajs/loyalty-plugin Patch
@medusajs/medusa-oas-cli Patch
integration-tests-http Patch
@medusajs/analytics Patch
@medusajs/api-key Patch
@medusajs/auth Patch
@medusajs/caching Patch
@medusajs/cart Patch
@medusajs/currency Patch
@medusajs/customer Patch
@medusajs/file Patch
@medusajs/fulfillment Patch
@medusajs/index Patch
@medusajs/inventory Patch
@medusajs/link-modules Patch
@medusajs/locking Patch
@medusajs/notification Patch
@medusajs/order Patch
@medusajs/payment Patch
@medusajs/pricing Patch
@medusajs/product Patch
@medusajs/promotion Patch
@medusajs/rbac Patch
@medusajs/region Patch
@medusajs/sales-channel Patch
@medusajs/settings Patch
@medusajs/stock-location Patch
@medusajs/store Patch
@medusajs/tax Patch
@medusajs/translation Patch
@medusajs/user Patch
@medusajs/workflow-engine-inmemory Patch
@medusajs/workflow-engine-redis Patch
@medusajs/draft-order Patch
@medusajs/oas-github-ci Patch
@medusajs/cache-inmemory Patch
@medusajs/cache-redis Patch
@medusajs/event-bus-local Patch
@medusajs/event-bus-redis Patch
@medusajs/analytics-local Patch
@medusajs/analytics-posthog Patch
@medusajs/auth-emailpass Patch
@medusajs/auth-github Patch
@medusajs/auth-google Patch
@medusajs/file-local Patch
@medusajs/file-s3 Patch
@medusajs/fulfillment-manual Patch
@medusajs/locking-postgres Patch
@medusajs/locking-redis Patch
@medusajs/notification-local Patch
@medusajs/notification-sendgrid Patch
@medusajs/payment-stripe Patch
@medusajs/core-flows Patch
@medusajs/framework Patch
@medusajs/js-sdk Patch
@medusajs/modules-sdk Patch
@medusajs/orchestration Patch
@medusajs/query Patch
@medusajs/types Patch
@medusajs/utils Patch
@medusajs/workflows-sdk Patch
@medusajs/http-types-generator Patch
@medusajs/cli Patch
@medusajs/deps Patch
@medusajs/eslint-plugin Patch
@medusajs/telemetry Patch
@medusajs/admin-bundler Patch
@medusajs/admin-sdk Patch
@medusajs/admin-shared Patch
@medusajs/admin-vite-plugin Patch
@medusajs/dashboard Patch
@medusajs/icons Patch
@medusajs/toolbox Patch
@medusajs/ui-preset Patch
create-medusa-app Patch
@medusajs/ui Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@medusa-os-bot

medusa-os-bot Bot commented Jul 17, 2026

Copy link
Copy Markdown

Thanks for the contribution! Initial automated review looks good.

Well-scoped fix for #16099: caching-redis now reads ioredis options from a nested redisOptions object (matching cache-redis, locking-redis, event-bus-redis, workflow-engine-redis) and stops forwarding module-own options (ttl, prefix, compressionThreshold) to the client. The flat top-level shape is kept behind a @deprecated alias with a runtime deprecation warning, preserving backward compatibility. Destructuring does not affect the later prefix registration. Includes a changeset and 9 focused unit tests with ioredis mocked. No security or performance concerns.

Triggered by: new PR opened

@shahednasser shahednasser left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM thanks!

@kodiakhq
kodiakhq Bot merged commit de9b40c into medusajs:develop Jul 21, 2026
51 of 56 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: caching-redis provider incorrectly parses redisOptions from moduleOptions

2 participants