Adding a second warehouse to Odoo is technically a checkbox. Operating two warehouses correctly is a system design problem. The configurations that look simple — "just create another warehouse and tell stock to move between them" — produce surprising failure modes the first time inventory needs to flow in a non-trivial way.
This guide walks through multi-warehouse configuration for technical leads and developers who own the Odoo implementation. It covers the route topology that actually works in production, the replenishment patterns for common business models (DC + retail, omni-channel, hub-and-spoke), and the reporting strategies that keep everyone aligned on inventory truth.
When you actually need multiple warehouses
Multi-warehouse adds complexity. Before adding it, verify the business case:
- Multiple physical sites — DC + stores, regional warehouses, manufacturing site + finished goods. Each needs separate stock tracking.
- Drop-ship suppliers as virtual warehouses — the supplier's stock is treated as a warehouse you can fulfill from without holding the goods.
- Bonded warehouse vs duty-paid stock — same physical building, different customs status. Best modeled as separate warehouses with transfer rules between them.
- Quarantine inventory — recalled products, returns awaiting inspection. A separate warehouse keeps this stock visible but unavailable for sale.
What you don't need a separate warehouse for: zones within one building (use locations), back-room vs front-shelf within one store (use locations), seasonal storage (use locations or storage categories).
Configuring multiple warehouses
Enable multi-warehouse at Inventory ‣ Configuration ‣ Settings ‣ Warehouse ‣ Storage Locations. Then create each warehouse:
- Navigate to Inventory ‣ Configuration ‣ Warehouses.
- Click New. Set Warehouse Name and Short Name (used as a prefix on receipt and picking sequences — keep it 2–3 characters).
- Set Address — drives shipping label calculations.
- Set Incoming Shipments and Outgoing Shipments step counts (1, 2, or 3 — see the Warehouse Management guide for guidance).
- Set Resupply: choose other warehouses that can act as suppliers to this one (for inter-warehouse transfers).
Saving creates the location tree under the new warehouse: WH/Stock, WH/Input, WH/Output, etc. — same shape as the first warehouse, prefixed with the warehouse code.
Routes: how stock moves between warehouses
A route defines the path stock takes through the system. Multi-warehouse adds two route types beyond the standard receive/deliver:
Resupply route (warehouse-to-warehouse)
When warehouse B is configured to be resupplied from warehouse A, Odoo auto-creates a resupply route: B's reordering rules trigger an internal transfer from A to B. The route handles the picking from A, the transit, and the receipt at B as separate stock moves chained together.
Make-to-Order across warehouses
If a sale at warehouse B has no stock locally, the route can be configured to MTO from warehouse A. The sale order creates a delivery from B; the delivery creates an internal transfer from A to B; the internal transfer creates a picking at A. The chain reverses the flow: customer demand at B pulls stock from A.
Configuring a resupply route
- At Inventory ‣ Configuration ‣ Warehouses ‣ <Warehouse B>, in the Resupply field, select Warehouse A.
- Odoo creates a resupply route automatically.
- On products that should resupply through this route, navigate to Inventory ‣ Products ‣ <Product> ‣ Inventory and add the resupply route to the product's Routes.
Replenishment rules per warehouse
Reordering rules tell Odoo when to replenish. They're configured per product per warehouse — meaning warehouse A and warehouse B can have completely different policies for the same product.
Common policies by warehouse type
- Central DC (replenished from suppliers): high min/max, longer lead time buffer, fewer larger orders. Driven by supplier MOQ and inbound logistics costs.
- Retail back-room (replenished from DC): low min/max, short lead time, frequent small transfers. Inventory turns fast on the shelf.
- Drop-ship hub (no holding): zero min/max, MTO route only. Stock is allocated, not held.
Setting reordering rules
- Navigate to Inventory ‣ Operations ‣ Replenishment.
- Click New. Select product, warehouse, location.
- Set Min Quantity (trigger threshold) and Max Quantity (target after replenishment).
- Set Multiple Quantity if orders must be in pack sizes (e.g., cases of 12).
- Set Trigger: Auto (system runs the replenishment) or Manual (operator runs it).
For a centralized retail operation with many SKUs, manage reordering rules in bulk via CSV import rather than one by one in the UI.
Virtual locations and aggregated views
A virtual location is a location that doesn't physically exist but represents a logical grouping. Common uses:
Aggregated stock for the storefront
If your e-commerce platform should see total available stock across multiple warehouses (because you'll fulfill from any of them), create a virtual location Aggregated Stock and configure your inventory sync to read from it. The virtual location aggregates the underlying physical warehouses.
Customer-allocated stock
For customers with reserved/allocated inventory (B2B contract customers, long-running projects), create a virtual sub-location under each warehouse: WH/Stock/Customer-X. Stock physically lives in WH/Stock but the location reservation prevents allocation to other orders.
Configuration
Configure virtual locations at Inventory ‣ Configuration ‣ Warehouses ‣ Locations. Set Location Type to View (aggregates child locations without holding stock itself) or Internal (holds stock).
Inter-warehouse transfers
Stock physically moves between warehouses through internal transfers. The flow:
- Pick from source warehouse (operator at warehouse A picks goods to a transit location).
- Transit (goods are in transport — often via a carrier).
- Receive at destination warehouse (operator at warehouse B receives goods).
Odoo models this as two pickings linked through a transit location. The picking at A confirms departure; the picking at B confirms arrival. Stock is in transit between confirmations — visible in inventory reports, not available for sale.
Triggering transfers
Three ways:
- Reordering rule: warehouse B's rule triggers a resupply from A.
- Manual transfer: an operator creates an internal transfer to move stock proactively (rebalancing).
- Sale order with MTO: a customer order at B creates a transfer from A to B.
Tracking transit time
Configure expected transit time on the resupply route at Inventory ‣ Configuration ‣ Routes ‣ <Resupply Route> ‣ Rules. The transit time feeds into the lead time calculation for replenishment, so warehouse B's reorder triggers early enough to receive in time.
Reporting across warehouses
Multi-warehouse reporting answers three questions:
What's the total inventory across the network?
The Inventory Valuation Report at Inventory ‣ Reporting ‣ Valuation shows total stock value summed across all warehouses, grouped by product and location. Filters and pivot tables let you slice by warehouse, category, or supplier.
Which warehouses are over- or under-stocked?
The Stock Report at Inventory ‣ Reporting ‣ Stock shows quantity available per product per warehouse. Compare against reordering rule min/max to identify imbalances. A custom dashboard with the formula (qty_available - reorder_min) / (reorder_max - reorder_min) shows fill ratio per warehouse.
How are transfers performing?
The Transfers Report at Inventory ‣ Reporting ‣ Transfers shows pending and completed transfers with cycle time. Long-pending transfers (out > 7 days) usually indicate operational issues — pickings not validated, carriers not picking up, receipts not processed.
Common multi-warehouse failure modes
1. Routes configured at warehouse level but not on products
Resupply route exists at warehouse B; products at warehouse B don't have the route on them; replenishment never triggers from A. Always verify route assignment on actual products, not just warehouses.
2. Reordering rules in conflict
Both warehouse A and warehouse B have reordering rules for the same product, both with auto-trigger. Both fire simultaneously, creating duplicate POs to the supplier. For products replenished centrally, the auto-trigger should be at the source warehouse only; downstream warehouses use resupply routes, not direct supplier reorders.
3. Transfers stuck in transit
Picking at A is validated; receiving at B is never processed. Stock sits in the transit location indefinitely. Inventory shows the right total but neither warehouse can sell it. Monitor transit duration and alert on transfers > 7 days.
4. Storefront sees only one warehouse
Storefront is configured to read from warehouse A's stock; warehouse B has stock; storefront says "out of stock" when B has plenty. For omni-channel fulfillment, sync storefront stock from a virtual aggregated location, not from a single warehouse.
5. Lead time miscalibration
Resupply lead time set to 2 days; actual transit takes 5 days; warehouse B stocks out before resupply arrives. Measure actual transit times monthly and update lead time configuration.
Reference notes
Sources verified against Odoo 19.0 documentation and standards bodies. Use these to confirm anything before applying it to your environment.
- Multi-warehouse — Odoo 19.0 documentation — warehouse and location configuration
- Routes and rules — Odoo 19.0 documentation — resupply and pull/push routes between warehouses
- Reordering rules — Odoo 19.0 documentation — per-warehouse min/max policies
- Magento 2 Multi-Source Inventory (MSI) — when integrating with Magento sources
Frequently Asked Questions
Can I have warehouses in different countries with different currencies?
Yes. Each warehouse belongs to a company; companies can have different currencies. Inter-company transfers handle currency conversion at the transfer date's exchange rate. The complexity is taxes — sales from one country to another involve VAT or import duties that need fiscal positions configured. For multinational retail, this is a significant project, not a checkbox.
How do I handle warehouse-specific pricing?
Pricing is on products, not warehouses. If you want different prices in different warehouses, use pricelists assigned to sales channels or customer segments, not to warehouses. The exception: if your warehouses correspond to legal entities with different cost bases, use Odoo's multi-company features.
Can I run a warehouse without barcodes?
Yes, but inventory accuracy will suffer. Multi-warehouse operations especially benefit from barcoded operations because the cost of inventory drift compounds across warehouses. Plan to roll out barcodes within the first 6 months of multi-warehouse operation.
How does Odoo handle inventory in transit between warehouses?
Odoo creates a transit location for inter-warehouse transfers. Stock moves to transit when leaving the source and to the destination when received. Inventory reports can be filtered to include or exclude transit. Accounting valuation includes transit (stock is on the books even if not in either warehouse).
Can I move stock between warehouses without creating a sale or purchase?
Yes — internal transfers between warehouses are stock movements, not sales. Create them at Inventory ‣ Operations ‣ Transfers with type Internal. They post stock moves and inventory valuation entries; no AR/AP entries (unless you're moving between separate companies, in which case it's an inter-company transaction).
How do I prevent overselling when stock is split across warehouses?
Two patterns. Pattern A: sync only the available stock from a primary warehouse to the storefront — accept that you can't oversell but might miss sales. Pattern B: sync aggregated stock from a virtual location, run an order routing engine that allocates each order to the best warehouse at allocation time. Pattern A is simpler; Pattern B is more efficient at scale. Odoo doesn't include order routing out of the box; for omni-channel retail, this is typically a custom module or external service.