As Ninja Van scaled its last-mile delivery operations across Southeast Asia, manually planning delivery routes became a bottleneck. Drivers were dispatched with unoptimized routes, leading to longer delivery times, higher fuel costs, and inconsistent service quality across zones.
I worked on a Play Java microservice that coordinated the routing process by consuming delivery order events, classifying them into geographic zones, and computing optimized routes for each driver. The system used Hazelcast's read-through caching to serve route and waypoint data with sub-millisecond latency, backed by a multi-master MySQL cluster for high availability.
A visualization of the routing system in action. Three delivery drivers are dispatched from a central hub, each assigned to a different zone across Singapore. Watch as they traverse their optimized routes, delivering parcels to each stop.
Delivery order events are consumed via Kafka, validated, and enriched with geocoded address data before being stored in the MySQL database.
Each delivery address is mapped to a geographic zone using coordinate-based classification. Zones segment cities into manageable areas for efficient driver routing.
Orders within each zone are grouped and sequenced to minimize travel distance, using nearest-neighbor heuristics and time-window constraints.
Optimized routes are assigned to available drivers based on zone familiarity, vehicle capacity, and current workload. Routes and waypoints are cached in Hazelcast for fast retrieval.
Drivers receive their assigned route via the mobile app. The system tracks progress and updates delivery statuses in real-time as drivers complete each stop.
Each delivery is marked as successful or failed based on driver confirmation. Failed deliveries are rescheduled and fed back into the routing pipeline.
Implemented a distributed caching layer using Hazelcast MapLoader to reduce database load for frequently accessed route and zone data, achieving sub-millisecond lookups with automatic cache population on misses.
Leveraged Play Framework's non-blocking I/O model and CompletableFuture-based async actions to handle high-throughput route calculation requests without thread pool exhaustion.
Deployed a multi-master MySQL setup to ensure high availability and fault tolerance for delivery data, with read replicas serving routing queries and writes distributed across masters.
Structured the microservice with Google Guice for dependency injection, enabling modular architecture where routing algorithms, caching strategies and data access layers can be swapped independently.