What food delivery taught me about engineering

I'm a developer who ended up co-founding a delivery service. A kitchen at peak hour turned out to be the best systems-design school I've had.

This post is available in another language: Русский

For most of my career I built systems other people used: an operator's subscribers, a bank's clients, users of payment services. There was almost always someone between me and reality — an analyst, a product manager, a support team.

Then came SOR PIZZA — a food delivery service in Dushanbe that we built as a technology business. We wrote our own CRM, an order-processing system, courier apps, telephony integration, analytics tools. And for the first time there was nobody between me and the consequences of my decisions.

It turned out to be the best engineering school I've had. Here's what I took from it.

The domain is messier than any model

In calm conditions an order looks neat: the customer picks, pays, the courier delivers. You design a tidy process, draw a state diagram, everything adds up.

Then life starts. A customer dictates an address that isn't on the map. The building exists but the entrance can't be found. The phone is off and the courier is standing at the door. It starts raining and half the couriers slow down. The customer asks for "no onions" after the pizza has gone into the oven.

None of these are edge cases. They happen every day, and a system that only handles the "normal" path is useless in practice: people simply stop using it and go back to paper.

I learned something simple: in an operational business the real work isn't the happy path, it's the exceptions. You can't "finish them later", because they are the job.

An interface for someone whose hands are full

I designed our call-centre and kitchen software the way I'd design an ordinary web app. That was a mistake.

At peak hour an operator doesn't read the interface. They're on the phone, entering the order and listening to the kitchen shouting at them at the same time. They have no spare capacity to "figure out the form".

What turned out to matter:

  • Every extra click costs money. Not metaphorically: multiplied by hundreds of orders it becomes minutes of delay and an annoyed customer.
  • A screen should answer one question: "what do I do right now?" — not display everything the system knows.
  • Prevent errors instead of reporting them. Validation after submit is useless in real time.
  • If it's awkward for staff, they'll work around the system. They'll jot it on paper, agree by voice, fix it later. At that moment your data stops reflecting reality — and so does all your analytics.

That last point was the most sobering for me. I used to think a bad interface was about discomfort. It turns out it's about whether your data is true.

The phone never went away

It's easy to design a beautiful product if you assume everyone orders through the app. In reality a large share of people simply call — out of habit, because it's faster, because they don't want to install an app for one pizza.

So telephony integration turned out not to be a secondary feature but part of the core. When the system recognises the caller's number and immediately pulls up their previous orders and address, the conversation is cut in half. That isn't a "feature" — it's time saved on every single order.

The broader lesson goes beyond delivery: don't design for the audience that's convenient for the developer. Look at how people actually want to interact with you.

A metric instead of an opinion

In employment, the quality of your work is often judged indirectly: the code passed review, the ticket is closed, the release shipped. In my own business a much harsher feedback loop appeared — the time from pressing a button to food at the door.

That number doesn't argue. You can't explain it away with elegant architecture. If a change to the system didn't improve it, the change was useless, however neat it looked inside.

That focus sorts a lot of things out. You start to see that some work you were proud of changes nothing. And conversely, that boringly automating one routine operation delivers more than a month of refactoring.

Data that collects itself

The most useful thing we did wasn't reports — it was the habit of recording operational events as they happen: when the order was taken, when it went to the kitchen, when it was assembled, when the courier picked it up, when it was delivered.

Without that, every discussion of a problem turns into a clash of opinions: "the kitchen is slow" versus "we don't have enough couriers". Once there are timestamps, the argument ends in five minutes — you can see exactly which stage is losing the minutes.

This is probably the most portable lesson. In any system it's worth asking upfront: which events will I want to measure six months from now? — and starting to record them immediately, even if you don't yet know why.

What changed in me as an engineer

My criterion for a good system used to be technical: clean architecture, readable code, no duplication. Now the first question is different: what specifically gets better once this works?

Lower costs. A faster process. Less manual work for an employee. Fewer mistakes. If there's no answer, maybe the task shouldn't be done at all, however interesting it is to solve.

This doesn't cancel engineering culture. It puts it in the right place: technical quality is a means, not an end. A beautiful system that saves no minutes and prevents no errors is just an expensive hobby.

Oddly enough, it was a pizzeria that made me a more demanding developer than any code review ever did.