Mobile App Development for Home Repair Service (Plumber, Electrician)
The task "connect customer with master in 3 minutes" sounds simple on the surface: request form, list of executors, "call" button. In practice — it's real-time geo-location matching, task queues with priorities, two-way notifications, and the "cold start" problem with zero masters in the database.
What Actually Breaks During Development
The main pain point — live map with masters. If each master sends location every 3 seconds via REST, with 50 concurrent executors the server gets 1000 requests per minute just for position updates. Solution: WebSocket channel (Flutter — web_socket_channel 2.x package) plus server-side throttle. Client receives delta-updates, not full list. On map — flutter_map with TileLayer from OpenStreetMap or Google Maps SDK, depending on license budget.
Second problem — job state machine. Typical graph: created → assigned → accepted → in_progress → completed | cancelled. If you don't lock transitions at backend level and sync with local state (Riverpod StateNotifier or BLoC), client sees "master is coming" even after cancellation — because push came later than user refreshed screen. Solve via FCM data messages instead of notification messages: app decides what to show based on current state.
Another thing: ratings and reviews can't be open before job completion. Without server check on review submission status, masters get ratings for jobs that never happened — seen this in three different projects.
Stack and Architecture
Flutter + Dart as main cross-platform choice: one codebase for iOS and Android, native calls via MethodChannel — for background geolocation (background_locator_2) and handling incoming calls via VOIP (iOS — CallKit, Android — ConnectionService). Built-in chat — via Firebase Realtime Database or own WebSocket, media files (damage photos) — via Firebase Storage or S3 with presigned URLs.
Architecturally: Clean Architecture with domain / data / presentation layers. Repositories isolate logic from data source — easy to swap Firebase for own API without rewriting UI. GetIt as service locator for DI, Dio with interceptors for REST, hive for offline job cache.
Key integrations:
- Google Maps SDK / Yandex MapKit — master's route to customer
- Firebase Cloud Messaging — status change notifications
- Stripe / CloudPayments / YooKassa — payment after completion
- Twilio or Vonage — number masking on calls
- OneSignal — marketing pushes and retention campaigns
Master Onboarding Separately
Executor verification — not just a form with fields. Need document upload (passport, license), manual moderation or verification service integration (e.g., Russian "Kontur.Focus" for entrepreneurs). Flutter: image_picker + dio multipart upload, check status via polling or WebSocket. Until account is verified — is_verified: false flag blocks job receipt at API middleware level.
Work Process
- Requirements audit — figure out: monetization (commission per job or master subscription), geography (one city or federal network), need dispatcher web cabinet
- Design — ERD, State Machine diagram for job, API contracts (OpenAPI 3.0)
- UI/UX — Figma prototype, separate flows for customer and master
- Development — 2-week sprints, CI/CD via Fastlane + GitHub Actions
-
Testing — integration tests on
flutter_test, manual QA on real devices - Publication — App Store + Google Play, ASO setup, screenshots and descriptions
Timeline
MVP (customer + master, basic matching, payment, pushes): 10–16 weeks. Full platform with dispatcher cabinet, analytics and verification: 20–28 weeks. Cost calculated after TZ analysis — too much depends on number of master categories and coverage geography.
Common Expensive Mistakes
- Implement geolocation without
background_locator— master "disappears" from map when app minimized on Android 12+ due to Doze Mode - Store FCM tokens in local DB without TTL — after 3 months 30% tokens expire, pushes stop delivering
- Don't separate FCM channels for customer and master in one app — both get wrong notifications on role switch







