The problem
Field data arrived through phone calls, paper forms, photos and spreadsheets completed after the fact. Dispatchers did not have one operational view. They had to assemble it from several systems to understand where each vehicle was, who was working on it and whether the job was complete.
This did not call for another isolated mobile app. It required a system that owned the path of the data from the field event to the existing database.
The constraints
- More than 5,000 vehicles across 1,000 geographical locations.
- iOS, Android and web using the same business rules.
- An existing SQL Server model and business logic that could not be replaced at once.
- Weak or intermittent connectivity in the field.
- Evidential storage of photos, coordinates and timestamps.
- Continuous operations: migrations could not stop the business.
The hard part was not the mobile screen. It was making the mobile app, backend, legacy model and daily operation agree on the same truth.
The architecture
The field application serves iOS and Android from one Flutter codebase. Required data is also stored locally, so capture continues through network failures. Synchronisation reaches the .NET backend through versioned APIs.
The backend handles more than 100 REST endpoints, background processing, integrations and geospatial calculations. Transactional data remains in SQL Server while large binary files live in a separate storage layer. Components can be replaced incrementally, avoiding a single high-risk migration day.
What we built
- An offline-tolerant field workflow for iOS and Android.
- GPS, timestamp, QR and photo-based events.
- Consistent photo processing and image dimensions across both mobile platforms.
- A dispatcher view for day-to-day operations.
- A .NET backend with more than 100 API endpoints.
- SQL Server data models, reporting and integrations.
- Production deployment, monitoring and operational support.
Measured and technical outcomes
| Before | After | |
|---|---|---|
| Main operational report | 306 s | 0.4 s |
| Photo processing | platform-specific | consistent dimensions and compression on iOS and Android |
| Photo storage | inside the transactional database | separate file storage with database references only |
| Automatic odometer recognition | manual | 74.6% on real, noisy data |
| Field capture | paper / later | on site, GPS + time + photo |
The client estimated that dispatcher phone time fell by roughly two hours a day and that retyping worksheets disappeared. That is explicitly a client estimate; the technical outcomes above are supported by system measurements and the implemented behaviour.
What we would do differently today
We would separate transactional data from file storage earlier. Every operational report would get a performance budget, and sync failure modes would be tested on real network conditions in the first prototype.
We would keep the incremental delivery model: put one critical process into production, measure it, and build the next one on top. It provides lower technical risk and faster operational feedback than replacing an entire system on one date.
This case study is anonymised. A named reference is available on request during a technical call.