Skip to main content
Case Study

Delivery Partner App for a Last-Mile Fleet

Mobile App Flutter Laravel Logistics

Delivery work happens in the places mobile networks are worst: basements, lift shafts, service corridors and dense building cores. The client's previous app treated connectivity as a precondition, so a rider standing at a door with a parcel in hand could not record the delivery. ELIVTECH rebuilt it in Flutter around a durable local queue, where every action is recorded first and synchronised second, and one codebase serves both platforms.

The client runs a last-mile delivery operation for retail and grocery clients using a fleet of contracted riders. Its previous app required a live connection for each step, so failed actions were retried at the next signal or reported by phone, and the control room maintained a parallel picture of the day in a spreadsheet. Proof of delivery was inconsistent, route information arrived as a list rather than as guidance, and earnings were queried constantly because riders could not see how a figure was reached. ELIVTECH rebuilt the app in Flutter with an offline-first action queue, deterministic conflict handling on a Laravel API, structured proof-of-delivery capture, and an earnings view derived from the same records the settlement run uses.

At a glance

0 Weeks End-to-End
0 Codebase Shipping to iOS and Android
0 Offline-Capable Field Actions
0 Field Actions Lost to Connectivity Gaps

The challenge

An app that assumed the network, used in the places where the network is least reliable.

Actions that failed where the work happens

Marking a pickup or a delivery required a successful request. Inside a basement car park or a lift, the request failed and the rider was left holding a parcel the system considered undelivered. Riders developed workarounds, stepping outside to get signal or calling the control room, and both cost time on every affected stop.

A control room running on a parallel record

Because app data was unreliable, the control room maintained its own picture of the day in a spreadsheet updated by phone. Two records existed for every route and they disagreed regularly, so answering a client's question about a parcel meant checking both and deciding which to believe.

Proof of delivery captured inconsistently

Evidence was a photograph if the connection allowed one, a name typed into a free-text box if it did not, and sometimes nothing at all. When a client disputed a delivery, the available evidence varied by rider and by signal strength rather than by policy, which made disputes difficult to close.

Routes delivered as a list

Riders received stops as an ordered list with addresses and nothing else. Sequencing decisions, access notes and building specifics lived in individual memory, so an experienced rider was substantially faster than a new one on the same route and none of that knowledge was captured anywhere.

Two builds, two release cycles

Separate iOS and Android applications meant every change was implemented and tested twice, and the platforms drifted apart between releases. A fix urgent enough to matter still had to wait for whichever build was further behind, and riders on different devices saw different behaviour.

Earnings that could not be checked

Riders saw a payment figure with no breakdown of the stops, distance and incentives behind it. Every question became a support conversation, and the volume of those conversations was a direct consequence of an interface that showed a total without showing its basis.

Our solution

Record locally first, synchronise second, and make the reconciliation rules explicit rather than incidental.

Field Research and Offline Modelling

Three weeks riding routes to observe where connectivity actually fails and what riders do when it does. That produced the offline model: which actions must succeed locally, how long a device might plausibly stay disconnected, and what a stale local record is allowed to overwrite when it finally syncs. Every one of those decisions was made deliberately rather than left to whichever write arrived last.

Flutter App with a Durable Action Queue

Field actions are written to a local database with a client-generated identifier and a device timestamp, and the interface advances immediately on that local write. A background worker drains the queue when connectivity allows, preserving order per delivery so a completion cannot arrive before the pickup that precedes it. Riders can see exactly which actions are still pending. The queue survives an app restart or a device running out of battery mid-route, because it is written to durable storage rather than held in memory, which is the condition under which the previous app lost work most often.

Deterministic Reconciliation on the Laravel API

The API treats client identifiers as idempotency keys, so a replayed action is recognised rather than duplicated. Conflicts follow declared rules instead of arriving-last-wins: a control room cancellation outranks a later field completion, while a delivery recorded offline is accepted even when it arrives after a reassignment, with both outcomes written to an append-only log.

Structured Proof, Route Guidance and Earnings

Proof of delivery captures a photograph, a recipient category and location metadata against a defined schema, held locally at reduced size and uploaded when bandwidth allows. Route guidance carries access notes and building specifics that riders contribute back. Earnings show the stops, distance and incentives behind a figure, drawn from the same records the settlement run uses, so a rider checking a payment and an operator checking the same payment are reading identical data.

Technology stack

Flutter Dart SQLite (on-device) Laravel MySQL 8 Laravel Queues Redis Push Notifications AWS ECS Fargate Amazon RDS Amazon S3 Amazon SQS Amazon CloudWatch Automated Device Testing CI/CD Pipeline

Results

Measured once the full fleet had moved to the new application across both platforms.

0 Field Actions Lost to Connectivity Gaps
0 Crash-Free Sessions Across Both Platforms
0 Release Shipping to Both Platforms Together
0 Deliveries With Schema-Complete Proof

Before and after: platform engineering measures

Before
  • Every field action required a live connection to succeed
  • Riders stepped outside or called the control room to record stops
  • A parallel spreadsheet record maintained by phone
  • Proof of delivery varied by rider and by signal strength
  • Routes issued as an ordered list of addresses
  • Separate iOS and Android builds on divergent release cycles
  • Earnings shown as a total with no breakdown
After
  • Actions recorded locally first and synchronised in the background
  • Pending actions visible to the rider until confirmed
  • One record of the day, with the control room reading the same data
  • Proof captured against a defined schema regardless of connectivity
  • Guidance carries access notes riders contribute back
  • One Flutter codebase releasing to both platforms together
  • Earnings itemised from the records settlement actually uses

Project timeline

Weeks 1-3

Field Research and Offline Modelling

Route observation across building types, connectivity mapping, action inventory and offline eligibility, conflict rule definition, and the target Flutter and Laravel architecture with the sync contract.

Weeks 4-9

Sync Foundation and API

On-device queue with local database, client-generated identifiers, ordered drain per delivery, idempotent Laravel endpoints, append-only reconciliation log, and the deployment pipeline on containerised AWS infrastructure.

Weeks 10-14

Field Workflows

Pickup, delivery, failed attempt and reassignment flows, structured proof-of-delivery capture with local media handling, route guidance with contributed access notes, and the itemised earnings view.

Weeks 15-19

Testing and Hardening

Automated tests across the conflict matrix, scripted connectivity-loss scenarios on real devices, battery and data usage profiling across a representative device range, and accessibility work on high-frequency screens.

Weeks 20-22

Pilot and Fleet Rollout

Pilot with a rider group across difficult buildings, monitoring on queue depth and sync latency per device, control room transition off the spreadsheet, then staged rollout by depot with the previous app retained until each was stable.

Key takeaways

What shaped the engineering decisions

  • Offline-first is a data decision, not a UI one: Caching reads while still requiring a live write was rejected because the failing actions were all writes. Recording locally and treating the server as an eventual destination is what actually removed the failure.
  • Declare the conflict rules, do not inherit them: Last-write-wins would let a stale offline action overwrite a control room decision. Writing the precedence rules explicitly, case by case, meant the reconciliation was reviewable instead of emergent.
  • Idempotency keys make retry free: With a client-generated identifier treated as an idempotency key, the queue can retry as aggressively as it needs to without any risk of double-recording a delivery.
  • Preserve order per delivery, not globally: A global ordering constraint would stall the whole queue behind one problematic action. Ordering per delivery keeps sequence where it matters and lets everything else drain freely.
  • Capture proof against a schema: Allowing evidence to vary with signal strength made disputes unresolvable. A defined schema held locally until upload means the record is complete regardless of where the delivery happened.
  • Rehearse the failure, then measure the device: Connectivity loss was scripted into the automated tests and rehearsed in real buildings, and battery and data usage were profiled across a representative device range because a field app that drains a phone is not usable however correct it is.
Where this app goes next. With a durable queue and explicit reconciliation rules, adding a field workflow is a matter of defining its offline behaviour rather than rebuilding sync. The team is extending the same foundation toward in-app route resequencing that works while disconnected, richer failed-attempt handling with customer-facing rescheduling, and depot analytics drawn from the access notes riders have been contributing.

Want results like these?

Let's discuss how ELIVTECH can drive measurable outcomes for your business.

Start your project