Medusa + PostgreSQL + Redis + MinIO
Headless commerce platform with full backend services.
Overview
Medusa is a modern headless commerce platform built with Node.js that provides a flexible, API-first approach to e-commerce. Unlike monolithic platforms like Shopify or WooCommerce, Medusa separates the backend commerce logic from the frontend presentation layer, enabling developers to build custom storefronts using any technology stack. The platform handles core commerce operations including product catalog management, order processing, customer management, and payment integration through a comprehensive REST API. This stack combines Medusa's commerce engine with PostgreSQL for transactional data storage, Redis for session management and caching, and MinIO for S3-compatible object storage of product images and digital assets. The architecture provides enterprise-grade data persistence through PostgreSQL's ACID compliance, sub-millisecond response times via Redis caching, and scalable media storage through MinIO's high-performance object store. This configuration creates a complete headless commerce backend that can power multiple storefronts, mobile applications, or integrate with existing business systems. The combination is ideal for businesses requiring custom e-commerce experiences, multi-channel selling, or complex B2B commerce workflows. Companies choose this stack when they need the flexibility of headless architecture without vendor lock-in, full control over their commerce data, and the ability to scale each component independently based on traffic patterns.
Key Features
- Headless commerce API supporting product catalogs, orders, customers, and multi-region selling
- PostgreSQL JSONB storage for flexible product attributes and complex catalog structures
- Redis-powered session management and cart persistence for high-performance checkout flows
- MinIO S3-compatible storage for product images, digital downloads, and media assets
- Built-in admin dashboard for managing products, orders, and customer data
- Multi-currency and multi-region support with tax and shipping calculations
- Pluggable payment processor integration supporting Stripe, PayPal, and custom gateways
- Event-driven architecture with Redis pub/sub for real-time inventory and order updates
Common Use Cases
- 1Headless e-commerce for React, Vue, or mobile app storefronts
- 2Multi-brand retailers managing separate storefronts from unified inventory
- 3B2B marketplaces requiring custom pricing and approval workflows
- 4Digital product stores selling downloads, subscriptions, or SaaS offerings
- 5International commerce with multi-currency and region-specific catalogs
- 6Marketplace platforms connecting multiple vendors with centralized order management
- 7Custom commerce integrations for existing business applications or ERPs
Prerequisites
- Minimum 4GB RAM for full stack operation (1GB PostgreSQL, 512MB Redis, 2GB MinIO, 512MB Medusa)
- Docker Engine 20.10+ and Docker Compose 2.0+ for container orchestration
- Ports 7001, 9000, and 9001 available for admin interface, API, and MinIO console
- Basic understanding of REST APIs and headless architecture concepts
- Node.js knowledge for customizing Medusa plugins and business logic
- PostgreSQL familiarity for database maintenance and backup procedures
For development & testing. Review security settings, change default credentials, and test thoroughly before production use. See Terms
docker-compose.yml
docker-compose.yml
1services: 2 medusa: 3 image: medusajs/medusa:latest4 environment: 5 - DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/medusa6 - REDIS_URL=redis://redis:63797 - NODE_ENV=production8 - JWT_SECRET=${JWT_SECRET}9 - COOKIE_SECRET=${COOKIE_SECRET}10 - STORE_CORS=http://localhost:800011 - ADMIN_CORS=http://localhost:700112 - MINIO_ENDPOINT=minio13 - MINIO_PORT=900014 - MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY}15 - MINIO_SECRET_KEY=${MINIO_SECRET_KEY}16 - MINIO_BUCKET=medusa17 ports: 18 - "9000:9000"19 depends_on: 20 - postgres21 - redis22 - minio23 networks: 24 - medusa-network25 restart: unless-stopped2627 postgres: 28 image: postgres:1529 environment: 30 - POSTGRES_USER=${POSTGRES_USER}31 - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}32 - POSTGRES_DB=medusa33 volumes: 34 - postgres-data:/var/lib/postgresql/data35 networks: 36 - medusa-network37 restart: unless-stopped3839 redis: 40 image: redis:alpine41 volumes: 42 - redis-data:/data43 networks: 44 - medusa-network45 restart: unless-stopped4647 minio: 48 image: minio/minio:latest49 command: server /data --console-address ":9001"50 environment: 51 - MINIO_ROOT_USER=${MINIO_ACCESS_KEY}52 - MINIO_ROOT_PASSWORD=${MINIO_SECRET_KEY}53 volumes: 54 - minio-data:/data55 ports: 56 - "9001:9001"57 networks: 58 - medusa-network59 restart: unless-stopped6061 admin: 62 image: medusajs/admin:latest63 environment: 64 - MEDUSA_BACKEND_URL=http://localhost:900065 ports: 66 - "7001:7001"67 depends_on: 68 - medusa69 networks: 70 - medusa-network71 restart: unless-stopped7273volumes: 74 postgres-data: 75 redis-data: 76 minio-data: 7778networks: 79 medusa-network: 80 driver: bridge.env Template
.env
1# Medusa2POSTGRES_USER=medusa3POSTGRES_PASSWORD=secure_postgres_password4JWT_SECRET=your-super-secret-jwt-key5COOKIE_SECRET=your-super-secret-cookie-key67# MinIO8MINIO_ACCESS_KEY=minioadmin9MINIO_SECRET_KEY=secure_minio_passwordUsage Notes
- 1API at http://localhost:9000
- 2Admin at http://localhost:7001
- 3MinIO console at http://localhost:9001
- 4Seed store: medusa seed -f data/seed.json
- 5Create admin: medusa user -e admin@example.com -p password
Individual Services(5 services)
Copy individual services to mix and match with your existing compose files.
medusa
medusa:
image: medusajs/medusa:latest
environment:
- DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/medusa
- REDIS_URL=redis://redis:6379
- NODE_ENV=production
- JWT_SECRET=${JWT_SECRET}
- COOKIE_SECRET=${COOKIE_SECRET}
- STORE_CORS=http://localhost:8000
- ADMIN_CORS=http://localhost:7001
- MINIO_ENDPOINT=minio
- MINIO_PORT=9000
- MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY}
- MINIO_SECRET_KEY=${MINIO_SECRET_KEY}
- MINIO_BUCKET=medusa
ports:
- "9000:9000"
depends_on:
- postgres
- redis
- minio
networks:
- medusa-network
restart: unless-stopped
postgres
postgres:
image: postgres:15
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=medusa
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
- medusa-network
restart: unless-stopped
redis
redis:
image: redis:alpine
volumes:
- redis-data:/data
networks:
- medusa-network
restart: unless-stopped
minio
minio:
image: minio/minio:latest
command: server /data --console-address ":9001"
environment:
- MINIO_ROOT_USER=${MINIO_ACCESS_KEY}
- MINIO_ROOT_PASSWORD=${MINIO_SECRET_KEY}
volumes:
- minio-data:/data
ports:
- "9001:9001"
networks:
- medusa-network
restart: unless-stopped
admin
admin:
image: medusajs/admin:latest
environment:
- MEDUSA_BACKEND_URL=http://localhost:9000
ports:
- "7001:7001"
depends_on:
- medusa
networks:
- medusa-network
restart: unless-stopped
Quick Start
terminal
1# 1. Create the compose file2cat > docker-compose.yml << 'EOF'3services:4 medusa:5 image: medusajs/medusa:latest6 environment:7 - DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/medusa8 - REDIS_URL=redis://redis:63799 - NODE_ENV=production10 - JWT_SECRET=${JWT_SECRET}11 - COOKIE_SECRET=${COOKIE_SECRET}12 - STORE_CORS=http://localhost:800013 - ADMIN_CORS=http://localhost:700114 - MINIO_ENDPOINT=minio15 - MINIO_PORT=900016 - MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY}17 - MINIO_SECRET_KEY=${MINIO_SECRET_KEY}18 - MINIO_BUCKET=medusa19 ports:20 - "9000:9000"21 depends_on:22 - postgres23 - redis24 - minio25 networks:26 - medusa-network27 restart: unless-stopped2829 postgres:30 image: postgres:1531 environment:32 - POSTGRES_USER=${POSTGRES_USER}33 - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}34 - POSTGRES_DB=medusa35 volumes:36 - postgres-data:/var/lib/postgresql/data37 networks:38 - medusa-network39 restart: unless-stopped4041 redis:42 image: redis:alpine43 volumes:44 - redis-data:/data45 networks:46 - medusa-network47 restart: unless-stopped4849 minio:50 image: minio/minio:latest51 command: server /data --console-address ":9001"52 environment:53 - MINIO_ROOT_USER=${MINIO_ACCESS_KEY}54 - MINIO_ROOT_PASSWORD=${MINIO_SECRET_KEY}55 volumes:56 - minio-data:/data57 ports:58 - "9001:9001"59 networks:60 - medusa-network61 restart: unless-stopped6263 admin:64 image: medusajs/admin:latest65 environment:66 - MEDUSA_BACKEND_URL=http://localhost:900067 ports:68 - "7001:7001"69 depends_on:70 - medusa71 networks:72 - medusa-network73 restart: unless-stopped7475volumes:76 postgres-data:77 redis-data:78 minio-data:7980networks:81 medusa-network:82 driver: bridge83EOF8485# 2. Create the .env file86cat > .env << 'EOF'87# Medusa88POSTGRES_USER=medusa89POSTGRES_PASSWORD=secure_postgres_password90JWT_SECRET=your-super-secret-jwt-key91COOKIE_SECRET=your-super-secret-cookie-key9293# MinIO94MINIO_ACCESS_KEY=minioadmin95MINIO_SECRET_KEY=secure_minio_password96EOF9798# 3. Start the services99docker compose up -d100101# 4. View logs102docker compose logs -fOne-Liner
Run this command to download and set up the recipe in one step:
terminal
1curl -fsSL https://docker.recipes/api/recipes/medusa-complete/run | bashTroubleshooting
- Medusa fails to connect to PostgreSQL: Verify POSTGRES_USER and POSTGRES_PASSWORD match in both services, ensure postgres container starts before medusa
- Redis connection timeout errors: Check Redis container health with docker logs redis, verify redis:6379 hostname resolves within medusa-network
- MinIO bucket access denied: Confirm MINIO_ACCESS_KEY and MINIO_SECRET_KEY are set correctly, create medusa bucket manually via MinIO console at localhost:9001
- Admin dashboard shows 'Backend unreachable': Ensure medusa container is running and MEDUSA_BACKEND_URL points to http://localhost:9000, check CORS settings
- Database migration failures on startup: Run docker exec -it medusa-container medusa migrations run, check PostgreSQL logs for permission or disk space issues
- High memory usage by PostgreSQL: Tune shared_buffers and work_mem in PostgreSQL config, consider adding postgresql.conf volume mount for custom settings
Community Notes
Loading...
Loading notes...
Download Recipe Kit
Get all files in a ready-to-deploy package
Includes docker-compose.yml, .env template, README, and license
Components
medusa-backendpostgresqlredisminiomedusa-admin
Tags
#medusa#headless#ecommerce#api#storefront
Category
E-Commerce & BusinessAd Space
Shortcuts: C CopyF FavoriteD Download