orchestrating five systems without middleware
date: May 20, 2024
The integration challenge: Connect Medusa (commerce), Odoo (ERP), a custom Product Configurator, Strapi (PIM), and a Data Management Portal. Maintain data consistency. Avoid complex middleware.
Traditional approach: Complex middleware. Sync failure handling. Data inconsistency debugging. Brittle connections.
Our approach: Event-driven architecture using Medusa's workflow engine. No middleware. No unnecessary data duplication.
System Responsibilities
Medusa:
- Cart and checkout
- Order orchestration
- Customer accounts with org links
- Shipping calculations
Odoo (ERP):
- Order fulfillment
- Inventory management
- Organization data
- Shipping rules
Product Configurator:
- Real-time price calculations
- Configuration validation
- Customer-specific pricing
Data Management Portal:
- Pricing rules
- Product configuration logic
- Volume discount tiers
Strapi (PIM):
- Product descriptions
- Material specifications
- Images and documents
Each system owns its domain. Medusa coordinates without trying to own everything.
The Integration Pattern
Two-way sync with Odoo:
Orders flow bidirectionally. Web orders go from Medusa → Odoo. Sales rep orders go Odoo → Medusa. This ensures consistency regardless of order source.
External IDs for linking:
Every entity (customer, order, product) has both a Medusa ID and an Odoo ID. We store the mapping, so systems stay loosely coupled.
// Simplified example of how we link entities
interface Customer {
id: string; // Medusa ID
externalId: string; // Odoo ID
organizationId: string; // Links multiple buyers
}
Caching for performance:
Customer shipping data caches in Medusa, updated only when Odoo sends change webhooks. This makes checkout fast. No waiting on ERP queries.
Workflows for data flow:
Medusa workflows handle order placement:
- Validate cart against configurator pricing
- Calculate shipping from Odoo data
- Create order in Medusa
- Send webhook to Odoo
- Listen for fulfillment updates
Built-in rollback if any step fails. No orphaned data.
Custom Pricing Integration
This was the complex part. Pricing depends on:
- Product configuration (material, size, quantity)
- Customer organization
- Volume discounts
- Special agreements
How it works:
- Customer configures product in storefront
- Configurator calculates base price using DMP rules
- DMP applies org-specific discounts
- Price validation happens at checkout
- Final price stores in Medusa order
- Order data syncs to Odoo with price locked
No price stored until validated. No chance of stale pricing at checkout.
Organization Accounts
Extended Medusa's customer model:
// Simplified schema
customer {
id: string;
email: string;
organizationId: string; // New field
externalId: string; // Links to Odoo
}
Result:
- Shared order visibility across org buyers
- Organization-level pricing and promotions
- Company-specific product recommendations
- Unified shipping and billing rules
Single field extension. Significant B2B experience impact.
What Worked
Event-driven beats request-response. Webhooks mean systems don't wait on each other. Order placement doesn't block on Odoo. Fulfillment updates arrive asynchronously.
Cache what changes slowly. Shipping rules don't change every second. Cache them in Medusa, update only when Odoo signals changes.
Validate at boundaries. Pricing calculations happen in the configurator, but Medusa validates before order creation. Catch inconsistencies early.
External IDs for loose coupling. Systems reference each other through IDs, not tight integration. Replacing one system doesn't cascade everywhere.
Technical Lessons
Middleware indicates unclear responsibilities. Complex middleware suggests architecture problems.
Workflows prevent bug classes. Structured patterns for multi-step operations with rollbacks eliminate failure modes.
Caching strategy equals architecture importance. Distinguish frequent changes (cart data) from rare changes (shipping rules). Cache accordingly.
ERP integration doesn't mean ERP ownership. Commerce platforms handle commerce better. Sync only what ERP requires.
Read about this integration pattern in Medusa's ERP guide.
Technical implementation by the rb2 team. I worked on the architecture and integration patterns.