GuideMarch 13, 2026

MTO vs MTS in Odoo 19:
Choosing the Right Procurement Strategy

INTRODUCTION

Your Warehouse Is Either Sitting on Dead Stock or Losing Sales to Stockouts

Every manufacturing and distribution company faces the same fundamental tension: stock too much and you tie up capital in unsold inventory; stock too little and you lose orders to lead time. The difference between companies that manage this well and those that don't comes down to one decision — which products get produced or purchased to stock, and which get produced or purchased only when a customer orders them.

Odoo 19 gives you two core procurement strategies to solve this: Make-to-Stock (MTS) and Make-to-Order (MTO). MTS keeps inventory on hand, replenished automatically by reorder rules. MTO triggers procurement only when a confirmed sales order demands it — no forecast, no safety stock, no risk of obsolescence. Most businesses need both, applied at the product level.

This guide walks through both strategies in detail — how to configure routes, set up procurement rules, build hybrid MTS+MTO workflows, tune reorder points, and avoid the configuration mistakes that cause silent procurement failures. Every setting is shown with the exact Odoo 19 path and XML if you need to automate it.

01

Make-to-Stock in Odoo 19: How Automatic Replenishment Keeps Your Shelves Full

Make-to-Stock is the default procurement strategy in Odoo 19. When a sales order is confirmed, Odoo checks the available stock in the delivery warehouse. If enough quantity exists, it reserves it immediately and creates a delivery order. If not, the product sits in a waiting state until stock arrives — either from a purchase order, a manufacturing order, or an inter-warehouse transfer triggered by reorder rules.

The key characteristic of MTS: procurement is decoupled from demand. You don't buy or manufacture because a customer ordered something. You buy or manufacture because your stock dropped below a threshold. The customer order simply consumes what's already there.

When to Use MTS

CriteriaMTS Is the Right Choice When...
Demand predictabilityProducts have stable, forecastable demand (e.g., consumables, standard parts)
Lead time toleranceCustomers expect same-day or next-day shipping
Shelf lifeProducts don't expire or become obsolete quickly
Unit economicsHolding cost is low relative to lost-sale cost
Batch economiesManufacturing or purchasing in bulk significantly reduces per-unit cost

Enabling MTS on a Product

MTS is the default behavior in Odoo 19. A product with no special routes configured uses MTS implicitly. However, you can make this explicit for clarity:

Path — Odoo 19 UI
Inventory > Products > [Your Product] > Inventory tab

Routes:  (leave empty for default MTS behavior)
         OR check "Replenish on Order (MTO)" to override — do NOT check this for MTS

To enable automatic replenishment:
  Inventory > Operations > Replenishment > Create Reorder Rule
  Product:    [Your Product]
  Warehouse:  [Your Warehouse]
  Min Qty:    10       (trigger replenishment when stock falls to this)
  Max Qty:    50       (order up to this quantity)
  Route:      Buy / Manufacture  (depends on product type)
XML — Reorder rule via data file
<odoo>
  <data>
    <!-- Reorder rule: replenish Widget-A when stock drops below 10 -->
    <record id="orderpoint_widget_a" model="stock.warehouse.orderpoint">
      <field name="product_id" ref="product.product_widget_a"/>
      <field name="warehouse_id" ref="stock.warehouse0"/>
      <field name="location_id" ref="stock.stock_location_stock"/>
      <field name="product_min_qty">10</field>
      <field name="product_max_qty">50</field>
      <field name="qty_multiple">5</field>
      <field name="trigger">auto</field>
    </record>
  </data>
</odoo>
MTS Without Reorder Rules Is Just "Hope"

Setting a product to MTS without creating a reorder rule means Odoo will never automatically replenish it. The product will sell until stock hits zero, then every new sales order will sit in "Waiting" status indefinitely. MTS only works as a strategy when paired with properly tuned reorder rules — otherwise you're running Make-to-Nothing.

02

Make-to-Order in Odoo 19: Procure Only What Customers Actually Order

Make-to-Order flips the procurement logic. Instead of maintaining stock and hoping demand matches your forecast, MTO triggers procurement directly from the sales order. When a customer orders 50 units, Odoo immediately creates either a purchase order (Buy route) or a manufacturing order (Manufacture route) for exactly 50 units. No more, no less.

In Odoo 19, MTO underwent a significant architectural change. The old procurement.group-based MTO was replaced with a stock reference system that links the sales order line directly to the procurement move. This means better traceability — you can trace any manufacturing order or PO back to the exact customer order that triggered it.

When to Use MTO

CriteriaMTO Is the Right Choice When...
Demand predictabilityProducts have sporadic or unpredictable demand (custom items, seasonal goods)
Product valueHigh-value items where holding cost is significant (machinery, electronics)
CustomizationProducts are configured or customized per order (made-to-spec)
Obsolescence riskProducts depreciate quickly or have short lifecycles (tech, fashion)
Lead time acceptanceCustomers accept longer lead times in exchange for customization or lower price

Enabling MTO on a Product

First, make the MTO route visible. In Odoo 19, it is archived by default:

Path — Activate MTO route in Odoo 19
Step 1: Unarchive the MTO route
  Inventory > Configuration > Routes
  Remove the "Active" filter (or add "Archived" filter)
  Find "Replenish on Order (MTO)" > Unarchive it

Step 2: Assign MTO to the product
  Inventory > Products > [Your Product] > Inventory tab
  Routes:  Check "Replenish on Order (MTO)"
           Also check "Buy" or "Manufacture" (the supply method)

Step 3: Confirm a sales order
  The system will auto-create a PO or MO linked to that SO line
Python — Programmatically set MTO route on a product
# In a custom module or server action
mto_route = self.env.ref('stock.route_warehouse0_mto')
buy_route = self.env.ref('purchase_stock.route_warehouse0_buy')

product = self.env['product.template'].browse(product_id)
product.route_ids = [(6, 0, [mto_route.id, buy_route.id])]

# Verify the configuration
for route in product.route_ids:
    print(f"Route: {{route.name}} (active={{route.active}})")
MTO + Buy vs MTO + Manufacture

MTO alone only defines when to procure (on demand). You must also specify how to procure. If the product is purchased from a vendor, add the Buy route alongside MTO. If it's manufactured in-house, add the Manufacture route. Without a supply route, confirming a sales order will create a stock move with no source — it will sit in "Waiting Another Operation" forever.

03

Odoo 19 Route and Procurement Rule Configuration for MTO and MTS

Routes are the backbone of Odoo's procurement system. A route is a collection of procurement rules (pull rules) that define how goods move between locations. Understanding the route architecture is essential for configuring MTO and MTS correctly.

How Procurement Rules Chain Together

When a sales order creates demand, Odoo walks the route's pull rules to find a supply source. Each rule defines a source location, a destination location, and an action (buy, manufacture, or pull from another location). Rules chain together: the output of one rule becomes the input of the next.

Diagram — MTS procurement chain
Sales Order confirmed
  |
  v
Check stock at WH/Stock
  |
  +--[Stock available]--> Reserve stock --> Create delivery order
  |
  +--[Stock NOT available]--> Delivery stays in "Waiting"
       |
       Reorder rule fires (scheduled or manual)
       |
       v
     Create PO / MO to replenish WH/Stock
       |
       v
     Goods received --> Stock updated --> Delivery auto-assigned
Diagram — MTO procurement chain
Sales Order confirmed
  |
  v
MTO route triggers immediately (no stock check)
  |
  +--[Buy route]--> Create Purchase Order for exact SO qty
  |                   |
  |                   v
  |                 PO confirmed --> Goods received --> Delivery created
  |
  +--[Manufacture route]--> Create Manufacturing Order for exact SO qty
                              |
                              v
                            MO completed --> Goods in stock --> Delivery created

Inspecting Route Rules in the Database

When debugging procurement issues, you often need to see exactly which rules are attached to a route and in what order they evaluate. This query shows you the full picture:

SQL — Inspect procurement rules for a warehouse
SELECT
    r.name           AS route_name,
    r.active         AS route_active,
    rule.name        AS rule_name,
    rule.action       AS rule_action,
    src.complete_name AS source_location,
    dest.complete_name AS dest_location,
    rule.procure_method AS procure_method,
    rule.sequence     AS sequence
FROM stock_rule rule
JOIN stock_route r      ON rule.route_id = r.id
LEFT JOIN stock_location src  ON rule.location_src_id = src.id
LEFT JOIN stock_location dest ON rule.location_dest_id = dest.id
WHERE rule.warehouse_id = 1
ORDER BY r.name, rule.sequence;
FieldMTS Rule ValueMTO Rule Value
procure_methodmake_to_stock — take from stock, wait if unavailablemake_to_order — always trigger upstream procurement
actionpull — pull goods from source locationpull — pull goods but force upstream creation
triggerReorder rule (scheduler-driven)Sales order confirmation (event-driven)
Stock reservationReserves existing inventory immediatelyCreates new procurement, reserves after receipt
04

Hybrid MTS + MTO: The Best Procurement Strategy for Products with Variable Demand

Most real-world businesses don't fit neatly into pure MTS or pure MTO. A furniture manufacturer might stock their 10 best-selling chairs (MTS) but make custom-colored versions only when ordered (MTO). A distributor might keep safety stock of fast-moving SKUs (MTS) while ordering slow-movers only on demand (MTO).

Odoo 19 supports a hybrid approach using the MTS+MTO route, available through the stock_mts_mto_rule module. This route first checks available stock (MTS behavior). If enough exists, it reserves it. If not, it procures only the shortfall via MTO.

Enabling the MTS+MTO Route

Path — Install and configure MTS+MTO
Step 1: Install the module
  Apps > Search "MTS+MTO" > Install "MTS+MTO Procurement Strategy"
  Technical name: stock_mts_mto_rule

Step 2: A new route appears automatically
  Inventory > Configuration > Routes
  You'll see: "Make To Order + Make To Stock"

Step 3: Assign to products
  Inventory > Products > [Your Product] > Inventory tab
  Routes:  Check "Make To Order + Make To Stock"
           Also check "Buy" or "Manufacture"

Step 4: Set a reorder rule (critical!)
  The MTS portion needs a reorder rule to replenish base stock.
  Without it, the MTS check always finds zero — making it pure MTO.

How the Hybrid Split Works

Consider a product with 30 units in stock and a customer orders 50:

Diagram — MTS+MTO split procurement
Customer orders 50 units
  |
  v
MTS+MTO route evaluates available stock: 30 units
  |
  +--[MTS portion: 30 units]--> Reserve from existing stock
  |                               Create delivery for 30 units (ready)
  |
  +--[MTO portion: 20 units]--> Trigger procurement for shortfall
                                  Create PO/MO for 20 units
                                  Create delivery for 20 units (waiting)
                                    |
                                    v
                                  Goods received --> Delivery assigned

Result: Customer gets 30 units immediately, 20 units after procurement
        (or: both ship together once the MTO portion arrives)
XML — Configure MTS+MTO via data file
<odoo>
  <data>
    <!-- Assign MTS+MTO + Buy routes to a product -->
    <record id="product_hybrid_example" model="product.template">
      <field name="name">Industrial Bearing X200</field>
      <field name="type">product</field>
      <field name="route_ids"
             eval="[(6, 0, [
               ref('stock_mts_mto_rule.route_mto_mts'),
               ref('purchase_stock.route_warehouse0_buy'),
             ])]"/>
    </record>

    <!-- Reorder rule for the MTS base stock -->
    <record id="orderpoint_bearing_x200" model="stock.warehouse.orderpoint">
      <field name="product_id" ref="product_hybrid_example"/>
      <field name="warehouse_id" ref="stock.warehouse0"/>
      <field name="location_id" ref="stock.stock_location_stock"/>
      <field name="product_min_qty">20</field>
      <field name="product_max_qty">100</field>
      <field name="qty_multiple">10</field>
    </record>
  </data>
</odoo>
Partial Deliveries and Customer Experience

The MTS+MTO split creates two delivery orders by default — one for the available stock and one for the procured shortfall. If your customer expects a single shipment, configure the delivery order to use backorder merging or set the product's Delivery Lead Time to account for procurement time. Otherwise, the warehouse team will ship partial orders and confuse customers who expected everything in one box.

05

Tuning Reorder Points: The Safety Stock Formula That Prevents Both Stockouts and Overstock

Reorder rules are the engine behind MTS. A badly tuned reorder point either leaves you with $200,000 in dead inventory or causes stockouts every week. Here's how to calculate the right values for your business:

Formula — Safety stock and reorder point calculation
# ── Core Formulas ──

Safety Stock = Z x sigma_d x sqrt(L)

Where:
  Z       = Service level factor (1.65 for 95%, 2.33 for 99%)
  sigma_d = Standard deviation of daily demand
  L       = Lead time in days (vendor or manufacturing)

Reorder Point (Min Qty) = (Average Daily Demand x Lead Time) + Safety Stock

Max Qty = Reorder Point + Economic Order Quantity (EOQ)

EOQ = sqrt((2 x Annual Demand x Ordering Cost) / Holding Cost per Unit)


# ── Worked Example: Widget-A ──

Annual demand:     12,000 units  (avg 33/day)
Demand std dev:    8 units/day
Lead time:         14 days (vendor)
Service level:     95% (Z = 1.65)
Ordering cost:     $25 per PO
Holding cost:      $2 per unit per year

Safety Stock  = 1.65 x 8 x sqrt(14) = 1.65 x 8 x 3.74 = 49.4 ≈ 50 units
Reorder Point = (33 x 14) + 50 = 462 + 50 = 512 units
EOQ           = sqrt((2 x 12000 x 25) / 2) = sqrt(300000) = 548 units
Max Qty       = 512 + 548 = 1,060 units

Odoo reorder rule:
  Min Qty:      512
  Max Qty:      1060
  Qty Multiple: 50  (vendor sells in cases of 50)

Odoo 19 Reorder Rule Settings Explained

FieldWhat It ControlsCommon Mistake
Min QtyWhen on-hand + incoming - outgoing drops below this, trigger replenishmentSetting to 0 — replenishment only fires after stockout
Max QtyOrder enough to bring forecasted stock up to this levelSetting equal to Min — creates tiny POs with high ordering cost
Qty MultipleRound up order quantity to this multiple (vendor MOQ)Ignoring vendor case quantities — leads to receiving mismatches
Triggerauto = scheduler checks daily; manual = only via "Order Once" buttonUsing manual for products that need continuous replenishment
Visibility DaysLook ahead N days of forecasted demand when calculating order qtyNot using it — leads to ordering exactly to Max, stockout before next order
Python — Bulk-update reorder rules from a spreadsheet import
# Server action to update reorder rules from product fields
for product in self.env['product.product'].search([
    ('type', '=', 'product'),
    ('x_reorder_min', '>', 0),
]):
    orderpoint = self.env['stock.warehouse.orderpoint'].search([
        ('product_id', '=', product.id),
        ('warehouse_id', '=', warehouse_id),
    ], limit=1)

    vals = {{
        'product_min_qty': product.x_reorder_min,
        'product_max_qty': product.x_reorder_max,
        'qty_multiple': product.x_order_multiple or 1.0,
    }}

    if orderpoint:
        orderpoint.write(vals)
    else:
        vals.update({{
            'product_id': product.id,
            'warehouse_id': warehouse_id,
            'location_id': warehouse.lot_stock_id.id,
        }})
        self.env['stock.warehouse.orderpoint'].create(vals)
Use Visibility Days to Prevent the "Order Today, Stockout Tomorrow" Problem

Without Visibility Days, the scheduler only looks at current stock levels. If your Min Qty is 100 and you have 101 units, no order fires — even if 200 units are committed to outgoing deliveries next week. Setting Visibility Days to your lead time (e.g., 14 days) tells the scheduler to factor in forecasted demand for the next 14 days, triggering earlier replenishment that arrives before the stockout.

06

4 MTO/MTS Configuration Mistakes That Silently Break Your Supply Chain

1

MTO Route Is Archived by Default in Odoo 19

In Odoo 19, the MTO route ships in an archived state. If you go to a product's Inventory tab and don't see "Replenish on Order (MTO)" in the route selection, it's not missing — it's hidden. Teams often work around this by manually creating procurement rules, which creates a fragile parallel system that breaks on Odoo upgrades.

Our Fix

Go to Inventory > Configuration > Routes, remove the Active filter, find "Replenish on Order (MTO)", and unarchive it. Then assign it to products normally. If you need this in a data file for automated deployments: <function model="stock.route" name="write">[[ref('stock.route_warehouse0_mto')], {'active': True}]</function>

2

MTO Without a Supply Route Creates Ghost Moves

Assigning only the MTO route to a product (without Buy or Manufacture) means Odoo knows it should procure on demand but has no rule telling it how. The result: confirming a sales order creates a stock move from "Vendors" or "Production" to "WH/Stock" with no corresponding PO or MO. The delivery order shows "Waiting Another Operation" and nothing ever arrives. There's no error message — just a silent procurement void.

Our Fix

Always pair MTO with either Buy (for purchased products) or Manufacture (for produced products). Run this diagnostic query periodically to catch orphaned MTO products: SELECT pt.name FROM product_template pt JOIN stock_route_product rel ON rel.product_template_id = pt.id WHERE rel.route_id = (SELECT id FROM stock_route WHERE name ILIKE '%mto%') AND pt.id NOT IN (SELECT product_template_id FROM stock_route_product WHERE route_id IN (SELECT id FROM stock_route WHERE name ILIKE '%buy%' OR name ILIKE '%manufacture%'))

3

The Scheduler Doesn't Run in Real-Time

MTS replenishment depends on the procurement scheduler (Inventory > Operations > Run Scheduler). By default, this scheduled action runs once per day. If a sales order depletes stock at 9 AM and the scheduler runs at midnight, the replenishment PO won't be created until the next day — adding 24 hours of invisible lead time. For high-volume operations, this daily gap causes cascading delays across the supply chain.

Our Fix

Increase scheduler frequency for critical products. Go to Settings > Technical > Scheduled Actions > "Scheduler: Run procurement" and change the interval to every 2-4 hours. For truly time-sensitive products, use the "Order Once" button on the replenishment dashboard for immediate procurement, or configure reorder rules with trigger='auto' which checks on every stock move.

4

Mixing MTO and MTS on the Same Product Without the Hybrid Module

Some teams assign both the MTO route and a reorder rule to the same product, thinking they'll get hybrid behavior. They won't. MTO takes priority over reorder rules. Every sales order will trigger a new PO/MO regardless of available stock. The reorder rule keeps buying to maintain Min Qty, and MTO keeps buying per order — resulting in double procurement and ballooning inventory that nobody ordered.

Our Fix

If you need hybrid behavior, install the stock_mts_mto_rule module and use the dedicated MTS+MTO route. Never combine the standard MTO route with reorder rules on the same product. Audit your current products with this check: any product that has both an MTO route and an active reorder rule is likely double-procuring.

BUSINESS ROI

What the Right Procurement Strategy Saves Your Business

Choosing MTO vs MTS isn't a technical decision — it's a financial one. Here's what changes when you match each product to the right strategy:

30-40%Lower Carrying Costs

Moving slow-movers from MTS to MTO eliminates safety stock for products that sell twice a year. No warehouse space, no insurance, no write-offs.

95%+Service Level on Fast-Movers

Properly tuned MTS reorder points with Visibility Days keep best-sellers in stock. Customers get same-day shipping instead of "2-3 week lead time."

ZeroDead Stock on Custom Items

MTO means you never produce or purchase a custom-spec product that a customer hasn't already committed to buying. No obsolescence risk.

The real ROI comes from the ABC analysis approach: classify your products by revenue contribution (A = top 20%, B = middle 30%, C = bottom 50%), then assign strategies accordingly. A-items get MTS with tight reorder points and high service levels. C-items get MTO with zero safety stock. B-items get the hybrid MTS+MTO approach. This segmentation alone typically reduces total inventory investment by 25-35% while improving fill rates.

SEO NOTES

Optimization Metadata

Meta Desc

Configure MTO vs MTS procurement strategies in Odoo 19. Route setup, reorder rules, hybrid MTS+MTO, safety stock formulas, and common gotchas.

H2 Keywords

1. "Make-to-Stock in Odoo 19: How Automatic Replenishment Keeps Your Shelves Full"
2. "Make-to-Order in Odoo 19: Procure Only What Customers Actually Order"
3. "Hybrid MTS + MTO: The Best Procurement Strategy for Products with Variable Demand"
4. "4 MTO/MTS Configuration Mistakes That Silently Break Your Supply Chain"

Stop Treating Every Product the Same

The single biggest inventory optimization you can make is not a software feature — it's a strategy decision. Most companies run every product on the same procurement logic, either stocking everything (wasting capital) or ordering everything on demand (losing sales to lead time). The fix is straightforward: classify your products, assign the right strategy to each one, and let Odoo's route system handle the execution.

If you're running Odoo 19 and unsure whether your procurement routes are configured correctly, we can audit them. We review your product classification, route assignments, reorder rule parameters, and scheduler frequency. The audit typically uncovers 3-5 products that are either double-procuring or silently failing to replenish — each one a direct hit to your bottom line.

Book a Free Procurement Audit