medusajs/medusa
The world's most flexible commerce platform.
Orchestrates modular commerce services through HTTP APIs and admin dashboards
HTTP requests enter through the main API server which routes them to appropriate modules based on resource type (cart, product, payment). Each module processes the request using its own service layer, interacts with its database entities through an ORM, and returns data that gets transformed into standardized API responses. Events flow between modules through an event bus to maintain consistency (e.g., cart updates trigger inventory checks).
Under the hood, the system uses 2 feedback loops, 3 data pools, 3 control points to manage its runtime behavior.
A 9-component fullstack. 10601 files analyzed. Data flows through 5 distinct pipeline stages.
How Data Flows Through the System
HTTP requests enter through the main API server which routes them to appropriate modules based on resource type (cart, product, payment). Each module processes the request using its own service layer, interacts with its database entities through an ORM, and returns data that gets transformed into standardized API responses. Events flow between modules through an event bus to maintain consistency (e.g., cart updates trigger inventory checks).
- HTTP request routing — Express.js routes in packages/medusa/src/api parse incoming requests, extract path parameters and query filters, then determine which module should handle the operation [HTTP request → Parsed request data]
- Module service invocation — The API layer calls the appropriate module service (CartModuleService.create, ProductModuleService.list) with validated input DTOs, leveraging dependency injection to locate services [CreateCartDTO → Cart entities]
- Database entity operations — Module services use MikroORM to persist/retrieve entities from PostgreSQL, with each module managing its own database schema and migrations [Service operations → Database entities]
- Response transformation — Functions like buildPriceListResponse transform raw database entities into API response DTOs, applying field selection and data enrichment [Database entities → AdminPriceListRemoteQueryDTO]
- Inter-module event propagation — Module operations emit events through the event bus (local or Redis) that other modules can subscribe to, enabling loose coupling between commerce operations [Domain events → Event notifications]
Data Models
The data structures that flow between stages — the contracts that hold the system together.
packages/medusa/src/api/admin/price-lists/typesAPI response object with id: string, title: string, description: string, rules: PriceListRule[], prices: PriceSetPrice[], created_at: Date, updated_at: Date
Created from database price list entities, enriched with rules and prices, then serialized for HTTP response
packages/modules/cart/src/typesInput object with optional fields like currency_code: string, region_id: string, customer_id: string, sales_channel_id: string, metadata: Record<string, unknown>
Received from HTTP requests, validated, then passed to CartModuleService.create() to persist as Cart entity
packages/modules/auth/src/modelsDatabase entity with id: string, provider_identities: ProviderIdentity[], app_metadata: Record<string, unknown>, user_metadata: Record<string, unknown>
Created during user registration, linked to provider identities, persisted in auth database, retrieved during authentication flows
packages/modules/api-key/src/typesInput object with title: string, type: ApiKeyType (SECRET|PUBLISHABLE), created_by: string
Created through admin API, generates hashed token, stored in database, used to authenticate API requests
packages/core/types/srcInterface with service: ModuleService, loaders?: ModuleLoader[], models?: Model[]
Defined by each module to export its service and configuration, consumed by framework during module loading
Hidden Assumptions
Things this code relies on but never validates. These are the things that cause silent failures when the system changes.
The priceLists parameter has properties price_list_rules and prices arrays that can be mutated in-place, and buildPriceListRules/buildPriceSetPricesForCore functions will return compatible array types
If this fails: If price list objects are immutable or lack these properties, the function silently fails to build rules/prices arrays, returning malformed response objects to API clients
packages/medusa/src/api/admin/price-lists/queries/index.ts:buildPriceListResponse
The apiFields parameter contains valid property paths that exist on the priceList objects being filtered, and the filtering logic can handle nested object structures
If this fails: Invalid field paths in apiFields cause property access errors or return empty objects, breaking API field selection functionality that clients depend on for performance
packages/medusa/src/utils/clean-response-data:cleanResponseData
Module service classes passed to Module() constructor have a working constructor that can be instantiated by the dependency injection container without throwing errors
If this fails: If a service constructor requires specific parameters or throws during instantiation, the entire application fails to start with unclear error messages about module loading
packages/core/modules-sdk:MedusaModule.bootstrap
Redis server is accessible at connection parameters specified in RedisCacheModuleOptions, and the Redis instance has sufficient memory for cache operations
If this fails: Application starts successfully but cache operations fail silently or with connection timeouts, causing performance degradation as database queries aren't cached
packages/modules/cache-redis/src/initialize/index.ts:initialize
Provider loading happens before AnalyticsService instantiation attempts to use those providers, and provider registration order doesn't matter for analytics functionality
If this fails: If services try to access providers before loader completes, analytics events are dropped silently without error logs, breaking tracking for business metrics
packages/modules/analytics/src/index.ts:loadProviders
In-memory cache size will not exceed available Node.js heap memory, and cache entries have reasonable TTL values to prevent unbounded growth
If this fails: Large product catalogs or missing TTL configurations cause out-of-memory crashes in production, especially under high concurrent load
packages/modules/cache-inmemory/src/services/inmemory-cache:InMemoryCacheService
The service parameter implements createAuthIdentities method that accepts the userData array format with optional id, required provider_identities array, and optional app_metadata object
If this fails: If IAuthModuleService interface changes or service implementation expects different data shape, test fixtures fail with method not found or validation errors
packages/modules/auth/integration-tests/__fixtures__/auth-identity/index.ts:createAuthIdentities
API key types SECRET and PUBLISHABLE map to specific authentication behaviors, and 'created_by' field accepts arbitrary string identifiers without validation
If this fails: If ApiKeyType enum values change or created_by requires valid user IDs, API key creation fails in production with cryptic validation errors
packages/modules/api-key/integration-tests/__fixtures__/index.ts:createSecretKeyFixture
Module loading order is deterministic and modules don't have circular dependencies that require specific initialization sequencing
If this fails: Race conditions during startup cause some modules to initialize before their dependencies are ready, leading to intermittent startup failures that are hard to reproduce
packages/core/modules-sdk:MedusaModule.bootstrap
Redis connection pool can handle concurrent cache operations from multiple request threads without connection exhaustion or timeout issues
If this fails: Under high load, cache operations queue up behind exhausted connections, causing API response times to degrade as requests wait for cache access
packages/modules/cache-redis/src/services:RedisCacheService
System Behavior
How the system operates at runtime — where data accumulates, what loops, what waits, and what controls what.
Data Pools
Each commerce module maintains its own PostgreSQL schema with entities like Cart, Product, Order — providing data isolation and independent scaling
Queues domain events between modules to ensure eventual consistency and enable reactive business logic
Stores frequently accessed data like product catalogs, price lists, and computed totals to reduce database load
Feedback Loops
- Module bootstrapping (recursive, reinforcing) — Trigger: Application startup. Action: MedusaModule.bootstrap loads each module, resolves dependencies, initializes services, and registers them in the container. Exit: All modules successfully initialized.
- Event-driven consistency (self-correction, balancing) — Trigger: Domain events (cart update, order creation). Action: Subscribing modules update their own state to maintain consistency (inventory adjustments, customer history). Exit: All modules processed event.
Delays
- Module initialization (warmup, ~Application startup time) — System unavailable until all modules bootstrap and register their services
- Event processing (async-processing, ~Near real-time) — Inter-module state updates happen asynchronously, creating brief eventual consistency windows
Control Points
- Module selection (architecture-switch) — Controls: Which implementation of each module to use (Redis vs in-memory cache, local vs Redis event bus)
- Provider configuration (runtime-toggle) — Controls: External service integrations (Stripe for payments, S3 for files, SendGrid for notifications)
- API field selection (feature-flag) — Controls: Which fields to include in API responses, enabling GraphQL-style field selection
Technology Stack
Primary language for type-safe commerce logic across all modules
JavaScript runtime environment for server-side execution
HTTP server framework providing REST API endpoints for admin and store operations
Database ORM for managing PostgreSQL schemas and entity relationships within each module
Primary database for persisting commerce entities like products, orders, customers
Distributed caching and event bus implementation for multi-instance deployments
Dependency injection container for managing module services and their dependencies
Frontend framework for building the admin dashboard interface
Testing framework for unit and integration tests across all packages
Monorepo build system for managing dependencies and parallel builds across 85+ packages
Key Components
- CartModuleService (orchestrator) — Manages cart lifecycle operations — creates carts, adds/removes items, calculates totals, handles cart-to-order conversion
packages/modules/cart/src/services - buildPriceListResponse (transformer) — Transforms raw price list data from modules into API response format, building rules and prices arrays for client consumption
packages/medusa/src/api/admin/price-lists/queries/index.ts - Module (factory) — Creates module registration objects that bind service implementations to module identifiers for dependency injection system
packages/core/framework/src/utils - MedusaModule.bootstrap (orchestrator) — Initializes modules by loading configurations, instantiating services, running loaders, and establishing inter-module communication
packages/core/modules-sdk - InMemoryCacheService (store) — Provides in-memory key-value storage for caching frequently accessed data with TTL support
packages/modules/cache-inmemory/src/services/inmemory-cache - RedisCacheService (adapter) — Bridges framework cache interface to Redis server for distributed caching across multiple application instances
packages/modules/cache-redis/src/services - AnalyticsService (orchestrator) — Coordinates analytics data collection and reporting across multiple analytics providers (PostHog, local storage)
packages/modules/analytics/src/services/analytics-service - ApiKeyModuleService (validator) — Manages API key generation, validation, and authentication for both secret and publishable key types
packages/modules/api-key/src/services - cleanResponseData (transformer) — Filters response objects to include only requested fields, implementing field selection for GraphQL-style API responses
packages/medusa/src/utils/clean-response-data
Package Structure
The main commerce platform API server that orchestrates all commerce operations through HTTP endpoints
Modular commerce services (cart, product, payment, etc.) that implement core business logic
Framework utilities, SDKs, orchestration, and type definitions that power the entire system
React-based administrative interface for managing the commerce platform
UI components, icons, and design tokens used across admin interfaces
Command-line tools for project creation, development, and OpenAPI spec generation
Testing utilities and fixtures for integration tests across the platform
Optional commerce extensions like draft orders and loyalty programs
Explore the interactive analysis
See the full architecture map, data flow, and code patterns visualization.
Analyze on CodeSeaCompare medusa
Related Fullstack Repositories
Frequently Asked Questions
What is medusa used for?
Orchestrates modular commerce services through HTTP APIs and admin dashboards medusajs/medusa is a 9-component fullstack written in TypeScript. Data flows through 5 distinct pipeline stages. The codebase contains 10601 files.
How is medusa architected?
medusa is organized into 4 architecture layers: API Gateway, Commerce Modules, Framework Layer, Provider Ecosystem. Data flows through 5 distinct pipeline stages. This layered structure keeps concerns separated and modules independent.
How does data flow through medusa?
Data moves through 5 stages: HTTP request routing → Module service invocation → Database entity operations → Response transformation → Inter-module event propagation. HTTP requests enter through the main API server which routes them to appropriate modules based on resource type (cart, product, payment). Each module processes the request using its own service layer, interacts with its database entities through an ORM, and returns data that gets transformed into standardized API responses. Events flow between modules through an event bus to maintain consistency (e.g., cart updates trigger inventory checks). This pipeline design reflects a complex multi-stage processing system.
What technologies does medusa use?
The core stack includes TypeScript (Primary language for type-safe commerce logic across all modules), Node.js (JavaScript runtime environment for server-side execution), Express.js (HTTP server framework providing REST API endpoints for admin and store operations), MikroORM (Database ORM for managing PostgreSQL schemas and entity relationships within each module), PostgreSQL (Primary database for persisting commerce entities like products, orders, customers), Redis (Distributed caching and event bus implementation for multi-instance deployments), and 4 more. This broad technology surface reflects a mature project with many integration points.
What system dynamics does medusa have?
medusa exhibits 3 data pools (Module databases, Event bus queue), 2 feedback loops, 3 control points, 2 delays. The feedback loops handle recursive and self-correction. These runtime behaviors shape how the system responds to load, failures, and configuration changes.
What design patterns does medusa use?
4 design patterns detected: Modular Service Architecture, Provider Plugin System, Event-Driven Architecture, API Response Transformation.
How does medusa compare to alternatives?
CodeSea has side-by-side architecture comparisons of medusa with commerce. These comparisons show tech stack differences, pipeline design, system behavior, and code patterns. See the comparison pages above for detailed analysis.
Analyzed on April 20, 2026 by CodeSea. Written by Karolina Sarna.