CASE STUDY

Food & Grocery Delivery Platform: Customer, Merchant, and Driver Apps

Undisclosed clientFood & grocery delivery (multi-country)8-Minute Read

A restaurant order, a grocery basket, and the driver carrying both rarely share one piece of software. This undisclosed client wanted all three on a single backend, running in several countries, with checkout that clears through Adyen in Switzerland and Stripe or PayPal elsewhere. Sigi Technologies designed and built the customer, merchant, and driver apps in Flutter, plus an admin panel, on a Node.js, MySQL, and Redis platform hosted on AWS. Group ordering, loyalty credits, and referral campaigns run inside the same order flow.

Stock photo of cardboard parcels, one labeled fragile, stacked in the back of a delivery van

A multi-country food and grocery delivery platform in one build

The client operates a food and grocery delivery service across more than one country and prefers not to be named. Restaurants and grocery stores list on the platform, customers order from either in the same basket, and a pool of drivers handles the last mile. Before the engagement, each of those groups was served by a different tool, and the client wanted a product of its own: a customer app, a merchant app, a driver app, and an admin panel.

Multi-country operation shaped the brief from the start. Swiss customers expect local payment rails, so the platform integrates Adyen (TWINT) for Switzerland alongside Stripe and PayPal for other markets, and grocery pricing has to handle bottle deposits on returnable containers. The project sits squarely in our food delivery industry practice.

Why three apps on one backend was the hard part

Building a food delivery app for a single audience is well understood. The difficulty here was that every order touches three people with different goals, in different countries, on different payment rails, and any lag or mismatch between the apps turns into a cold meal or a driver waiting at a closed kitchen. The concrete problems the client brought to us:

  • Order state lived in separate systems, so a merchant marking an order ready did not automatically release it to a driver, and customers phoned in to ask where their food was.
  • Checkout could not route by region: one gateway per market meant separate reconciliation, separate refund handling, and no shared view of loyalty credits or discount codes.
  • Group orders were handled by one person collecting money manually — no shared basket, no per-person payment, and no cutoff to stop late additions from delaying a restaurant.
  • Merchants printed orders by retyping them, because nothing pushed tickets to the Bluetooth or Wi-Fi receipt printers already on the counter.
  • Refunds, commissions, and service fees were negotiated case by case rather than applied from a policy, which made finance work slow and inconsistent.

The stack we built it on

All three mobile apps are written in Flutter from a shared codebase, so the customer, merchant, and driver experiences ship to iOS and Android together and reuse the same networking, authentication, and order models. The backend is Node.js on AWS, with MySQL as the system of record for orders, menus, merchants, drivers, and ledgers, and Redis in front of it for the short-lived state that changes every few seconds — driver locations, open dispatch jobs, and basket sessions during group ordering. Firebase delivers push notifications so each app hears about a state change the moment it happens. This is the pattern we recommend for most custom software builds where several apps share one domain model.

The second architectural decision was to model an order as a single state machine that all four surfaces subscribe to, rather than letting each app keep its own copy. One transition is written once, in the backend, and pushed out. The lifecycle across the three apps looks like this:

  • Customer app: basket built (or a group order joined), delivery address and time chosen, payment authorized through the routed gateway — order created.
  • Merchant app: new order alert with ticket auto-printed; merchant accepts (or rejects with a reason that triggers a policy refund), sets a preparation time, and marks the order ready.
  • Backend dispatch: on acceptance the order enters the dispatch pool in Redis and is offered automatically to a nearby, available driver; unanswered offers roll to the next driver.
  • Driver app: driver accepts, follows the in-app route to the merchant, confirms pickup, then navigates to the customer and confirms drop-off.
  • Customer app: live tracking from pickup to door, then the receipt, loyalty credit posting, and a refer-a-friend prompt on completion.
  • Admin panel: commissions and service fees are computed on completion; refunds, cancellations, and disputes are handled from the same record.

How the platform is built and run

The platform is built so one order stays consistent across three apps, several countries and three payment gateways — one state machine, one payment record, one ledger:

  • Three Flutter apps — customer, merchant and driver — from a shared codebase, shipping to iOS and Android together and reusing the same networking, authentication and order models.
  • One order modeled as a single state machine on the backend that all four surfaces subscribe to, so a transition is written once and pushed out rather than each app keeping its own copy.
  • A Node.js backend on AWS with MySQL as the system of record for orders, menus, merchants, drivers and ledgers, and Redis in front for the short-lived state that changes every few seconds — driver locations, open dispatch jobs and group-order basket sessions.
  • Region-based payment routing: the app asks the backend for a payment session and a routing layer picks Adyen (TWINT) for Switzerland, Stripe, or PayPal by market and method, with every provider writing back to one internal payment record using the same statuses.
  • Automated dispatch out of the Redis pool: on acceptance an order is offered to a nearby, available driver, and an unanswered offer rolls to the next driver.
  • A group-ordering engine with a host-controlled merchant, address and cutoff, per-participant payment shares that must all authorize before the order submits, and loyalty credits and discounts applied per participant to their own share.
  • Merchant hardware and messaging: accepted orders print instantly to Bluetooth or Wi-Fi receipt printers at the counter, and Firebase Cloud Messaging delivers push updates at each state change.
  • Policy-driven finance: commissions and service fees computed on completion and refunds applied from policy, with payments from Adyen, Stripe and PayPal reconciled in one ledger rather than three dashboards.

What we implemented: across the delivery ecosystem

Sigi designed, built and shipped all four surfaces on one backend. Here is what we implemented across the customer, merchant and driver apps and the admin panel.

Customer app: food and grocery ordering, tracking, and rewards

  • Browse restaurants and grocery stores by location, with menus and product catalogs managed by merchants themselves.
  • Pay with saved cards or wallets through whichever gateway the region routes to, and apply credits, discount offers, or promotions at checkout.
  • Track the order in real time from acceptance through pickup to the door, with push updates at each transition.
  • Reserve a table at restaurants that offer it, from the same app.
  • Earn loyalty credits on completed orders and share a referral code that rewards both parties.

Group ordering rules

Group ordering was the feature the client cared most about for office and household use, and it needed firm rules so a shared basket does not stall a kitchen. The rules the platform enforces:

  • Host: the person who starts the group order chooses the merchant, delivery address, and time slot, and is the only participant who can submit the order.
  • Joining: guests join through a shared link and add their own items to the basket, each tagged with the guest’s name for the merchant’s ticket.
  • Split: the host can pay for everyone or ask each participant to authorize their own share; the order only submits once every share is authorized.
  • Cutoff: the host sets a deadline for additions; when it passes, the basket locks, unpaid shares are dropped or picked up by the host, and the order goes to the merchant.
  • Credits and offers: loyalty credits and discount codes apply per participant to their own share, never to someone else’s.

Merchant app: menus, promotions, and printed tickets

  • Manage menus, product listings, availability, and preparation times without contacting support.
  • Set up promotions such as buy-one-get-one and free-delivery offers with their own start and end dates.
  • Connect directly to Bluetooth or Wi-Fi receipt printers so each accepted order prints instantly at the counter or the kitchen pass.
  • Accept or reject incoming orders, with rejections feeding the refund policy automatically.

Driver app: automated assignment, routing, and earnings

  • Receive automated assignments from the dispatch pool rather than picking from a list.
  • Follow the in-app route to the merchant and then to the customer, with pickup and drop-off confirmations at each stop.
  • See a clear earnings dashboard covering completed deliveries and the current pay period.

Admin panel: commissions, refunds, and loyalty campaigns

  • Set commission rates and service fees per merchant or per market.
  • Apply policy-driven refunds so cancellations and rejections resolve consistently.
  • Manage loyalty credits, discount engines, and refer-a-friend campaigns across all countries.
  • Review payments from Adyen, Stripe, and PayPal in one ledger rather than three dashboards.

Delivery and engineering practice

The build ran surface by surface against the shared backend: the order state machine and payment routing first, then the customer app, the merchant app, and the driver app in turn, so each new app was tested against real transitions rather than mocks. Payment routing was exercised with each provider’s test environment before any market went live, and bottle-deposit and refund rules were checked against the client’s own examples. Hosting and deployment follow the AWS setup we use across our DevOps and cloud work, with the Flutter mobile apps released to the App Store and Google Play under the client’s own accounts.

The team and expertise behind the build

The platform was delivered end to end by one cross-functional Sigi team — product strategists, UI/UX designers, mobile and full-stack engineers, and QA — working as a single unit rather than handing the build between vendors. Sigi hires only specialists: every engineer is an expert in their own field, and we invest in the team as they deliver, supporting certifications and continuous learning so expert, motivated engineers stay on every build. It is the model we have run since 2016: deep, cross-industry expertise owning the whole stack, from the three Flutter apps and the Node.js backend to the regional payment routing across Adyen, Stripe and PayPal and the group-ordering engine. Keeping one order consistent across three apps, several countries and three payment gateways is exactly the kind of demanding, multi-surface engineering our team is built for — the same capability behind our mobile app development and custom software work.

What shipped

The client now runs its food and grocery delivery service on software it owns: three Flutter apps — customer, merchant, and driver — on iOS and Android, an admin panel, and the Node.js backend behind them. An order placed in the customer app prints at the merchant, dispatches to a driver, and settles through the right gateway for its country without anyone rekeying details, and finance works from one ledger and one refund policy. Group ordering, loyalty credits, and referral campaigns run inside that same flow, so growth features needed no separate integration work. The client name and its operating figures remain confidential at the client’s request.

Related work and how to start a similar build

Kwik eMart is a UK online supermarket where grocery catalogs and delivery slots were the center of the build. Bix Delivery is the closest technical sibling — Flutter customer and driver apps on a Node.js dispatch backend, built for parcels rather than meals. Mahir Company, covered in our ServiPR case study, is an on-demand home services marketplace that solves the same dispatch-and-payout problem for service providers instead of drivers, and the agritech marketplace app applies a similar Flutter and Node.js structure to farm machinery rental in Austria. Bix and Mahir share the customer, provider, and admin structure used here, and both sit in our on-demand industry work.

If you are planning a food and grocery delivery platform that has to work across markets — with regional payment routing, group ordering, or merchant hardware in scope — contact Sigi and we will walk through the order lifecycle for your case before anything is built.

Need a grocery app for your business?

Tell us what you want to build. We’ll show you how a Sigi team would scope, design, and ship it — and the stack it would take.