Multi-Source Fulfilment Routing 2026: Order Routing Across Suppliers
Production B2B digital-goods fulfilment cannot depend on a single supplier. An exclusive supplier is a single point of failure: one outage and every order fails. The correct architectural pattern is multi-source routing with automatic selection of the best option per request.
This guide covers routing logic in your own system. When FoxReload is one of your suppliers, you call POST /api/orders after your routing layer selects it. Retrieve results by polling GET /api/orders/{order_id} — FoxReload does not push webhook callbacks, so design your routing layer to poll for completion.
1. Latency-weighted routing
The simplest variant is to pick the supplier with the lowest p95 delivery latency. Store historical metrics in a Redis sliding window:
type SupplierStats = { p95Ms: number; failureRate: number; stock: number };
async function pickSupplier(productId: string): Promise<string> {
const candidates = await getSuppliersForProduct(productId);
const stats = await Promise.all(
candidates.map(s => redis.hgetall(`sup:${s.id}:stats`))
);
const scored = candidates.map((s, i) => ({
id: s.id,
score: 1 / (parseFloat(stats[i].p95Ms) + 1),
}));
return scored.sort((a, b) => b.score - a.score)[0].id;
}
This covers 80% of scenarios. Latency metrics refresh every 30 seconds from real order completion times recorded in your tracking layer.
2. Stock-aware routing
If a supplier's inventory is below buffer (e.g., <50 codes for a popular product), avoid using it as primary even with good latency. The stock buffer prevents the race condition "4 concurrent orders for 3 codes".
function isViableSupplier(s: SupplierStats, qty: number): boolean {
const buffer = Math.max(50, qty * 3); // 3x safety margin
return s.stock >= buffer && s.failureRate < 0.05;
}
For FoxReload specifically, check GET /api/products/{id_or_slug} to verify the product is still listed and active before routing orders there.
3. Cost-optimised routing
If SLA allows (e.g., fulfilment within 5 minutes is normal for B2B), optimise on wholesale cost. Formula:
score = (1 / wholesale_cost) * sla_multiplier
where sla_multiplier = 1 if p95 < target else 0
This gives a hard SLA guarantee plus minimum cost. At scale (>10k orders/day) it saves 1.5–3% on marginal cost.
4. Failover and circuit breaker
Health-check pattern:
| Signal | Threshold | Action |
|---|---|---|
| 5xx rate over 5 min | >5% | Mark DEGRADED |
| Timeout rate | >2% | Mark DEGRADED |
| Heartbeat fail | 3 in a row | Mark DOWN |
| Recovery | 5 successful | Mark HEALTHY |
Circuit breaker pattern (Polly/resilience4j-style):
import CircuitBreaker from 'opossum';
const breaker = new CircuitBreaker(callSupplier, {
timeout: 8000,
errorThresholdPercentage: 50,
resetTimeout: 120000, // 2 min
});
breaker.fallback(() => fallbackSupplier());
In open state 100% of traffic moves to fallback — 2-minute cooldown, then a half-open canary check, then recovery.
5. Polling after order placement
When FoxReload is the selected supplier, after calling POST /api/orders your routing layer must poll for completion:
async function placeAndWait(items: OrderItem[], apiKey: string): Promise<string[]> {
const res = await fetch('https://public-api.foxreload.com/api/orders', {
method: 'POST',
headers: { 'X-API-Key': apiKey, 'Content-Type': 'application/json' },
body: JSON.stringify({ items }),
});
const order = await res.json();
// Poll until terminal state
let delay = 5_000;
while (true) {
await sleep(delay);
const statusRes = await fetch(
`https://public-api.foxreload.com/api/orders/${order.id}`,
{ headers: { 'X-API-Key': apiKey } },
);
const latest = await statusRes.json();
if (latest.status === 'completed') {
return latest.items.flatMap((i: any) => i.externalData ?? []);
}
if (['cancelled', 'failed'].includes(latest.status)) {
throw new Error(`Order ${order.id} ended with status ${latest.status}`);
}
delay = Math.min(delay * 1.5, 30_000);
}
}
CTA
FoxReload provides a single REST API with a large product catalog. Get access and plug it into your multi-source routing layer.
