Skip to main content

Modules

Medusa’s architecture is built around modules - isolated, pluggable packages that provide specific commerce functionality. Each module is independently developed, tested, and can be customized or replaced.

What are Modules?

Modules are self-contained packages that encapsulate:
  • Data models - Database entities and schemas
  • Business logic - Services that implement domain operations
  • Type definitions - TypeScript interfaces and DTOs
  • Configuration - Module registration and joiner config
Modules are designed to be swapped, extended, or replaced without affecting other parts of your application. This modular architecture enables you to customize only what you need.

Module Structure

Every module follows a consistent structure:
import { Module, Modules } from "@medusajs/framework/utils"
import { ApiKeyModuleService } from "@services"

export default Module(Modules.API_KEY, {
  service: ApiKeyModuleService,
})
Source: packages/modules/api-key/src/index.ts

Module with Providers

Some modules support multiple provider implementations:
import { Module, Modules } from "@medusajs/framework/utils"
import AnalyticsService from "./services/analytics-service"
import loadProviders from "./loaders/providers"

export default Module(Modules.ANALYTICS, {
  service: AnalyticsService,
  loaders: [loadProviders],
})
Source: packages/modules/analytics/src/index.ts

Core Commerce Modules

Medusa includes 30+ built-in commerce modules organized by domain:

Product & Catalog

Modules.PRODUCT
  • Product - Product catalog, variants, options, categories, collections
  • Pricing - Price lists, rules, currency management
  • Inventory - Stock levels, inventory locations
  • Promotion - Discounts, campaigns, promotions

Orders & Checkout

  • Cart - Shopping cart management
  • Order - Order processing and management
  • Payment - Payment processing and providers
  • Fulfillment - Shipping and fulfillment providers

Customer & Auth

  • Customer - Customer profiles and management
  • Auth - Authentication providers and sessions
  • User - Admin users and permissions
  • RBAC - Role-based access control

Regional & Multi-currency

  • Region - Regional settings and configurations
  • Currency - Currency definitions and conversions
  • Store - Store settings and metadata
  • Sales Channel - Multi-channel commerce

Platform Services

  • API Key - API key management (secret & publishable)
  • Notification - Notification providers and templates
  • File - File storage providers
  • Translation - Multi-language support
  • Analytics - Analytics providers
  • Tax - Tax calculation providers
  • Settings - Application settings

Infrastructure

  • Event Bus - Event distribution (local/Redis)
  • Caching - Cache providers (in-memory/Redis)
  • Locking - Distributed locking
  • Workflow Engine - Background workflow execution (in-memory/Redis)
  • Index - Search and indexing
  • Link Modules - Dynamic entity relationships

Module Resolution

Modules are registered in the dependency injection container using the Modules enum:
import { Modules } from "@medusajs/framework/utils"
import type { IProductModuleService } from "@medusajs/framework/types"

export const createProductStep = createStep(
  "create-product",
  async (data: CreateProductInput, { container }) => {
    const productModule = container.resolve<IProductModuleService>(
      Modules.PRODUCT
    )
    
    const product = await productModule.createProducts(data)
    return new StepResponse(product, product.id)
  },
  async (productId, { container }) => {
    const productModule = container.resolve<IProductModuleService>(
      Modules.PRODUCT
    )
    await productModule.deleteProducts([productId])
  }
)
Source: packages/core/core-flows/src/api-key/steps/create-api-keys.ts:35-36

Module Service Interface

All module services implement a consistent interface pattern:
export class ApiKeyModuleService
  extends MedusaService<{
    ApiKey: { dto: ApiKeyTypes.ApiKeyDTO }
  }>({ ApiKey })
  implements IApiKeyModuleService
{
  protected baseRepository_: DAL.RepositoryService
  protected readonly apiKeyService_: ModulesSdkTypes.IMedusaInternalService<
    InferEntityType<typeof ApiKey>
  >

  constructor(
    { baseRepository, apiKeyService }: InjectedDependencies,
    protected readonly moduleDeclaration: InternalModuleDeclaration
  ) {
    super(...arguments)
    this.baseRepository_ = baseRepository
    this.apiKeyService_ = apiKeyService
  }

  __joinerConfig(): ModuleJoinerConfig {
    return joinerConfig
  }
}
Source: packages/modules/api-key/src/services/api-key-module-service.ts:44-67
When extending or replacing modules, ensure your custom module implements the appropriate IModuleService interface to maintain compatibility with workflows and API routes.

Module Configuration

Configure modules in your medusa-config.ts:
import { defineConfig, Modules } from "@medusajs/framework/utils"

export default defineConfig({
  modules: [
    {
      resolve: "@medusajs/file",
      options: {
        providers: [
          {
            resolve: "@medusajs/file-s3",
            id: "s3",
            options: {
              file_url: process.env.S3_FILE_URL,
              access_key_id: process.env.S3_ACCESS_KEY_ID,
              secret_access_key: process.env.S3_SECRET_ACCESS_KEY,
              region: process.env.S3_REGION,
              bucket: process.env.S3_BUCKET,
            },
          },
        ],
      },
    },
  ],
})

Custom Modules

Create custom modules to extend Medusa:
import { Module } from "@medusajs/framework/utils"
import { MyCustomService } from "./services/my-custom-service"

export const MY_CUSTOM_MODULE = "myCustomModule"

export default Module(MY_CUSTOM_MODULE, {
  service: MyCustomService,
})

Next Steps

Services

Learn how to build module services with decorators

Workflows

Orchestrate module operations with workflows

Build docs developers (and LLMs) love