Match, cost, completion
Profiling and routing exist to honor three product pillars:
- Match: infrastructure that fits the work (compute class, memory, interconnect, runtime, locality), not the largest machine in the catalog.
- Cost: optimize expected cost to completion, not the cheapest hourly offer.
- Completion: attach a fallback graph so reclaim does not end the workload.
A B200 that the work does not need is a routing failure, even if it is available and bid-able.
Two stage handoffs
Profile. Workload revision + inputs
become a versioned
execution_envelope
(Temporal activity / gRPC). Durable ack: envelope row +
outbox.
Route. Envelope + policy + market/health
snapshots + remaining budget/deadline become primary route
+ fallback graph +
bid_ceiling
+ score breakdown. Durable ack: route decision and
explanation in the same Postgres transaction.
Pilot today Profile and Route run as in-process activities rather than Temporal activities over gRPC, and both are idempotent by operation key, so a replayed step returns the stored decision instead of re-scoring. The router itself is already the pure function described here: envelope and snapshots in, decision plus score breakdown out, no provider client anywhere in the package.
Signals → envelope
Customers describe work and outcome. The profiler compiles that into something the router can score:
- Memory / model size → peak host memory, optional device memory, footprint, topology
- Runtime / throughput → expected duration, parallelism, deadline slack
- Data / resilience → locality, restartability, checkpoint cost, interruption tolerance
- Outcome → remaining
max_cost_usd, policy, continuity mode
Confidence is recorded on the envelope and scored as a routing input rather than hidden. v1 may derive the envelope from static image metadata and declared requirements. Short probe runs remain an open decision.
Continuity modes
Not every AI workload is a long checkpointable training job. The envelope carries honesty about recovery:
Training / fine-tune. Restore gen N+1 from the latest verified manifest.
reclaim → fence → restore → re-route
Idempotent batch / many inference jobs. Re-queue unfinished units via cursor.
reclaim → cursor → requeue
Short best-effort. Fail fast or retry from origin per policy.
interrupt → end or origin retry
The router must not invent checkpoint restore for work that cannot resume.
The objective function
Maximize probability of finishing on time within budget, subject to policy. Score components persisted with every decision:
fit 0.35 envelope vs offer (compute class, resources,
interconnect, locality)
cost_to_complete 0.30 expected run cost + expected recovery under
the interruption model
time_to_result 0.20 expected runtime + provision latency vs
deadline slack
recovery_value 0.10 quality of fallback graph (alternates, restore RTO)
health 0.05 supplier health facts
policy -- hard constraints; violations are rejects,
not soft scores
total = weighted sum, scaled by snapshot freshness
Those weights are constants, not per-request tuning, because a decision has to be replayable years later from its stored snapshot IDs. Two thresholds are not scores at all: supplier health below the eligibility floor rejects an offer outright, and policy violations reject. Staleness applies as a penalty that grows as a snapshot nears its TTL. Excess capacity relative to the envelope is an explicit penalty, which is how “bigger is available” loses to “right-fit finishes”.
bid_ceiling
derives from remaining budget after non-compute costs, a minimum recovery
reserve, and margin for viable fallback. Cheap capacity wins only when it
can deliver the outcome.
Pilot today The shipping ceiling implements the first three terms: remaining budget, a flat non-compute reserve, and a percentage recovery reserve held back from every bid. The explicit margin for fallback routes is specified but not yet computed, so today’s ceiling is conservative in the safe direction — it reserves recovery money before it reserves a machine.
Fallback is a graph
The decision stores a graph, not one backup provider. Branches are typed by failure class: reclaim, provisioning failure, restore incompatibility, deadline or budget risk. Each carries feasibility conditions, expected recovery time, expected cost, and confidence. When the graph is exhausted, recovery re-enters routing against fresh snapshots with the remaining envelope: progress consumed, budget spent, deadline slack left, last verified manifest. It never invents capacity.
Each branch is emitted with the facts that justified it: whether the alternate fits the envelope’s memory, whether its expected cost fits the remaining budget, and the health score it carried at decision time. A recovery can then be audited without re-deriving the world as it looked. Branch ordering is deterministic, with ties breaking on offer ID rather than map iteration.
Market price changes alone never preempt a healthy run. Explanations replay from stored snapshot IDs, and identical snapshot IDs must produce identical scores. Audit and customer trust both depend on it.
Why purity matters
If the router also reserved, every scoring bug would be a financial bug. If it called providers, latency and rate limits would poison every decision. Purity keeps side effects in the bidding service, keeps decisions append-only and explainable, and lets reclaim call the same function with a thinner envelope.
Inputs are immutable IDs and snapshots. Outputs are a plan. That is the entire interface.