The Distance and Priority Algorithm in Multi-Source Inventory Explained
AI generated
M2
di.xml
Magento 2 · MSI
The Distance and Priority Algorithm in Detail
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.

12 min read Distance Algorithm Priority Geocoding Multi-Region MSI Setup

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.

11. FAQ: Distance and Priority: Key Takeaways

1What is the main difference between Priority and Distance?
Priority uses a fixed order configured in the admin with no regard for the shipping address. Distance calculates the actual straight-line distance between the customer address and each source for every order, preferring the nearest source.
2How are source coordinates determined?
Through a geocoding provider, by default the Google Maps API, which is called in the background when a source address is saved and converts the address into latitude and longitude.
3What happens if a source's geocoding fails?
The source is left without coordinates and is treated as unratable by the Distance algorithm, effectively excluding it from selection even if it holds sufficient stock.
4Does Distance calculate the actual driving route?
No, by default the Haversine formula is used for the straight-line distance between two points, not the real route. That is considerably cheaper to calculate but can be inaccurate across mountain ranges or bodies of water between two warehouses.
5How is a source's priority configured?
Per stock-source link in the admin under Inventory Stocks, as an integer value where a lower value means higher priority. The same source can have different priorities across different stocks.
6What happens when two sources have the same priority?
The order is then effectively undefined and depends on the internal load order of the records. For production setups, every source in a stock should therefore be given a unique priority.
7Does Distance take current warehouse utilization into account?
No, neither Distance nor Priority are aware of a source's current capacity. Anyone wanting to combine both needs a custom algorithm built on SourceSelectionInterface.
8From how many warehouses does Distance become worthwhile over Priority?
Once several warehouses are clearly separated geographically and shipping time matters to customers, usually starting at two or three locations across regions. With just one main and one backup warehouse, Priority is usually sufficient.
9What happens with an expired geocoding API key?
Already-geocoded sources keep working normally, but newly created sources can no longer be geocoded and are silently left out of Distance selection until the key is renewed.
10Is caching worthwhile for distance calculation?
For very large warehouse networks, yes, since the distance between a source and a postal code area practically never changes. A cache per postal code area noticeably reduces compute load on high-traffic checkouts.