Running one warehouse in Odoo is straightforward: stock arrives, it is put away, and it leaves on a delivery. Running two or more warehouses is a different problem. A shop may sell a product it does not hold, a central warehouse may hold most of the stock, and a second site may need replenishment before a promotion. If staff handle every movement by phone and manual transfers, stock ends up in the wrong place at the wrong time. Multi-warehouse routing is Odoo's answer: a set of rules that decides, automatically, where a demand should be sourced from and which transfers should be created to satisfy it.
This guide explains how that system fits together in Odoo 17, how to set up the built-in resupply route, when to add a custom route, and how to test the result.
First, the vocabulary: warehouses, locations, and routes
Each Odoo warehouse owns a hierarchy of locations and its own operation types for receipts, deliveries, and internal moves. A location is the precise place stock is counted — a shelf, an input zone, a transit location, or a virtual location such as Customer. Stock moves always go from one location to another, so routing is ultimately a decision about locations.
A route is a named collection of rules. A rule says, in effect, when this kind of need or arrival happens, create a move from this source location to that destination location using this operation type. Routes can be assigned at several levels:
- On a product, in the Inventory tab of the product form.
- On a product category, so a whole family inherits the same behaviour.
- On a warehouse, for its receipt and delivery flows.
- On a sales order line, for an exception that applies to one order only.
When Odoo needs to fulfil a demand, it looks for applicable routes in that order and follows the rules it finds. That is why the same product can be bought in one warehouse, manufactured in another, and simply transferred in a third: the route, not the product alone, decides the supply method.
Pull rules and push rules do different jobs
Most confusion about routing comes from mixing up the two kinds of rule.
Pull rules start from demand
A pull rule is triggered by a need at a destination. Confirm a sales order for a customer location, for example, and Odoo works backwards: it creates the delivery move to the customer, checks whether the output location can satisfy it, and if not, creates an earlier move from stock to output. In a multi-step delivery that chain becomes picking, then packing or shipping, then delivery — although warehouse staff process the transfers in the opposite, physical order, starting with the picking.
Pull rules are the engine behind make-to-order, cross-docking, and inter-warehouse resupply. Demand can come from a sales order, a manufacturing order, or a reordering rule.
Push rules start from arrival
A push rule is triggered when stock actually arrives in a location. A typical example is a receipt: goods arrive in an input area and a push rule moves them onward to quality control or to storage. Push rules are useful for standardising what happens after arrival, regardless of why the goods arrived.
One important interaction matters in practice: a push rule is only used when a pull rule has not already created the needed transfer. If you design both for the same flow, test carefully, because the chain Odoo chooses may not be the one you pictured on a whiteboard.
Before you configure anything: turn on the right settings
Go to Inventory > Configuration > Settings. In Odoo 17, enable Storage Locations, and enable Multi-Step Routes if you plan to build or edit routes yourself. Save, then confirm each physical site has its own warehouse record — a central warehouse and each shop it supplies must be separate warehouses, not just shelves under one warehouse.
The built-in resupply route: the fastest correct setup
For the common pattern — one central warehouse supplying one or more smaller warehouses — you do not need to build a route from scratch. Odoo can generate the route for you.
Step 1: Declare who resupplies whom
Open the warehouse that needs stock, for example the shop, under Inventory > Configuration > Warehouses. In its Warehouse Configuration tab, find the Resupply From field and tick the central warehouse. If more than one warehouse can supply this one, tick each of them. Saving this creates the resupply relationship Odoo will use to generate a route.
Step 2: Put the route on the product
Open a product that should move between warehouses. In its Inventory tab, a new route appears with a name of the form: receiving warehouse supplying from sending warehouse. In plain terms, if the shop is called Store and the central site is your main warehouse, the route reads as Store being supplied from that main warehouse. Tick it.
A route on the product alone does not move anything yet. It only says, if this product needs resupply, this is an allowed path. Something still has to create the demand.
Step 3: Choose how demand is created
You have two main choices, and picking the wrong one is the most common design mistake:
- Replenish on Order (MTO). Also tick the MTO route on the product. Now every confirmed demand at the shop creates a linked resupply, unit for unit. This suits expensive, slow-moving, or order-specific items you do not want to hold speculatively in every shop.
- A reordering rule. Create a rule for the shop's stock location, set its route to the resupply route, and set a minimum and maximum. Now resupply is driven by stock level rather than by a single order. This suits everyday items a shop should always have on its shelf.
You can also trigger a one-off replenishment manually from the product form with the Replenish button, choosing the destination warehouse and confirming. That is useful for an initial stocking or a one-time event, and it follows the same route logic as the automatic methods.
What Odoo creates when resupply fires
When the flow triggers, Odoo does not create a single vague transfer. It creates a delivery order out of the supplying warehouse and a receipt into the receiving warehouse. While the goods are travelling, they sit in the inter-warehouse transit location, so neither warehouse counts them as available on its shelves. That transit step is important for honesty in reporting: stock in a truck is real, but it is not sellable at either end until the receipt is validated.
Each warehouse's one-, two-, or three-step shipment settings may add picking or packing transfers around that core pair, without changing the logic.
When to build a custom route instead
Use a custom route when the built-in warehouse flows do not match how you actually work. Examples include:
- A quality-control step that only some product categories must pass through.
- A packing or cross-dock flow where receipts should go to output without being put away.
- A repair or returns flow that moves goods to a dedicated location and back.
- A manufacturing chain where components must be picked to production in a specific sequence.
To build one, enable Multi-Step Routes, go to Inventory > Configuration > Routes, and create a route that applies to products, categories, warehouses, or sales lines as appropriate. Then add rules one link at a time. For each rule, define whether it is a pull or a push, the operation type, the source location, and the destination location. Keep each rule to one leg of the journey. A single rule that tries to describe an entire chain is hard to debug; a chain of small rules mirrors how Odoo itself builds transfers and makes the faulty link obvious.
A testing checklist before go-live
- Create a test product, put stock only in the central warehouse, and confirm a sale from the shop warehouse. Confirm the delivery and receipt pair is created, not just a customer delivery.
- Validate the supplying delivery, check the quantity sits in transit, then validate the shop receipt and confirm it is now on hand at the shop.
- Repeat with a reordering rule: lower the shop below its minimum and run the scheduler or replenish manually, depending on the trigger.
- Repeat with no stock in the central warehouse. Confirm the behaviour is the one you want — a purchase, a manufacture, a backorder, or a clear shortage — rather than a silent dead end.
- Check access rights. Warehouse staff should only see and validate the operations for their own sites where that separation matters to you.
Common pitfalls
- One warehouse, many locations, mistaken for multi-warehouse. Locations alone do not give you separate resupply, operation types, and reporting per site. Create real warehouses for real sites.
- Route ticked, no demand. Without MTO, a reordering rule, or a manual replenishment, a resupply route does nothing on its own.
- Rule on the wrong location. A reordering rule points at a specific location. If it points at the central warehouse instead of the shop, it will replenish the wrong place perfectly reliably.
Done well, multi-warehouse routing turns phone calls into a predictable system: demand appears where customers are, supply answers from where stock is, and every movement is a transfer you can pick, ship, receive, and audit. Start with one product and two warehouses, prove it end to end, then add custom routes.
Further reading
- Odoo 17 documentation: Inter-warehouse replenishment
- Odoo documentation: Routes and push/pull rules
- Odoo 17 documentation: Reordering rules
