TypeScript engine for optimally assigning delivery orders to riders using multi-stage optimization, intelligent batching, and dynamic surge handling.
This engine solves the assignment problem in last-mile delivery: given a set of orders and available riders, assign orders to riders to minimize costs while respecting hard constraints (vehicle capacity, time windows, geography) and maximizing business objectives (SLA compliance, efficiency, fairness).
It's designed for high-volume delivery operations where orders arrive continuously and demand fluctuates unpredictably. The algorithm runs in near real-time (cycles every 15-60 seconds) and adapts to surge conditions automatically.
- Multi-objective optimization: Balances 6 competing goals (time, SLA risk, distance, route disruption, workload fairness, zone familiarity)
- Constraint satisfaction: Respects vehicle capacity, shift times, SLA deadlines, geographic boundaries, and special requirements
- Scalability: Handles 100-1000+ orders per cycle with automatic fallback to approximation algorithms
- Surge adaptation: Detects demand-supply imbalances and dynamically adjusts batch sizes and search radii
- Re-assignment: Handles rider availability changes, ETA updates, and high-priority order arrivals
- Batching: Optimizes delivery routes with Cheapest Insertion Heuristic + local search (2-opt)
import { AssignmentEngine, MARKET_CONFIGS } from '@project/allot';
// 1. Create config for your use case
const config = MARKET_CONFIGS.bangalore_default();
// 2. Create engine
const engine = new AssignmentEngine(config);
// 3. Load current state
engine.updateState(ordersMap, ridersMap);
// 4. Assign orders
const result = engine.executeCycle();
// 5. Read results
console.log(`Assigned: ${result.successCount} orders`);
result.decisions.forEach(({ orderId, riderId, sequenceIndex }) => {
console.log(`${orderId} -> ${riderId} (position ${sequenceIndex})`);
});// High SLA priority (food delivery, time-sensitive)
const config = MARKET_CONFIGS.high_sla_priority();
// Cost optimization (e-commerce, bulk orders)
const config = MARKET_CONFIGS.cost_optimized();
// Surge handling (peak hours)
const config = MARKET_CONFIGS.surge_optimized();
// Default balanced
const config = MARKET_CONFIGS.bangalore_default();const config = new ConfigurationBuilder()
.setWeights({
w1_time: 0.25, // Pickup delay
w2_slaRisk: 0.50, // SLA breach risk
w3_distance: 0.10, // Travel distance
w4_batchDisruption: 0.10, // Route disruption
w5_workload: 0.05, // Load balance
w6_affinity: 0.00, // Zone familiarity
})
.setMaxBatchSizes({ bike: 2, car: 3, van: 5 })
.setSLARiskScale(8)
.build();
const engine = new AssignmentEngine(config);See Configuration Guide for all options.
- One-time assignment: Assign a batch of orders to available riders in a single cycle
- Continuous optimization: Re-run cycles every 15-60 seconds to adapt as new orders arrive and riders complete deliveries
- Surge-responsive assignment: Automatically adjust strategy when demand spikes (expand batches, increase search radius, relax SLA constraints)
- Re-assignment: Reassign orders when riders go offline, ETAs change, or high-priority orders arrive
- Zone-based assignment: Optimize within geographic regions for locality and zone familiarity
The engine minimizes a weighted cost function across:
| Objective | Purpose | Example |
|---|---|---|
| Pickup Time (w1) | Minimize wait at pickup location | Reduce cold chain risk, pickup unavailability |
| SLA Risk (w2) | Minimize probability of deadline breach | Premium customer satisfaction, penalties |
| Travel Distance (w3) | Minimize total distance traveled | Reduce fuel, emissions, delivery time |
| Route Disruption (w4) | Minimize impact on existing routes | Keep batches cohesive, reduce re-planning |
| Workload Balance (w5) | Balance utilization across riders | Fair distribution, avoid overload |
| Zone Affinity (w6) | Prefer familiar zones for riders | Faster delivery, higher success rates |
Challenge: Minimize late deliveries for perishable food while maintaining reasonable batch sizes to preserve freshness.
Solution:
const config = new ConfigurationBuilder()
.setWeights({
w1_time: 0.20,
w2_slaRisk: 0.50, // Heavy SLA focus
w3_distance: 0.15,
w4_batchDisruption: 0.10,
w5_workload: 0.05,
w6_affinity: 0.00,
})
.setMaxBatchSizes({ bike: 2, car: 3, van: 5 })
.setSLARiskScale(8) // Steep penalty
.build();Outcome: 98% on-time delivery, small batches preserve food quality
Challenge: Minimize cost and distance for large-scale bulk orders with flexible time windows.
Solution:
const config = new ConfigurationBuilder()
.setWeights({
w1_time: 0.20,
w2_slaRisk: 0.20, // Softer SLA (longer windows)
w3_distance: 0.35, // Minimize km
w4_batchDisruption: 0.15,
w5_workload: 0.08,
w6_affinity: 0.02,
})
.setMaxBatchSizes({ bike: 5, car: 12, van: 30 })
.build();Outcome: 40-50% cost reduction through larger batches and route optimization
Challenge: Handle sudden 2-3x increase in order volume without SLA degradation.
Solution:
const config = new ConfigurationBuilder()
.setSurgeRatios(1.1, 1.3, 1.8)
.setMaxBatchSizes({ bike: 4, car: 7, van: 12 })
.build();The engine automatically:
- Detects surge (demand/supply ratio > 1.2)
- Increases batch sizes by 1-2 orders per type
- Expands search radius from 5km → 10km → 20km
- Prioritizes SLA-critical orders
Outcome: 80%+ assignment rate even at 3x load
Challenge: Urgent medical deliveries must be completed within 1-2 hours; failures are not acceptable.
Solution:
const config = new ConfigurationBuilder()
.setWeights({
w1_time: 0.10,
w2_slaRisk: 0.70, // Extreme SLA focus
w3_distance: 0.10,
w4_batchDisruption: 0.05,
w5_workload: 0.05,
w6_affinity: 0.00,
})
.setMaxBatchSizes({ bike: 1, car: 2, van: 3 }) // No batching
.setSLARiskScale(5) // Very steep
.setCycleInterval(10) // Faster cycles
.build();Outcome: 99.8%+ SLA compliance, no failed critical deliveries
Challenge: Route different order types (food, parcels, pharmacy) with different SLA/cost priorities simultaneously.
Solution:
// Route orders by type
const foodEngine = new AssignmentEngine(MARKET_CONFIGS.high_sla_priority());
const parcelEngine = new AssignmentEngine(MARKET_CONFIGS.cost_optimized());
const medicineEngine = new AssignmentEngine(createCriticalConfig());
// Assign each type separately, avoiding conflicts
foodEngine.updateState(foodOrders, availableRiders);
parcelEngine.updateState(parcelOrders, availableRiders);
medicineEngine.updateState(medicineOrders, availableRiders);
// Combine results
const allAssignments = [
...foodEngine.executeCycle().decisions,
...parcelEngine.executeCycle().decisions,
...medicineEngine.executeCycle().decisions,
];Outcome: 95%+ overall on-time rate with cost-optimal parcel routing
- Getting Started Guide: Step-by-step tutorial, data structures, common patterns
- Configuration Reference: Complete list of all configuration options
- Algorithms Deep Dive: Mathematical formulas, scoring logic, optimization techniques
- API & Architecture Guide: Full API reference, class structure, internal components
Run executable examples demonstrating real-world scenarios:
npx ts-node examples/food-delivery.ts
npx ts-node examples/last-mile.ts
npx ts-node examples/surge-handling.tsSee Examples Guide for detailed explanations.
All functionality is tested with 180+ unit and integration tests:
pnpm test
pnpm test --coverage// Initialize
const engine = new AssignmentEngine(config);
// Update orders and riders
engine.updateState(orders, riders);
// Run assignment cycle
const result = engine.executeCycle();
// Inspect state
const state = engine.getState();
console.log(state.surgeState.level);interface AssignmentCycleResult {
decisions: AssignmentDecision[]; // Assignments made
successCount: number; // Orders assigned
failureCount: number; // Orders failed
metrics: {
avgCost: number; // Cost per assignment
totalSlaSlackMinutes: number; // Minutes until SLA breach
riderUtilization: Record<string, number>;
};
}Contributions are welcome! Please see CONTRIBUTING.md for guidelines on:
- Code style and standards
- Testing requirements
- Submission process
- Architecture guidelines
- Algorithms Deep Dive - How the scoring and optimization work
- Configuration Reference - Complete customization guide
- Getting Started - Detailed tutorial with examples
- Test Coverage - 180+ tests showing usage patterns
For questions, issues, or feature requests:
- Check the Getting Started Guide
- Review Configuration Reference
- Look at Examples
- Open an issue on GitHub