Orchestrating Five Systems Without Middleware
May 20, 2024
The integration challenge: Connect Medusa (commerce), Odoo (ERP), a custom Product Configurator, Strapi (PIM), and a Data Management Portal. Keep data consistent. Avoid middleware hell.
Traditional approach: Build complex middleware. Handle sync failures. Debug data inconsistencies. Maintain brittle connections.
Our approach: Event-driven architecture using Medusa's workflow engine. No middleware. No data duplication where it doesn't belong.
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
}
This unlocks:
- Shared order visibility across org buyers
- Organization-level pricing and promotions
- Company-specific product recommendations
- Unified shipping and billing rules
One field. Massive impact on B2B experience.
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.
What I Learned
Middleware is often a crutch. If you need complex middleware, your architecture probably has unclear responsibilities.
Workflows are underrated. Having structured patterns for multi-step operations with rollbacks prevents entire classes of bugs.
Caching strategy matters as much as architecture. Know what changes frequently (cart data) vs rarely (shipping rules). Cache accordingly.
ERP integration doesn't mean ERP owns everything. Commerce platforms are better at commerce. Let them handle it, sync what the ERP needs.
Read about this integration pattern in Medusa's ERP guide.
Technical implementation by the rb2 team. I worked on the architecture and integration patterns.