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?
2. What is a reservation?
3. How is salable quantity calculated?
Flashcards
Question
What is a source?
Click to reveal answer
Answer
Physical inventory location (warehouse, store)
Question
What is a stock?
Click to reveal answer
Answer
Virtual group of sources for a sales channel
Question
What is a reservation?
Click to reveal answer
Answer
Temporary stock hold for pending orders (negative qty)
Question
What is salable quantity?
Click to reveal answer
Answer
Available quantity = source quantities - reservations
Question
What is source selection algorithm?
Click to reveal answer
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