Checkout, the screen where the customer pays, charged the same shipping for an address 1.4 km away and for one 16 km away. It was the most democratic rate in Lima: whoever lives close by was buying the trip for whoever lives far. Nobody on the team could say what it cost us to reach each address, because the rate came out of an old deal with our delivery rider and we never compared it against a measured cost.
A local order leaves the store with the rider and comes back. The cost of that trip depends on distance and on the hour, because Lima traffic changes during the day, but the customer always saw the same number in the cart. The register doesn't show it either: delivery goes in as order revenue and the rider as a fixed monthly expense, two lines that never meet.
Charging flat is like a micro, one of Lima's small private buses, charging the same fare for one block as for the whole route. It looks fair until you glance at the taxi meter next to you and see which stop the business started paying the trip from. My first theory was that the problem was limited to three or four districts on the edge. I was wrong.
13 of 18 districts in the red
We measured 18 districts from the store's front door. In 13 the regular flat rate doesn't cover the cost of the trip, and the 5 still in the green all sit inside the short radius. The loss grows almost in a straight line with distance: break-even shows up around 4 km, and in the most expensive district the loss per delivery is two and a half times the average of those 13. The express rate, which charges more for same-day delivery, was set correctly in every district except the farthest one.
Me, who said three or four districts
The price comes from a taxi app's fare
The country has no public delivery API, an official place to ask a system what it costs to go from one point to another. We compare against a taxi app's fare, the reference anyone can see from their phone: a service of ours looks up the price of the trip to each delivery address.
Keeping it standing cost more than writing it. The lookup needs a live session, so a cron job, a scheduled task, renews it every 12 hours so it doesn't expire. Opening a browser from scratch on every query is slow, so a separate microservice keeps the browser open and stores each quote for 90 seconds in a cache.
The 9 seconds weren't ours
We measured the same quote through all three paths: 9.2 s with a cold browser, 9.6 s with the browser already warm and 0.002 s when the answer comes from the cache. Those 9 seconds belong to the provider, which spends them calculating its fare on the other side of the connection. We left the warm browser in place because it was already built, and we didn't spend another minute there. The cache bought the speed, and the quote is requested in the background while the person finishes typing the address, so the form never sits blocked waiting on the provider.
The same route changed 33% in one day
We repeated measurements on one route and the price varied as much as 33% within the same day, because rush hour and demand at that moment move the app's fare. The morning number is useless in the afternoon, so the quote is captured when the delivery is recorded and never recalculated later.
We set the prices by hand
We thought about putting in a per-kilometer formula and letting checkout charge whatever the calculation returns. We didn't do it: there are districts where it pays to lose on shipping to win the customer, and a script doesn't make that call. We handed over the table of 18 districts, the gap in each one and the break-even point.
Two limits remain. 18 districts are a sample, not the full map of Lima, and a taxi app's fare is a borrowed reference for what our own rider actually costs us. It's enough to see the order of magnitude and where the line crosses.
Now the system quotes before we promise
We also learned to measure before optimizing: we believed the warm browser would bring down those 9 seconds, and it came out 0.4 s slower than the cold one. The address 16 km out no longer travels as a guest, it gets recorded with its reference cost next to it.
