“Send the nearest driver” sounds like the right dispatch rule. It minimizes pickup time for this one rider. But it ignores the driver’s position after the drop-off, other pending rider requests, and overall system efficiency. Real dispatch is an optimization problem.

Nearest Driver Is a Greedy Heuristic#

Greedy nearest-driver assignment: find the closest available driver, assign them, done. Fast to compute, easy to understand. The problem is it optimizes for one request in isolation.

Consider two riders A and B, and two drivers X and Y. Driver X is 2 minutes from A and 5 minutes from B. Driver Y is 5 minutes from A and 2 minutes from B. Greedy assigns X to A and Y to B: average wait = 2 minutes. But what if X is about to drop off near where B needs to go? Assigning X to B directly after their current trip might result in a better overall system state.

At the scale of a city with thousands of simultaneous requests, greedy assignment leaves significant efficiency on the table.

Batching Requests#

One improvement: batch ride requests in short time windows (10-30 seconds) and solve the assignment problem across all pending requests simultaneously. Match riders to drivers as a bipartite matching problem: minimize total weighted travel time across all assignments, not just the current request.

This is an NP-hard problem in its full form. Practical dispatch systems use approximations: Hungarian algorithm for smaller batches, greedy with limited lookahead for larger ones, machine-learned heuristics for tuning.

graph TD A[Rider Requests arrive continuously] --> B[Batch window: 15 seconds] B --> C[Pending requests pool] C --> D[Available drivers pool] D --> E[Assignment optimizer: minimize total pickup time] E --> F[Assign Driver X to Rider A] E --> G[Assign Driver Y to Rider B] F --> H[Notify driver and rider] G --> H style A fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style B fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style C fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style D fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style E fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style F fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style G fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style H fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff

Additional Signals Beyond Distance#

Distance is one input. Others:

Driver rating and acceptance rate: a driver with a low acceptance rate for the rider’s route shouldn’t be the top candidate even if they’re nearest.

Trip destination: some platforms allow drivers to filter by destination. A driver heading home might be assigned a trip that naturally falls along their route.

Driver earnings balancing: ensuring drivers who have been waiting longer get priority to prevent them from sitting idle while new drivers get all requests.

Pool ride matching: for shared rides, finding two riders with compatible routes and timing is a more complex matching problem.

At Salesforce#

We had a case assignment system: incoming support cases needed to be routed to support engineers. Nearest-engineer didn’t apply, but skill matching did. A case about a Salesforce API bug needed an engineer with that expertise. Simple rule-based routing (first match on skill tag) worked until case volume was high enough that some engineers were overloaded while others were idle. We added load balancing across equally-skilled engineers. Not bipartite matching, but the principle of optimizing across multiple assignments rather than greedily per-case improved throughput by 30%.

What I’m Learning#

Dispatch is an optimization problem with a real-time constraint. The right solution depends on how much latency you can tolerate in assignment: greedy runs in milliseconds, batch optimization takes seconds. The trade-off between assignment quality and assignment speed is a product decision.

Have you built assignment or scheduling systems where greedy allocation turned out to be suboptimal, and how did you improve it?