Concevoir un service géolocalisation temps réel pour plateforme de mobilité
OSRM route optimisation, MQTT position streaming, PostGIS queries, geofencing, GDPR, load testing 10k rides.

Sur une plateforme de mobilité, le service de géolocalisation est le système qui décide en réalité de la qualité perçue. Le matching trop lent fait fuir les passagers, l'ETA imprécise détruit la confiance, le suivi de course coupé fait s'inquiéter la famille restée à la maison. Sur un opérateur que nous avons accompagné, le temps de matching médian a été le KPI numéro un suivi par la direction pendant 18 mois — pas le revenu, pas l'uptime, pas le NPS, le matching. L'architecture du service géo détermine ce KPI, et elle se conçoit autour de quatre composants principaux : routage, streaming temps réel, requêtes spatiales et conformité légale. Le routage couvre deux besoins distincts. Le calcul d'un trajet point-à-point avec ETA est typiquement délégué à OSRM (Open Source Routing Machine), self-hosted sur des serveurs CPU avec un OSM pre-processed pour la région servie. Un OSRM bien tuné répond en 5 à 20 ms même sur des trajets de 30 km, soit des ordres de grandeur plus rapides qu'un appel à Google Directions ou Mapbox. Pour les besoins multi-stop (livraison, covoiturage avec arrêts intermédiaires), Vroom ou OR-Tools en complément résolvent le VRP (Vehicle Routing Problem) en quelques secondes pour 10 à 30 points. Garder un Google Maps en fallback pour les zones où l'OSM est incomplet (parkings privés, voies récentes) est une politique pragmatique. Le streaming temps réel des positions est l'épine dorsale du système. Le chauffeur publie sa position chaque 3 à 5 secondes sur un topic MQTT (Mosquitto ou Emqx en cluster 3 nœuds avec retained messages). Le passager s'abonne uniquement pendant la durée d'une course active, ce qui borne naturellement le fan-out. Côté serveur, un consumer (Go, Rust ou Python avec asyncio) souscrit aux wildcards par zone géographique et écrit dans Redis avec un TTL de 30 secondes. Cette séparation à trois étages — broker MQTT pour le fan-out, Redis pour le hot-state interrogeable, PostgreSQL pour l'historique — est ce qui permet de tenir 3 secondes de p50 sur le matching même à 10 000 chauffeurs simultanés. Les requêtes spatiales reposent sur PostgreSQL avec l'extension PostGIS. La requête canonique — « trouve-moi les 10 chauffeurs disponibles dans un rayon de 2 km de cette position » — s'écrit `SELECT driver_id FROM driver_positions WHERE ST_DWithin(position, ST_MakePoint($lng, $lat)::geography, 2000) AND status = 'available' ORDER BY position <-> ST_MakePoint($lng, $lat)::geography LIMIT 10`. Avec un index GIST sur la colonne `position` (`USING GIST(position)`), cette requête répond en 5 à 20 ms même sur 100 000 chauffeurs actifs. Le piège : les chauffeurs très actifs génèrent des updates à chaque seconde, et écrire dans une table PostgreSQL à 10 000 writes par seconde tue le throughput. La parade est d'écrire dans Redis en hot path et de flusher vers PostgreSQL toutes les 30 secondes pour l'historique. Le géofencing — alerter quand un chauffeur sort d'une zone autorisée, calculer les surcharges de zone, valider qu'une course de retour démarre bien dans la zone d'arrivée — utilise des polygones stockés en PostGIS. La requête `ST_Within(position, zone_polygon)` est rapide avec un index GIST sur les polygones eux-mêmes. Pour les alertes en temps réel (chauffeur qui sort), un trigger PostgreSQL qui écrit dans une queue Redis suffit ; pour les calculs statistiques (temps moyen par zone, fréquence de visite), des matérialisées vues rafraîchies toutes les heures portent la charge sans pénaliser le hot path. La conformité RGPD est le sujet qui transforme un prototype technique en produit déployable. Les positions chauffeur en France sont des données personnelles : la jurisprudence CNIL impose une durée de conservation strictement proportionnée à la finalité. La pratique standard est de conserver les positions précises pendant 30 jours (gestion litiges, sécurité), puis d'agréger en hexagones H3 ou tronquer à 100 m de précision pour les 12 mois suivants (analytique), puis de supprimer définitivement. Un job pg_cron quotidien qui exécute un `DELETE FROM driver_positions WHERE captured_at < NOW() - INTERVAL '30 days'` et un `INSERT INTO driver_positions_aggregated ...` règle la mécanique. Les accès aux traces (équipes data, support, justice) doivent être loggés de manière immuable et accessibles à l'audit. L'optimisation bandwidth côté chauffeur est un sujet réel, surtout en zone rurale. Un Raspberry Pi CM4 ou équivalent monté dans le véhicule peut servir d'edge gateway : il agrège les positions GPS du téléphone et d'un récepteur dédié, compresse via delta-encoding (envoyer le delta par rapport à la position précédente plutôt que la valeur absolue), filtre les mouvements insignifiants (<5 mètres, sans changement de cap) et bufferise jusqu'à 24 heures en cas de perte 4G. C'est une optimisation qui devient cruciale au-delà de 5 000 chauffeurs simultanés, où les coûts bande passante et stockage commencent à peser sur la marge unitaire. Le load testing pré-production est non-négociable. Artillery ou K6 simulent 10 000 chauffeurs publiant simultanément sur le broker MQTT, et 30 000 passagers requêtant les chauffeurs disponibles en parallèle. Les métriques à surveiller : latence p95 des `ST_DWithin`, débit messages/seconde acceptable par le broker MQTT (Emqx tient typiquement 50 000 à 100 000 msg/s par nœud sur du matériel raisonnable), saturation du consumer Go entre MQTT et Redis, et — souvent oublié — le coût mémoire du connection pool Redis quand chaque chauffeur a sa propre session. Un test charge réaliste révèle systématiquement deux ou trois bottlenecks que ni le code review ni les tests unitaires n'auraient trouvés. La leçon transverse, sur les projets de mobilité que nous avons opérés : le service géo réussit ou échoue sur la discipline des trois couches (broker / hot-state / vérité historique) et sur la rigueur de la conformité RGPD. Le reste — choix du broker MQTT, version de PostGIS, langage du consumer — sont des optimisations qui peuvent évoluer avec le temps. La séparation des trois couches, elle, doit être posée dès le premier jour, parce que la remonter rétrospectivement sur une plateforme en production est un chantier de plusieurs mois.
— · —
← Retour au journal