Story · Last-Mile Delivery
Nine branches across Lagos. Online, the chain behaves as though it has one.
A supermarket group that already knows where all of its stores are, already knows what each one holds — and ships every web order from a single depot, past the branch at the end of the customer's street.
The shop and the people in this story are an illustration, not a customer. The software is real; the problem is one we keep being called about by retailers running more than one address.
Tuesday, 11:20
2.3 kilometres away. Dispatched from 25.
Chidi orders in Yaba. There is a branch of the same chain a seven-minute walk from his flat, open, stocked, with staff standing in it.
His order is picked at the central depot and driven across Lagos. The van passes within a street of the branch that could have filled it.
Folake, who runs retail operations, can see both facts on the same screen: the branch, and the order. Nothing in the system connects them.
One order, two possible journeys
Branch nearest the customer
2.3 km
Open, staffed, and not asked.
Central depot that shipped it
25 km
Across the city, past the branch.
The part that is already solved
They are not short of visibility.
Head office knows every branch address, every opening hour, what moves through each one. That reporting has existed for years and it is good.
The website has none of it. One address, one delivery fee table, one point that every distance is measured from. The map exists in the business and not in the checkout.
This is not a data problem. It is a wiring problem.
What head office sees
- Yabaopen · stocked
- Lekkiopen · stocked
- Ikejaopen · stocked
- Surulereopen · stocked
What the checkout sees
Central depot, Agbara
Same company, same week. The map exists in the business and not in the checkout.
What one origin costs
One fee, for a city that is not one city.
A single delivery rate across Lagos has to survive the worst journey on the list, so it is priced for the worst journey on the list.
Customers near a branch pay for a trip nobody made and quietly stop ordering. Customers far from the depot are carried at a loss on every order. The rate is an average of journeys with nothing in common.
One rate, three journeys
Priced to survive the last one, charged on all three. The near customer is paying for a trip nobody made.
So the orders go elsewhere
Renting back their own neighbourhoods.
The chain is listed on a delivery app — all nine branches. It pays a commission to reach people who live three streets from a shop it already owns and already staffs.
The order, the phone number, the reorder next Tuesday: all of it sits with the platform. The chain supplies the stock, the shelf and the name on the bag.
There is a branch on my street. Why did this take three hours?
What changes
Every branch becomes its own starting point.
Each branch runs as its own sales channel with its own fulfilment coordinates, and distance is measured from that branch's door rather than from a depot. Price rules and surcharges are scoped per channel too, so Lekki can price differently from Ikeja — different traffic, different cost base, the same software.
Said plainly, because it decides whether this fits: the plugin does not choose the branch. It prices and verifies the delivery for whichever branch's channel the order arrives on. Routing a customer to the right branch is the chain's own setup, and so is knowing whether the item is on that branch's shelf.
What it does do is stop measuring from the wrong place.
Yaba
own origin
Lekki
own origin
Ikeja
own origin
Surulere
own origin
Ajah
own origin
Ikorodu
own origin
Each branch is a sales channel with its own fulfilment point, its own price rules and its own surcharges. Which branch takes an order is your routing, not the plugin's.
The journey that actually happens
A shorter trip is a different rule.
When the origin is the Yaba branch instead of the depot, the distance that goes into the pricing engine is the real one — alongside total weight, volumetric weight, whichever is higher, the longest edge, the item count, the order value.
The rule that matches is a different rule, and it is cheaper because the journey is shorter, not because anything was discounted. Conditions combine with AND, priority decides, and no two active rules may share a priority, so checkout has exactly one answer.
- Driving distance
- 2.3 km
- Total weight
- 24.6 kg
- Volumetric weight
- 9.2 kg
- Longest edge
- 48 cm
Matched rule
0–5 km · over 20 kg · priority 30
Nine branches, nine realities
Mainland traffic is not island traffic.
Surcharges stack on the base price, each gated by its own conditions, each scoped to the channels it applies to. A peak-hour charge on the branches that sit in the worst of it, read in the fulfilment timezone. A bulky charge past a certain size. A fuel percentage changed in one field the week fuel moves.
And when an address cannot be resolved to a real street, checkout says so and offers another method, rather than inventing a distance and handing the chain the difference.
Base rule price
0–5 km from the Yaba branch
Peak hour
Mon–Fri 17:00–20:00, mainland branches
Bulky
Longest edge over 40 cm
Fuel
Percentage of the running total
At the door
One evidence standard, across every branch.
The branch moves the delivery to In transit, and that transition — not the order, not the payment — issues the code. Chidi receives it by email, or by SMS if that is the flow the chain builds: the plugin raises the event and leaves the channel to them.
Six digits at the door, entered on the order. Only a hash was ever stored, it expires, and it locks after a set number of wrong attempts. Or a photo does the same job — uploaded after the order was placed, so last week's picture cannot stand in for today's handover.
Nine branches, one definition of delivered.
Delivery code
Only a hash is stored. The code expires, and locks after too many wrong attempts — the same rule at every branch.
What head office finally sees
Nine cost pictures instead of one blended number.
Every order carries its own breakdown, written at the moment it was placed: base price, each surcharge by name, the total, the currency, and whether the customer saw it net, gross or tax-free.
So the question stops being what delivery costs the chain, and starts being what it costs out of Lekki on a Friday evening versus out of Ikeja on a Tuesday morning.
That is the number a chain can actually act on — open earlier, add a rider, re-cut a rule — and the one the platform was never going to hand over.
Delivery price breakdown
Yaba branch · written when the order was placed
- Base rule · 0–5 km
- ₦900
- Peak hour · +15%
- ₦135
- Fuel · +8% of running total
- ₦83
The chain's own delivery prices, not ours. Stored per order in its currency and labelled net, gross or tax-free to match what the customer saw.
Two sides of the same delivery
For the person waiting
- A trip that starts down the road rather than across the city, when the branch nearby is the one serving them.
- A delivery price on screen before paying, reflecting that shorter journey instead of a city-wide average.
- A code at the door that settles the handover, for them as much as for the rider.
- A relationship with the chain itself — not a listing inside somebody else's application.
For the chain paying for it
- Stores already paid for become fulfilment points, without new buildings or new leases.
- Delivery priced per branch, so a shorter journey can be charged as one rather than averaged away.
- Per-branch delivery economics, visible for the first time, instead of one national figure.
- Customer, order history and repeat business stay with the chain, reducing how much of its own neighbourhood it rents back.
Why people leave
The complaints, and which of them this answers
Retailers do not go looking for an alternative to delivery marketplaces like Chowdeck, Glovo or FoodCourt because of a feature. They go looking because of five recurring complaints — three of them from their own customers. Here is what changes on your own storefront, and what this plugin does not touch.
“The price on the app is not the price in the shop.”
What changes
On your own storefront there is no marketplace commission folded into the shelf price, because there is no marketplace. You set the price. Delivery is then calculated from the trip that is about to happen — distance, weight, size — shown at checkout before payment, and written onto the order as a breakdown: the base rule, every surcharge by name, the total, and whether it was net, gross or tax-free.
What this does not fix
It cannot make you transparent. You can still charge whatever you like. What it removes is a blended delivery fee that nobody, including you, can account for a month later.
“Why am I paying for the rider to reach the shop?”
What changes
A dispatch platform pays a rider to travel to the pickup point and then on to the buyer, and that first leg sits in the price one way or another — a journey made before the order existed. When the goods start where the rider starts, there is no pickup leg to price. This plugin only ever measures one: your door to theirs.
What this does not fix
It does not make your riders free. If yours wait at a depot and drive to a branch first, that cost is still real. It has moved out of the customer's delivery fee and into your own operation, where at least you can see it.
“Nobody told me where my order was.”
What changes
In transit is a real delivery state, and reaching it is what sends the customer their code. Delivered stops being a rider's word and becomes a recorded event with a time against it.
What this does not fix
It does not dispatch riders, does not assign them, and does not make anything arrive sooner. Fulfilling from a nearer branch can shorten the trip, but only if your routing and your stock allow it. This removes the silence, not the traffic.
“I could not get hold of anyone.”
What changes
The customer is contacting you rather than queueing behind a platform's automation. And the dispute that generates most of that contact — it never arrived — now has evidence on the order: a verified code with a timestamp, or a photo that had to be taken after the order was placed.
What this does not fix
It is not a support desk and it does not process refunds. It gives your team something to answer with. Answering is still yours.
“How do I know this seller is real?”
What changes
There is no third-party vendor to vet, because the shop is yours. The question stops being whether a marketplace checked the seller properly and becomes whether the customer trusts your name — which, for a chain with branches people walk past every day, is a question you have already answered.
What this does not fix
Nothing here is the plugin's doing. It is a consequence of selling direct, and it is worth saying so rather than claiming credit for it.
Straight answers
What this is not
The honest edges, including the ones that matter most to a chain. A plugin that claims everything is a plugin you find out about later.
- It does not choose the branch
- The plugin prices and verifies the delivery for the sales channel the order arrives on. Which branch serves a given customer is your own routing — a storefront per location, a picker, however you already do it.
- It does not check stock
- Proximity is not availability. Whether the nearest branch actually holds the item is a question for your inventory setup, and the plugin does not answer it.
- One origin per sales channel
- Each channel measures from a single point, which is why a branch is modelled as a channel. Several origins inside one channel are not supported yet.
- Not a rider network
- It prices deliveries and proves they happened. It does not supply couriers. A chain running its own riders is exactly the case it was built for.
- No live map
- There is no GPS tracking and no courier app. The states are open, in transit and shipped, with evidence attached to the order — not a moving dot.
- A manual “shipped” still works
- Staff with normal order permissions can mark a delivery shipped without a code or a photo. Shopware's own state machine allows it, and the plugin does not override that.
Not a mockup
It is running on our demo store right now.
Instant Delivery sits in the shipping selector at shophub.kommandhub.dev, beside Standard, Express and Self pick-up. Choose it without a full address and the checkout answers:
Please enter a complete delivery address (street and city) to use Instant Delivery.
That is the behaviour described above, in the open: no distance, no price, no guess. Add a street and the cost appears and follows the cart.
Open the demo storeBefore you ask
The questions a retailer asks first
Is this an alternative to Chowdeck, Glovo or similar delivery apps?
It is an alternative to listing on one. Those are marketplaces: they bring the demand, take a commission on it and keep the customer relationship. This is a shipping method inside your own Shopware store, so the demand is yours to generate and the customer stays yours. If you have no storefront and no way to deliver, a marketplace is still the faster route to orders.
Can it replace a delivery platform completely?
Not on its own, and we would rather say so. A marketplace supplies demand, a rider network and a consumer app. This supplies distance-based pricing, handover verification and a per-order record for deliveries you fulfil yourself. Retailers who already have branches and riders are replacing the part they were paying commission for; the demand still has to come from somewhere.
Do we need our own riders?
Yes. The plugin prices deliveries and proves they happened. It does not supply couriers, and it does not assign them. A chain already running its own riders is the case it was built for.
Is this an app our customers download?
No. It is a plugin for Shopware 6, so it runs inside the store you already have. Customers order on your website in a browser; your staff work in the Shopware administration. There is nothing to install on a phone.
Does it work across several stores?
Yes, with each branch set up as its own Shopware sales channel carrying its own fulfilment coordinates, price rules and surcharges, so distance is measured from that branch. Choosing which branch serves a given order is your own routing, and whether the item is on that branch's shelf is your inventory — the plugin does neither.
Last-Mile Delivery is in private beta.
We are running it with a small number of merchants before it goes public, which is why there is no download button on this page. If you run more than one address and every web order still leaves from one of them, tell us how your branches are set up and we will show you the real thing.