---
title: "Announcing Cache Modules"
description: "We are excited to announce that we introduced cache modules into Medusa. This article gives an under-the-hood look at this feature."
url: https://medusajs.com/blog/announcing-cache-modules
last_updated: 2026-08-13T14:25:44Z
---

# Announcing Cache Modules

_Published 2023-04-04 by Frane Polić in Product_

[Medusa](https://medusajs.com/) provides commerce building blocks for developers to build rich commerce applications. With the latest evolution of our toolkit towards a more modular architecture, we are taking steps to make Medusa more agnostic to infrastructure. As a big step in this direction, we are excited to announce Medusa’s new cache modules.

In this article, we will look under the hood to see how cache modules work, which cache module you can use in your project today, and, finally, we will demonstrate how easily a Memcached module can be built.

## How it works

Cache modules in Medusa implement the [`ICacheService`](https://github.com/medusajs/medusa/blob/develop/packages/types/src/cache/service.ts) interface and are used internally to cache data like product prices and tax rates.

Medusa’s default starter project comes with an in-memory cache module (`@medusajs/cache-inmemory`) pre-installed, which uses a plain JavaScript Map object to store data. This is great for testing and development purposes, but not recommended for production environments. You can have one cache module installed at a time and for production environments, we have built a cache module that uses Redis (`@medusajs/cache-redis`). To enable the Redis cache module, simply install the package:

```typescript
yarn add @medusajs/cache-redis
```

And configure it in your `medusa-config.js` file:

```typescript
module.exports = {
  //...
  modules: {
      // ...
        "cacheService": {
            resolve: "@medusajs/cache-redis",
            options: { ttl: 30, redisUrl: REDIS_URL }
        }
    },
};
```

And that’s it. With just a couple of changed config lines, you use a different data store for our caching layer.

## Building a cache module

As mentioned above, we are making in-memory and Redis cache modules available today. Building a new cache module is, however, very easy if you have a different caching tool in place already or prefer another caching technology. To demonstrate how to build a cache module, we will implement `ICacheService` to work with Memcached. For communication with the Memcached instance, we will be using the [Memcached client for Node.js](https://www.npmjs.com/package/memcached).

The first thing to do is to create our project. We need a basic TypeScript project configured for Node. You can clone a preconfigured starter [here](https://github.com/fPolic/medusa-cache-memcached/tree/setup), and after running `yarn install`, start building.

To implement the service, create a new TypeScript file in `src/services`:

```typescript
// src/services/memcached-cache.ts

import Memcached from "memcached" // 1. Memcached client
import { ICacheService } from "@medusajs/medusa" // 2. Interface from medusa core that all caching modules need to implement

const DEFAULT_CACHE_TIME = 30 // 3. Keep data cached for 30 seconds

/**
 * 4. Module config type.
 * Defines which options can be passed to the module in the medusa-config file.
 */
type MemcachedCacheModuleOptions = {
  /**
   * Time to keep data in the cache (in seconds)
   */
  ttl?: number

    /**
        * Allow passing the configuration for Memcached client
        */
  location: Memcached.Location
  options?: Memcached.options
}

type InjectedDependencies = {}

class MemcachedCacheService implements ICacheService {
  protected readonly memcached: Memcached
  protected readonly TTL: number

  constructor(
        {}: InjectedDependencies,
    options: MemcachedCacheModuleOptions // 5. Options passed as module config will be injected here by the modules loader
  ) {
    this.memcached = new Memcached(options.location, options.options) // 6. Instantiate Memcached client for communication with the Memcached instance
    this.TTL = options.ttl || DEFAULT_CACHE_TIME
  }

 /**
   * Set a key/value pair to the cache.
   * It is also possible to manage the `ttl` through environment variables using CACHE_TTL. If the ttl is 0 it will
   * act like the value should not be cached at all.
   */
  async set(
    key: string,
    data: Record<string, unknown>,
    ttl: number = this.TTL
  ): Promise<void> {
    return new Promise((res, rej) =>
      this.memcached.set(key, JSON.stringify(data), ttl, (err) => {
        if (err) {
          rej(err)
        } else {
          res()
        }
      })
    )
  }

  /**
   * Retrieve a cached value belonging to the given key.
   */
    async get<T>(cacheKey: string): Promise<T | null> {
    return new Promise((res, rej) => {
      this.memcached.get(cacheKey, (err, data) => {
        if (err) {
          res(null)
        } else {
          if (data) {
            res(JSON.parse(data))
          } else {
            res(null)
          }
        }
      })
    })
  }

  /**
   * Invalidate cache for a specific key.
   */
  async invalidate(key: string): Promise<void> {
    return new Promise((res, rej) => {
      this.memcached.del(key, (err) => {
        if (err) {
          rej(err)
        } else {
          res()
        }
      })
    })
  }
}

export default MemcachedCacheService
```

And that’s it. The final thing to add is export from the `index.ts` file like so:

```typescript
// src/index.ts

import { ModuleExports } from "@medusajs/modules-sdk"

import { MemcachedCacheService } from "./services"

const service = MemcachedCacheService

const moduleDefinition: ModuleExports = {
  service,
}

export default moduleDefinition
```

You can find the entire implementation [here](https://github.com/fPolic/medusa-cache-memcached/blob/main/src/services/memcached-cache.ts).

To test the module with a Medusa instance, [link](https://classic.yarnpkg.com/lang/en/docs/cli/link/) your module project with a Medusa instance:

```typescript
// first build the package from the root
yarn build

// register package
yarn link
```

Next, we need to add this package to our Medusa project and tweak our `medusa-config.js` file:

```typescript
// in the root of your Medusa project run:
yarn link medusa-cache-memcached
```

```typescript
// medusa-config.js
module.exports = {
  // ...
  modules:{ 
        // ...
        "cacheService": 
            {
                resolve: "medusa-cache-memcached", 
                options: { location: "localhost:55000" }}
            },
};
```

With this example, we see how straightforward it is to build a (cache) module for Medusa. This, combined with the fact that Medusa is an open-source project, shows the advantages users of such projects have in terms of a growing ecosystem of existing modules.

## What’s next

The introduction of cache modules is a step in adding infrastructure agnosticism to Medusa’s architecture. This will make it easier to integrate Medusa into existing stacks and improve the developer experience. Our introduction of [EventBus modules](https://medusajs.com/blog/announcing-event-bus-modules) is a similar evolution to Medusa’s architecture. We are excited to see what you build with these new tools and can’t wait to launch more modules in the near future.

Learn more about [Cache Modules in our documentation](https://docs.medusajs.com/development/cache/overview).
