We like to move it move it…

Dhruv Sikri
Mercadona Tech
Published in
6 min readAug 29, 2023

👋 Hello! I’m Dhruv, and I work at Mercadona Online in Valencia as a Product Manager in the Capacity Vertical. Mercadona Online is the e-commerce arm of the largest grocery company in Spain.

Over the last few months, we’ve been working on building an automated system that moves capacity dynamically between different delivery zones to help our customers (aka “Jefes”) get their orders at the time they most like. Sounds gibberish? Read on to learn more about it!

Ok, but what do you really do?

On an average day in Mercadona Online, more than 600 trucks leave from one of the 6 preparation hubs (aka “hives”) to deliver to 10.000 customers (aka “Jefes”). As the capacity vertical (aka “Oferta”), we manage how these 10.000 orders are distributed geographically and temporally, which has implications on the quality of service we offer and how profitable our business can be.

Slot availability for order delivery: The customer selects the slot they wish to receive their order in; each box representing one slot

This distribution is managed through slot availability that Jefes see. Our team decides which slots the Jefes can order in.

So you just change colors of some boxes; that sounds easy right?

Well, not so much. Fundamentally, managing the availability is an optimization problem to offer the slots that the Jefe wants while ensuring delivery feasibility and business efficiency. We want to allow the Jefe to buy in the slot they most like, ensure we are capable of meeting the delivery promise with the planned resources and do it while actually making some money from it.

We define availability at an area or zone level. A group of postal codes together make up an area. So, all Jefes that live inside an area see the same availability. What availability the Jefe sees is a result of various inputs, but the most important being how many vehicles or trucks are available to deliver in the area they live in. The more vehicles we have in an area, the higher the capacity we would have to deliver, and hence better the availability.

Hmm… sounds pretty sorted already. What’s exactly the problem here?

One preparation hub (hive) can deliver to multiple areas or zones. So, in order to show the suitable availability, we need to know the number of vehicles that are active in that area. In the past, we used to allocate each area a certain number of vehicles, create availability using these fixed vehicles, and let Jefes purchase.

The problem with the fixed vehicle allocation approach is that demand is highly volatile. The approach forces you to predict how many orders you’ll sell in each area and allocate vehicles accordingly. If you make a wrong prediction, you may end up with too few resources in one area (read poor availability for Jefes) and too many underutilized resources in another (read idle trucks).

We were losing around 2% of our planned capacity due to the sub-optimal distribution of resources (trucks) between areas. That might sound small but at the scale we operate, small percentages can move a lot of money.

And what’s this fancy dynamic capacity thingy you told us about earlier?

In order to solve this problem, we realized that instead of trying to predict the demand, we should let it guide us. It was better to be reactive and adapt ourselves to the demand. We started with a base allocation of vehicles at an area level, and moved them from one area to another depending on how demand was behaving in real-time.

Each hour, the algorithm compares “occupancy rates” between areas. Occupancy is defined as the number of orders sold at a given time divided by the capacity we have in that area. If an area has a 90% occupancy, that means we’re close to selling all the capacity we had planned. While if an area has a 10% occupancy, it tells us that the area is under-utilized and the capacity planned in this area might be better used elsewhere. In such a case, if the occupancy difference is above a threshold, we would move a vehicle from the low occupancy area (source) to the high occupancy area (destination). In this way, we balance capacity in real time across delivery zones to better match the demand.

Obviously, this is a hyper simplification. It had to be adapted to our particular nuances and tailored to manage the specific objectives we had in mind.

In retrospect, I believe there were some broad principles that helped us push it through, especially when things were tough.

1) Small iterations >> Big Bold ideas

When we started, there were a lot of uncertainties. We didn’t know if it was even possible, we didn’t know how complex the logic would need to be or how many factors we would need to consider.

In order to learn quickly, we did some really shoddy stuff. Before writing a line of code, we built SQL queries to test simple logics that prompted the user every time it detected a movement. Our “MVP” was literally a black screen where a python command showed two areas — which area we need to remove a vehicle and where to give it. We took turns to manually implement that movement in our system.

The MVP: A beautiful black screen that rather curtly tells us what we are supposed to do

During this phase, the idea was not to try adding value to the user but to learn the most basic logic that could work at scale.

2) Law of unintended consequences

I’ve realized over time that in the world of logistics, any initiative you undertake will have consequences outside your core objective. These unintended consequences have the potential to derail you from your objective and lose focus entirely.

We went into this with the objective to better match our capacity to the demand and hence utilize better our resources. But each area has a different delivery efficiency: you have to spend more time moving around in rural or suburban areas because orders are farther apart compared to dense urban locations. So, a vehicle movement could potentially help you improve availability but make your delivery more inefficient. Is it worth making such a movement?

The complex nature of multi-variable optimization blurred our path, often causing some fundamental differences in what we were trying to achieve through our objective; which brings me to the final point.

3) Finding the common language

When the problem is multi-variate, it is important to have clear the possible consequences and impact you can have, and convert them into a common denominator.

A vehicle movement could help us sell more, it could help improve availability to the Jefe or it could affect the efficiency of our delivery routes. We converted all of these into a single denominator: how many additional or fewer orders moving a vehicle helped us sell.

Obviously, comparing concepts that have structurally different meanings is hard. But I believe it is essential to do this even if it’s done with various different hypotheses and assumptions built in.

En fin…

What started off as a wacky idea 6 months ago is now capable to automatically adapt better our availability to demand trends across all hives. By letting us utilize our resources more efficiently, it has helped us bring down that 2% sale loss to consistently sub 1%.

Some logistics products can seem odd— you look around, and everything seems similar. But dig down a little, and you realize how fundamentally things have moved.

--

--