Skip to content
intermediate Phase 44 · Catalog Advanced

Multi-Source Inventory (MSI)

Multi-Source Inventory including sources, stocks, reservations, salable quantity, and inventory APIs

1h
0 problems
Topic Progress 0%

MSI Architecture

Sources and Stocks

Sources: Physical locations where inventory is stored
Stocks: Virtual groups of sources for sales channels

Example:
  Sources:
    - warehouse_east (New York)
    - warehouse_west (Los Angeles)
    - store_nyc (NYC Retail)
    - store_la (LA Retail)

  Stocks:
    - default (all warehouses)
    - online (both warehouses)
    - nyc_only (warehouse_east + store_nyc)

Source Tables

-- inventory_source
SELECT source_code, name, enabled, country_id, city
FROM inventory_source;
+----------------+----------------+---------+------------+--------+
| source_code    | name           | enabled | country_id | city   |
+----------------+----------------+---------+------------+--------+
| default        | Default        |       1 | US         | Austin |
| warehouse_east | East Warehouse |       1 | US         | NYC    |
| warehouse_west | West Warehouse |       1 | US         | LA     |
+----------------+----------------+---------+------------+--------+

-- inventory_stock
SELECT stock_id, name, is_default
FROM inventory_stock;
+----------+---------+-----------+
| stock_id | name    | is_default|
+----------+---------+-----------+
|        1 | Default |         1 |
|        2 | Online  |         0 |
+----------+---------+-----------+

-- inventory_source_stock (mapping)
SELECT source_code, stock_id, priority
FROM inventory_source_stock;
+----------------+----------+----------+
| source_code    | stock_id | priority |
+----------------+----------+----------+
| default        |        1 |        1 |
| warehouse_east |        1 |        2 |
| warehouse_west |        1 |        3 |
| warehouse_east |        2 |        1 |
| warehouse_west |        2 |        2 |
+----------------+----------+----------+

Stock Management

Source Items

-- inventory_source_item (physical stock per source)
SELECT source_code, sku, quantity, status
FROM inventory_source_item
WHERE sku = 'TSHIRT-001';
+----------------+--------------+----------+--------+
| source_code    | sku          | quantity | status |
+----------------+--------------+----------+--------+
| default        | TSHIRT-001   |      100 |      1 |
| warehouse_east | TSHIRT-001   |       50 |      1 |
| warehouse_west | TSHIRT-001   |       25 |      1 |
| store_nyc      | TSHIRT-001   |       10 |      1 |
+----------------+--------------+----------+--------+

Salable Quantity

// Get salable quantity
$stockState = $objectManager->get(
    \Magento\InventoryApi\Api\GetStockItemsBySkuInterface::class
);

$stockItems = $stockState->execute(['TSHIRT-001'], $stockId);

// Salable quantity = sum of source quantities - reservations
// Example: 100 + 50 + 25 + 10 = 185 total
// Minus 5 reserved = 180 salable

Stock Status

// Check if product is salable
$stockResolver = $objectManager->get(
    \Magento\InventoryApi\Api\SourceItemsCheckInterface::class
);

$isSalable = $stockResolver->execute(
    'TSHIRT-001',
    $sourceCode,
    $stockId
);

// Get stock status for product
$stockStatus = $objectManager->get(
    \Magento\InventoryApi\Api\GetStockItemConfigurationInterface::class
);

$config = $stockStatus->execute('TSHIRT-001', $stockId);
$isSalable = $config->isSalable();

Reservations

Reservation System

-- inventory_reservation (pending orders)
SELECT reservation_id, sku, quantity, stock_id
FROM inventory_reservation
WHERE sku = 'TSHIRT-001';
+-----------------+--------------+----------+----------+
| reservation_id  | sku          | quantity | stock_id |
+-----------------+--------------+----------+----------+
|             123 | TSHIRT-001   |       -5 |        1 |
|             124 | TSHIRT-001   |       -2 |        1 |
+-----------------+--------------+----------+----------+

-- Negative quantity = reserved for order
-- Total reserved: 7 units
-- Salable: 185 - 7 = 178

Reservation Lifecycle

1. Cart Add:
   No reservation yet

2. Checkout:
   Reservation created (negative qty)
   inventory_reservation: -5

3. Invoice:
   Reservation converted to deduction
   inventory_source_item: qty -5

4. Ship:
   Source assigned based on algorithm

5. Cancel:
   Reservation removed

Source Selection Algorithm

// Default algorithm: source priority
// 1. Check source priority (lower = higher priority)
// 2. Check if source has sufficient stock
// 3. Assign from best source

// Custom algorithm
class CustomSourceSelection implements \Magento\InventoryApi\Api\SourceSelectionServiceInterface
{
    public function execute(
        \Magento\InventoryApi\Api\Data\SourceSelectionRequestInterface $request
    ): \Magento\InventoryApi\Api\Data\SourceSelectionResultInterface {
        // Custom logic: nearest warehouse, alphabetical, etc.
    }
}

Reserving Stock

// Reserve stock for order
$reservationService = $objectManager->get(
    \Magento\InventoryApi\Api\AppendReservationsInterface::class
);

$reservation = $objectManager->get(
    \Magento\InventoryApi\Api\Data\ReservationInterfaceFactory::class
)->create();

$reservation->setSku('TSHIRT-001')
    ->setQuantity(-5) // Negative for reservation
    ->setStockId(1)
    ->setMetadata(['order_id' => 12345]);

$reservationService->execute([$reservation]);

Inventory APIs

Source Items API

// Get source items by SKU
$getSourceItems = $objectManager->get(
    \Magento\InventoryApi\Api\GetSourceItemsBySkuInterface::class
);

$sourceItems = $getSourceItems->execute('TSHIRT-001');
foreach ($sourceItems as $item) {
    echo $item->getSourceCode();  // warehouse_east
    echo $item->getQuantity();     // 50
    echo $item->getStatus();       // 1 (in stock)
}

// Save source item
$saveSourceItem = $objectManager->get(
    \Magento\InventoryApi\Api\SaveSourceItemInterface::class
);

$sourceItem = $objectManager->get(
    \Magento\InventoryApi\Api\Data\SourceItemInterfaceFactory::class
)->create();

$sourceItem->setSourceCode('warehouse_east')
    ->setSku('TSHIRT-001')
    ->setQuantity(75)
    ->setStatus(1);

$saveSourceItem->execute($sourceItem);

Stock API

// Get stock items
$getStockItems = $objectManager->get(
    \Magento\InventoryApi\Api\GetStockItemsInterface::class
);

$stockItems = $getStockItems->execute(['TSHIRT-001'], $stockId);

// Get stock item configuration
$getConfig = $objectManager->get(
    \Magento\InventoryApi\Api\GetStockItemConfigurationInterface::class
);

$config = $getConfig->execute('TSHIRT-001', $stockId);
echo $config->isSalable();  // true/false

Source Selection

// Get source selection algorithm result
$sourceSelection = $objectManager->get(
    \Magento\InventoryApi\Api\SourceSelectionServiceInterface::class
);

$request = $objectManager->get(
    \Magento\InventoryApi\Api\Data\SourceSelectionRequestInterfaceFactory::class
)->create();

$request->setItems([
    $objectManager->get(
        \Magento\InventoryApi\Api\Data\SourceSelectionItemRequestInterfaceFactory::class
    )->create()->setSku('TSHIRT-001')->setQty(5)
]);

$result = $sourceSelection->execute($request);

foreach ($result->getSourceSelectionItems() as $item) {
    echo $item->getSourceCode(); // warehouse_east
    echo $item->getQtyAssigned(); // 5
}

MSI Configuration

# Enable MSI
bin/magento module:enable Magento_Inventory
bin/magento module:enable Magento_InventoryApi
bin/magento setup:upgrade

# Check MSI status
bin/magento inventory:source-items:show

# Reindex inventory
bin/magento indexer:reindex inventory

Quiz

1. What is a source in MSI?

Question 1 options

2. What is a reservation?

Question 2 options

3. How is salable quantity calculated?

Question 3 options

Flashcards

Question

What is a source?

Answer

Physical inventory location (warehouse, store)

Question

What is a stock?

Answer

Virtual group of sources for a sales channel

Question

What is a reservation?

Answer

Temporary stock hold for pending orders (negative qty)

Question

What is salable quantity?

Answer

Available quantity = source quantities - reservations

Question

What is source selection algorithm?

Answer

Logic for assigning sources to orders (priority-based)

Revision Notes

Key Takeaways

  • 1. MSI provides multi-location inventory management
  • 2. Sources: physical locations (warehouses, stores)
  • 3. Stocks: virtual groups of sources for sales channels
  • 4. Reservations: temporary stock holds for pending orders
  • 5. Salable quantity = source quantities - reservations
  • 6. Source selection algorithm assigns sources to orders

Interview Tips

  • Explain the difference between sources and stocks
  • Describe the reservation lifecycle
  • Discuss source selection algorithms

Cheat Sheet

MSI Tables:
  inventory_source → Physical locations
  inventory_stock → Virtual stock groups
  inventory_source_stock → Source-stock mapping
  inventory_source_item → Stock per source
  inventory_reservation → Pending order holds

Salable Quantity:
  Sum(source quantities) - Reservations

Reservation Lifecycle:
  Cart → Checkout (reserve) → Invoice (deduct) → Ship (assign)

APIs:
  GetSourceItemsBySkuInterface
  SaveSourceItemInterface
  GetStockItemsInterface
  AppendReservationsInterface
  SourceSelectionServiceInterface