How Magento MSI combines geographic distance and priority across multiple warehouses
Anyone running multiple warehouses across regions eventually has to decide whether Distance or Priority is the right fit for MSI. Both algorithms ship by default, but they work in fundamentally different ways: one calculates, the other walks down a fixed list. This article shows how source geocoding actually works, how per-source priority behaves, and what a realistic multi-region warehouse setup looks like.
Table of Contents
- 1. Two different philosophies of source selection
- 2. How source geocoding actually works
- 3. The actual distance calculation
- 4. Per-source priority configuration in the Priority algorithm
- 5. Practical example: three warehouses across regions
- 6. A combined strategy for growing warehouse networks
- 7. Common pitfalls with Distance setups
- 8. Performance considerations with many sources
- 9. Configurability of the algorithm choice
- 10. Summary
- 11. FAQ
1. Two different philosophies of source selection
Priority works entirely without calculation: every source gets an integer priority in the stock-source link, and the algorithm walks down that list strictly in order until the requested quantity is covered. There is no consideration of the shipping address, no distance calculation, and no runtime cost for geo lookups, which makes Priority the more performant of the two default algorithms.
Distance, on the other hand, calculates the actual distance between the customer's shipping address and every source's address for each order and sorts by that. This is closer to what customers intuitively expect, namely that shipping comes from the nearest warehouse, but it costs additional compute time for geocoding and distance calculation on every request.
2. How source geocoding actually works
For Distance to calculate anything at all, every source needs geographic coordinates. These are not determined automatically when a source is saved, they need to be resolved through the geocoding provider Magento connects by default via a Google Maps API key. When a source address is saved in the admin, an API call is triggered in the background that translates street, postal code, city, and country into latitude and longitude, and persists those values in the inventory_source table.
If that call fails, for example because of an invalid address, a missing API key, or a quota limit at Google, the source is left without coordinates. The Distance algorithm then treats such a source as unratable and effectively excludes it from selection, even if it holds sufficient stock. This silent exclusion is one of the most common sources of trouble with Distance setups and often only becomes apparent once a new source is added but never gets shipped from.
<?php
declare(strict_types=1);
namespace Mironsoft\InventoryGeocodingCheck\Console\Command;
use Magento\InventoryApi\Api\SourceRepositoryInterface;
use Magento\Framework\Api\SearchCriteriaBuilder;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Lists all active sources missing geocoded coordinates, which would
* silently exclude them from the Distance algorithm.
*/
class ListUngeocodedSourcesCommand extends Command
{
/**
* @param SourceRepositoryInterface $sourceRepository
* @param SearchCriteriaBuilder $searchCriteriaBuilder
*/
public function __construct(
private readonly SourceRepositoryInterface $sourceRepository,
private readonly SearchCriteriaBuilder $searchCriteriaBuilder
) {
parent::__construct();
}
/**
* Configures the command name.
*
* @return void
*/
protected function configure(): void
{
$this->setName('mironsoft:source:list-ungeocoded');
}
/**
* Iterates all active sources and prints those without valid coordinates.
*
* @param InputInterface $input
* @param OutputInterface $output
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$criteria = $this->searchCriteriaBuilder->addFilter('enabled', 1)->create();
$sources = $this->sourceRepository->getList($criteria)->getItems();
foreach ($sources as $source) {
if ($source->getLatitude() === null || $source->getLongitude() === null) {
$output->writeln(sprintf(
'%s (%s) has no geocoded coordinates and is excluded from Distance selection.',
$source->getSourceCode(),
$source->getName()
));
}
}
return Command::SUCCESS;
}
}
3. The actual distance calculation
For the distance calculation itself, Magento uses the Haversine formula by default, which calculates the shortest distance between two points on a sphere's surface, in other words the straight-line distance rather than the actual driving route. That is a deliberate tradeoff: a real route calculation through a mapping API would be considerably more expensive and slower on every order, while the straight-line distance provides a good enough approximation for most cases, especially for warehouses several hundred kilometers apart.
In regions with very uneven transport infrastructure, however, the straight-line approximation can produce misleading results, for example when two warehouses are separated by a mountain range and the actual driving route is considerably longer than the direct distance. For such cases, a custom algorithm would need to extend the Distance base logic with a real routing API, which is disproportionately expensive for most operations.
4. Per-source priority configuration in the Priority algorithm
A source's priority is not maintained globally, it is set per stock-source link, in the admin under Inventory Stocks while editing a stock. Every linked source gets an integer priority there, where a lower value means higher priority. The same source can have different priorities across different stocks, which matters for operations with multiple, overlapping sales channels, for example when a B2B stock prefers a different main warehouse than the B2C stock of the same company.
It is important that two sources within the same stock can be given the same priority. In that case, the internal load order of the source item records from the database decides, which is effectively undefined without an explicit secondary sort. For production setups, every source in a stock should therefore be given a unique priority to make this behavior predictable.
<!-- Excerpt: stock-source link via the resource model, illustrating the
data structure behind the admin configuration of Inventory Stocks -->
<config>
<stock_source_links>
<link stock_id="10" source_code="warehouse-north" priority="1" />
<link stock_id="10" source_code="warehouse-central" priority="2" />
<link stock_id="10" source_code="warehouse-south" priority="3" />
</stock_source_links>
</config>
5. Practical example: three warehouses across regions
A realistic setup for a company with customers across the north, center, and south of a country consists of three sources: warehouse-north in Hamburg, warehouse-central in Frankfurt, and warehouse-south in Munich, all linked to the same stock. If Priority is chosen, a deliberate order must be defined, for example Frankfurt as the central main warehouse with the highest priority and the two regional warehouses as supplements. That works well as long as customers are geographically spread out, but it also means a customer in Hamburg still ships primarily from Frankfurt.
If Distance is chosen instead, the same customer in Hamburg automatically ships from warehouse-north, a customer in Munich from warehouse-south, without any explicit order needing to be maintained. The upside shows up mainly as shorter shipping times, the downside is that warehouse utilization and inventory distribution are not taken into account. If warehouse-north is low on stock, Distance still consistently picks the nearest warehouse, even if another warehouse with more buffer is geographically farther away.
6. A combined strategy for growing warehouse networks
In practice, a multi-source setup often grows organically: first there is a single main warehouse using Priority, later regional satellite warehouses are added, and only then does the question of Distance come up. A clean transition works by first testing Distance with just two or three geographically distinct sources before switching the entire warehouse network over. That surfaces geocoding problems and unexpected distribution patterns early, without immediately overhauling the whole fulfillment setup.
For operations that want to weigh both geographic proximity and warehouse utilization, a combination makes sense, as described in the previous article on building a custom source selection algorithm: Distance as a coarse pre-selection of the nearest sources, then sorted by utilization within that pre-selection. That cannot be modeled with the default algorithms alone and requires a custom implementation of SourceSelectionInterface.
7. Common pitfalls with Distance setups
The most common mistake is an incompletely maintained source address, for example a missing country or a malformed postal code, that causes geocoding to fail without a clear error message showing up in the admin. Regularly checking all active sources for missing coordinates, as shown in the example above, prevents a new source from being silently excluded from selection.
A second mistake concerns the API key itself: if the geocoding provider's quota is exceeded or the key is left to expire, new geocoding requests fail while already-geocoded sources keep working. That leads to deceptive behavior where existing sources work normally while every newly created source is silently left out of the Distance calculation until the quota issue is resolved.
8. Performance considerations with many sources
For stocks with a double-digit number of sources, Distance calculates a Haversine distance to every single source on every order, which becomes noticeable for very large warehouse networks. The calculation itself is mathematically cheap, the real cost risk lies more in the fact that Distance is invoked more often than Priority for live delivery-time estimates at checkout and can therefore run multiple times per page view.
For very large warehouse networks it is worth caching the calculated distances per postal code area instead of recalculating exactly on every request, since the distance between a source and a postal code area practically never changes. That noticeably reduces compute load on high-traffic checkouts without meaningfully hurting accuracy.
9. Configurability of the algorithm choice
Which algorithm is used is a pure stock configuration in the admin and requires no custom code as long as the default algorithms are sufficient. It is important that this decision is documented and known across the team, since it directly affects shipping times and warehouse utilization and a switch can have a noticeable operational impact on fulfillment.
For custom extensions, such as a configurable maximum distance beyond which a source no longer qualifies at all, the same principle applies as for any other Mironsoft module: a dedicated system.xml section with acl.xml and a menu item instead of hardcoded thresholds in code, so the fulfillment team can adjust configuration independently.
| Criterion | Priority | Distance | Impact |
|---|---|---|---|
| Calculation cost | None, fixed list | Haversine distance per source and request | Priority is more performant with many sources |
| Prerequisite | Priority value per stock-source link | Geocoded coordinates per source | Missing geocoding silently excludes sources |
| Customer experience | Independent of the customer's location | Nearest warehouse is preferred | Distance tends to shorten shipping time |
| Warehouse utilization | Not considered | Not considered | Both algorithms ignore current capacity |
| Best suited for | One clearly prioritized main warehouse plus backup | Several regionally distributed, equivalent warehouses | The choice depends on warehouse structure |
Mironsoft
Magento development, module consulting, and system architecture
A Magento project that needs a second opinion or experienced execution?
We build custom Magento modules, advise on architecture decisions, and take on complex implementations, from service contract planning to production-ready deployment.
Architecture Consulting
Have module and system architecture thought through properly before you build.
Custom Module Development
Build custom Magento modules cleanly, following best practices.
Code Review & Audit
Have existing modules reviewed for performance, security, and maintainability.
10. Summary
Distance and Priority: Key Takeaways
Priority is static
A fixed, configured order without any regard for the shipping address or stock situation.
Distance calculates live
Haversine straight-line distance between customer address and geocoded source coordinates per order.
Geocoding is a prerequisite
Without valid coordinates, Distance silently excludes a source from selection.
Combination is possible
Distance as a pre-selection, custom criteria like utilization as a tiebreaker within that pre-selection.