Skip to main content

Configuration

Medusa applications are configured using a medusa-config.js or medusa-config.ts file in the root of your project.

Configuration File

The configuration file exports a configuration object using the defineConfig helper:
medusa-config.ts
import { defineConfig } from "@medusajs/utils"

export default defineConfig({
  projectConfig: {
    databaseUrl: process.env.DATABASE_URL,
    http: {
      jwtSecret: process.env.JWT_SECRET,
      cookieSecret: process.env.COOKIE_SECRET,
      adminCors: process.env.ADMIN_CORS,
      storeCors: process.env.STORE_CORS,
      authCors: process.env.AUTH_CORS,
    },
  },
})
medusa-config.js
const { defineConfig } = require("@medusajs/utils")

module.exports = defineConfig({
  projectConfig: {
    databaseUrl: process.env.DATABASE_URL,
    http: {
      jwtSecret: process.env.JWT_SECRET,
      cookieSecret: process.env.COOKIE_SECRET,
      adminCors: process.env.ADMIN_CORS,
      storeCors: process.env.STORE_CORS,
      authCors: process.env.AUTH_CORS,
    },
  },
})

Configuration Structure

The configuration object has the following structure:
  • projectConfig: General configurations (database, HTTP, Redis)
  • admin: Admin dashboard configurations
  • modules: Module configurations and providers
  • plugins: Plugin configurations
  • featureFlags: Feature flag toggles

Project Configuration

Database Configuration

medusa-config.ts
export default defineConfig({
  projectConfig: {
    // Database connection URL
    databaseUrl: process.env.DATABASE_URL,
    
    // Optional: Database schema (default: "public")
    databaseSchema: "public",
    
    // Optional: Database driver options
    databaseDriverOptions: {
      pool: {
        min: 2,
        max: 10,
        idleTimeoutMillis: 30000,
      },
    },
  },
})
The database URL format is: postgres://[user][:password]@[host][:port]/[dbname]

HTTP Configuration

medusa-config.ts
export default defineConfig({
  projectConfig: {
    http: {
      // JWT configuration
      jwtSecret: process.env.JWT_SECRET,
      jwtExpiresIn: "1d",
      jwtPublicKey: process.env.JWT_PUBLIC_KEY, // For asymmetric JWT
      jwtOptions: {
        algorithm: "HS256", // or RS256 for asymmetric
      },
      jwtVerifyOptions: {
        algorithms: ["HS256"],
      },
      
      // Cookie configuration
      cookieSecret: process.env.COOKIE_SECRET,
      
      // CORS configuration
      adminCors: process.env.ADMIN_CORS || "http://localhost:7001",
      storeCors: process.env.STORE_CORS || "http://localhost:8000",
      authCors: process.env.AUTH_CORS || "http://localhost:7001",
      
      // Authentication methods per actor type
      authMethodsPerActor: {
        user: ["emailpass"], // Admin users
        customer: ["emailpass"], // Storefront customers
      },
    },
  },
})
jwtSecret and cookieSecret are required for production. Use strong, random secrets.

Redis Configuration

For production, configure Redis for caching and event handling:
medusa-config.ts
export default defineConfig({
  projectConfig: {
    redisUrl: process.env.REDIS_URL,
    redisOptions: {
      // Custom retry strategy
      retryStrategy(retries) {
        const delay = Math.min(Math.pow(2, retries) * 50, 4000)
        const jitter = Math.floor(Math.random() * 200)
        return delay + jitter
      },
    },
  },
})

Worker Mode

Configure how your application handles HTTP requests and background jobs:
medusa-config.ts
export default defineConfig({
  projectConfig: {
    workerMode: "shared", // "shared" | "server" | "worker"
  },
})
You can also set this via environment variable:
MEDUSA_WORKER_MODE=server

Admin Configuration

medusa-config.ts
export default defineConfig({
  admin: {
    // Disable admin dashboard
    disable: process.env.DISABLE_ADMIN === "true",
    
    // Admin path (default: "/app")
    path: "/admin",
    
    // Backend URL for admin
    backendUrl: process.env.MEDUSA_BACKEND_URL || "http://localhost:9000",
    
    // Storefront URL (for generating customer links)
    storefrontUrl: process.env.STOREFRONT_URL || "http://localhost:8000",
    
    // Output directory for admin build
    outDir: "./build",
    
    // Max file upload size (bytes)
    maxUploadFileSize: 10 * 1024 * 1024, // 10MB
  },
})

Module Configuration

Configure Medusa modules and providers:
medusa-config.ts
import { Modules } from "@medusajs/utils"

export default defineConfig({
  modules: [
    {
      key: Modules.FILE,
      resolve: "@medusajs/file",
      options: {
        providers: [
          {
            resolve: "@medusajs/file-s3",
            id: "s3",
            options: {
              bucket: process.env.S3_BUCKET,
              region: process.env.S3_REGION,
              access_key_id: process.env.S3_ACCESS_KEY_ID,
              secret_access_key: process.env.S3_SECRET_ACCESS_KEY,
            },
          },
        ],
      },
    },
    {
      key: Modules.NOTIFICATION,
      resolve: "@medusajs/notification",
      options: {
        providers: [
          {
            resolve: "@medusajs/notification-sendgrid",
            id: "sendgrid",
            options: {
              api_key: process.env.SENDGRID_API_KEY,
              from: process.env.SENDGRID_FROM,
            },
          },
        ],
      },
    },
    {
      key: Modules.PAYMENT,
      resolve: "@medusajs/payment",
      options: {
        providers: [
          {
            resolve: "@medusajs/payment-stripe",
            id: "stripe",
            options: {
              api_key: process.env.STRIPE_API_KEY,
              webhook_secret: process.env.STRIPE_WEBHOOK_SECRET,
            },
          },
        ],
      },
    },
    // Disable a module
    {
      key: Modules.INDEX,
      disable: true,
    },
  ],
})

Module Provider Configuration

Modules can have multiple providers configured. Each provider needs:
  • resolve: Package name or path to the provider
  • id: Unique identifier for the provider
  • options: Provider-specific configuration
  • is_default (optional): Set as the default provider

Plugin Configuration

medusa-config.ts
export default defineConfig({
  plugins: [
    {
      resolve: "medusa-payment-stripe",
      options: {
        api_key: process.env.STRIPE_API_KEY,
      },
    },
    {
      resolve: "medusa-fulfillment-shippo",
      options: {
        api_key: process.env.SHIPPO_API_KEY,
      },
    },
  ],
})

Feature Flags

Enable or disable experimental features:
medusa-config.ts
export default defineConfig({
  featureFlags: {
    translation: process.env.MEDUSA_FF_TRANSLATION === "true",
    rbac: process.env.MEDUSA_FF_RBAC === "true",
    index_engine: process.env.ENABLE_INDEX_MODULE === "true",
  },
})
Feature flags allow you to enable experimental features. Check the documentation for each feature flag before enabling.

Complete Production Example

medusa-config.ts
import { defineConfig, Modules } from "@medusajs/utils"

export default defineConfig({
  projectConfig: {
    databaseUrl: process.env.DATABASE_URL,
    redisUrl: process.env.REDIS_URL,
    workerMode: process.env.MEDUSA_WORKER_MODE as any,
    http: {
      jwtSecret: process.env.JWT_SECRET,
      cookieSecret: process.env.COOKIE_SECRET,
      jwtExpiresIn: "7d",
      adminCors: process.env.ADMIN_CORS,
      storeCors: process.env.STORE_CORS,
      authCors: process.env.AUTH_CORS,
    },
    databaseDriverOptions: {
      pool: {
        min: 2,
        max: 10,
      },
    },
  },
  admin: {
    backendUrl: process.env.MEDUSA_BACKEND_URL,
    storefrontUrl: process.env.STOREFRONT_URL,
    maxUploadFileSize: 10 * 1024 * 1024, // 10MB
  },
  modules: [
    {
      key: Modules.FILE,
      resolve: "@medusajs/file",
      options: {
        providers: [
          {
            resolve: "@medusajs/file-s3",
            id: "s3",
            options: {
              bucket: process.env.S3_BUCKET,
              region: process.env.S3_REGION,
              access_key_id: process.env.S3_ACCESS_KEY_ID,
              secret_access_key: process.env.S3_SECRET_ACCESS_KEY,
            },
          },
        ],
      },
    },
    {
      key: Modules.CACHE,
      resolve: "@medusajs/cache-redis",
      options: {
        redisUrl: process.env.REDIS_URL,
      },
    },
    {
      key: Modules.EVENT_BUS,
      resolve: "@medusajs/event-bus-redis",
      options: {
        redisUrl: process.env.REDIS_URL,
      },
    },
  ],
  featureFlags: {},
})

Configuration Validation

Medusa validates your configuration on startup. Common errors:
  • Missing jwtSecret: Required for JWT authentication
  • Missing cookieSecret: Required for session management
  • Invalid database URL: Check connection string format
  • Module configuration errors: Verify module options
In production mode (NODE_ENV=production), configuration errors will cause the application to fail to start. In development, warnings are logged instead.

Environment-Specific Configuration

You can create different configurations for different environments:
medusa-config.ts
import { defineConfig } from "@medusajs/utils"

const isProduction = process.env.NODE_ENV === "production"

export default defineConfig({
  projectConfig: {
    databaseUrl: process.env.DATABASE_URL,
    http: {
      jwtSecret: process.env.JWT_SECRET || (isProduction ? undefined : "supersecret"),
      cookieSecret: process.env.COOKIE_SECRET || (isProduction ? undefined : "supersecret"),
      adminCors: isProduction 
        ? process.env.ADMIN_CORS 
        : "http://localhost:7001",
      storeCors: isProduction
        ? process.env.STORE_CORS
        : "http://localhost:8000",
    },
  },
})

Build docs developers (and LLMs) love