Problem
Grid currently ranks eligible providers, and Praxis selects the first viable candidate. When several providers are equally suitable, a deterministic identity tie-break keeps the same provider first. The others remain available for failover but do not actively share new traffic.
Grid ranks A, B, C
-> Praxis always selects A
-> B and C remain idle until A is unavailable
Ranking answers which providers are preferred. It does not by itself provide load balancing among equally preferred providers.
This spike investigates a clean division of responsibility:
- Grid discovers providers, evaluates health and admission, applies routing and scoring policy, and publishes groups of equally eligible candidates.
- Praxis reads the accepted overlay from memory and locally selects a provider within the best viable group.
Grid, Kubernetes, the operator, ConfigMaps, overlay-sync, metrics endpoints, and remote policy services must remain outside the request hot path.
Focused demo narrative
The spike is exercised through a deliberately small provider-traffic demo:
Client
|
v
One consumer gateway
|
v
Praxis intelligent_route
|
+--> Provider Gateway A --> backend A
+--> Provider Gateway B --> backend B
`--> Provider Gateway C --> backend C
All three provider gateways advertise the same capability and are equally eligible. Grid discovers them across the three sites and publishes them in the same active selection group. The consumer gateway then applies a local picker to new, unbound requests.
The focused proof should demonstrate:
- one consumer gateway receives all measured client traffic;
- three provider gateways are discovered and accepted in one active group;
roundRobin produces a repeating A -> B -> C sequence;
- 60 measured requests produce an exact 20/20/20 split;
- every request succeeds and reports the selected provider;
- the serving overlay remains unchanged during the measured window;
- traces show the consumer-to-selected-provider path;
- request processing causes no control-plane call or overlay write.
This isolates provider selection. It intentionally excludes DNS/GTM behavior, multiple active consumer gateways, metric-derived weights, and fallback-group demonstration.
Proposed routing contract
Keep the following concepts separate:
admission
-> may this provider receive new or existing sessions?
routing policy
-> which eligibility boundary is preferred?
scoring policy
-> which asynchronous signal affects provider preference?
selection group
-> which providers may actively compete with one another?
selection policy
-> how does Praxis choose within the active group?
An initial overlay extension can use additive fields:
selection_policy: round_robin
candidates:
- cluster: provider-a
selection_group: 0
- cluster: provider-b
selection_group: 0
- cluster: provider-c
selection_group: 0
Group 0 is the best active group. Lower groups are fallback candidates and must not receive new traffic while a better group remains viable.
Implementation boundary
The Praxis-side changes for this spike should remain constrained to the praxis-proxy/ai routing filters, primarily intelligent_route and its AI-owned overlay, grouping, and picker modules.
Praxis core's generic HTTP/TCP load balancers already select endpoints within a configured cluster. They should not gain Grid-specific concepts such as provider admission, selection groups, overlay revisions, or provider affinity.
praxis-proxy/grid
-> computes provider eligibility and selection groups
-> publishes the overlay contract
praxis-proxy/ai intelligent_route
-> consumes the accepted overlay snapshot
-> applies affinity and the configured group picker
-> selects the provider cluster
Praxis core load_balancer
-> selects an endpoint within that already-selected cluster
This keeps Grid semantics in the AI extension, preserves the reusable Praxis core boundary, and limits request-path changes to the filter that already owns model/provider routing.
Picker policies
The first increment should evaluate:
deterministic: preserve the historical first-viable behavior;
roundRobin: take turns across viable candidates in the active group;
random: choose uniformly within the active group.
Round-robin state is process-local. The goal is balanced behavior at each Praxis gateway, not a globally synchronized counter across a fleet.
The request sequence is:
valid existing session binding?
|
+-- yes -> reuse the bound provider if admission still permits it
|
`-- no -> identify the best viable group
-> run its configured picker
-> create an affinity binding when affinity is enabled
Compatibility requirements
- Existing overlays without group or picker metadata retain deterministic, ordered-first behavior.
- Omitted policy must not silently change an upgraded deployment's behavior.
- New-install configuration may explicitly choose
roundRobin.
- Unknown picker values fail validation rather than silently changing routing.
- Additive overlay fields must survive operator, overlay-sync, and Praxis digest validation.
- Invalid reloads retain the last-known-good serving snapshot.
- In-flight requests continue using the immutable snapshot they started with.
- Picker state must not reset merely because unchanged overlay content is republished.
Candidate grouping questions
The spike must define a deterministic and transitive grouping rule for each routing policy.
Candidate identity must not split otherwise equivalent providers. Admission, freshness, and required policy boundaries must split groups. Metric score differences should not automatically prevent future weighted distribution inside a group.
Do not use pairwise epsilon comparisons in sorting. They can be non-transitive and make output depend on input order.
The spike should verify behavior for:
- input permutations;
- multiple capabilities;
- local and remote candidates;
- mixed admission states;
- stale candidates;
- grouped and legacy ungrouped overlays;
- duplicate or conflicting group metadata;
- overlay reloads with the same and different semantic revisions.
Admission, affinity, retry, and fallback
The design must preserve:
new_and_existing: eligible for new and already-bound sessions;
existing_only: excluded from new selection but valid for an existing binding;
excluded: never selected;
- valid affinity before picker execution;
- retry within the selected group before falling through to a lower group;
- bounded behavior when group membership changes during reload.
The focused three-provider demo proves equal active-group distribution. A separate scenario is still needed to prove draining, retry order, lower-group fallback, and recovery without weakening the focused narrative.
Observability
Each route decision should expose bounded, privacy-safe evidence:
- picker policy;
- selection group;
- selected provider, site, cluster, and stable ID;
- overlay accepted and serving revision;
- admission state;
- whether affinity was created, reused, or failed over;
- whether retry stayed within the group or fell through.
Provider and session identifiers must not become unbounded metric labels. Tracing may carry bounded decision attributes, while aggregate metrics should use controlled dimensions.
How this leads to weighting
Equal round-robin selection closes the immediate winner-take-all gap for equivalent providers. It also creates the correct boundary for a later weighted policy:
Grid control plane
-> filters ineligible providers
-> forms the active selection group
-> normalizes asynchronous capacity signals
-> publishes bounded traffic weights
Praxis data plane
-> reads the immutable local snapshot
-> preserves valid affinity
-> performs local weighted selection within the active group
Weighting must be a separate, explicit selection policy. Scores, ranks, queue depth, or KV-cache pressure must not silently become traffic percentages.
A later weighted increment must define:
traffic_weight schema and valid range;
- missing, zero, invalid, and stale weight behavior;
- normalization across providers with different capacities;
- whether weights distribute requests, new sessions, or both;
- deterministic tests using an injected random source;
- statistical runtime tolerances over sufficiently large samples;
- affinity behavior as weights change;
- removal and recovery without resetting unrelated picker state;
- protection against noisy metrics and excessive overlay churn.
Deliverables
- Grid/Praxis responsibility boundary.
- Additive overlay schema and compatibility behavior.
- Deterministic grouping rules for supported routing policies.
- Picker ownership and configuration shape.
- Immutable snapshot and picker-state lifecycle.
- Admission, affinity, retry, fallback, and recovery semantics.
- Bounded telemetry contract.
- Focused one-consumer/three-provider demo and evidence format.
- Phased implementation plan from equal selection to optional weighting.
- Risks and unresolved questions.
Out of scope for this spike
- Fleet-global round-robin coordination.
- Per-request calls to Grid or Kubernetes.
- Treating scores as implicit weights.
- Production metric-derived weighting.
- DNS, Anycast, or global entry-point balancing.
- Tenant, billing, quota, or cost-policy implementation.
- Replacing existing Grid scoring strategies.
Exit criteria
The spike is ready to conclude when it provides a compatibility-preserving design and focused runtime evidence that one Praxis consumer can distribute new traffic across three equally eligible provider gateways using only its local in-memory snapshot.
The spike must also leave a concrete, separately scoped path to weighted selection without claiming that equal round-robin distribution is weighted or metric-aware routing.
Problem
Grid currently ranks eligible providers, and Praxis selects the first viable candidate. When several providers are equally suitable, a deterministic identity tie-break keeps the same provider first. The others remain available for failover but do not actively share new traffic.
Ranking answers which providers are preferred. It does not by itself provide load balancing among equally preferred providers.
This spike investigates a clean division of responsibility:
Grid, Kubernetes, the operator, ConfigMaps, overlay-sync, metrics endpoints, and remote policy services must remain outside the request hot path.
Focused demo narrative
The spike is exercised through a deliberately small provider-traffic demo:
All three provider gateways advertise the same capability and are equally eligible. Grid discovers them across the three sites and publishes them in the same active selection group. The consumer gateway then applies a local picker to new, unbound requests.
The focused proof should demonstrate:
roundRobinproduces a repeating A -> B -> C sequence;This isolates provider selection. It intentionally excludes DNS/GTM behavior, multiple active consumer gateways, metric-derived weights, and fallback-group demonstration.
Proposed routing contract
Keep the following concepts separate:
An initial overlay extension can use additive fields:
Group
0is the best active group. Lower groups are fallback candidates and must not receive new traffic while a better group remains viable.Implementation boundary
The Praxis-side changes for this spike should remain constrained to the
praxis-proxy/airouting filters, primarilyintelligent_routeand its AI-owned overlay, grouping, and picker modules.Praxis core's generic HTTP/TCP load balancers already select endpoints within a configured cluster. They should not gain Grid-specific concepts such as provider admission, selection groups, overlay revisions, or provider affinity.
This keeps Grid semantics in the AI extension, preserves the reusable Praxis core boundary, and limits request-path changes to the filter that already owns model/provider routing.
Picker policies
The first increment should evaluate:
deterministic: preserve the historical first-viable behavior;roundRobin: take turns across viable candidates in the active group;random: choose uniformly within the active group.Round-robin state is process-local. The goal is balanced behavior at each Praxis gateway, not a globally synchronized counter across a fleet.
The request sequence is:
Compatibility requirements
roundRobin.Candidate grouping questions
The spike must define a deterministic and transitive grouping rule for each routing policy.
Candidate identity must not split otherwise equivalent providers. Admission, freshness, and required policy boundaries must split groups. Metric score differences should not automatically prevent future weighted distribution inside a group.
Do not use pairwise epsilon comparisons in sorting. They can be non-transitive and make output depend on input order.
The spike should verify behavior for:
Admission, affinity, retry, and fallback
The design must preserve:
new_and_existing: eligible for new and already-bound sessions;existing_only: excluded from new selection but valid for an existing binding;excluded: never selected;The focused three-provider demo proves equal active-group distribution. A separate scenario is still needed to prove draining, retry order, lower-group fallback, and recovery without weakening the focused narrative.
Observability
Each route decision should expose bounded, privacy-safe evidence:
Provider and session identifiers must not become unbounded metric labels. Tracing may carry bounded decision attributes, while aggregate metrics should use controlled dimensions.
How this leads to weighting
Equal round-robin selection closes the immediate winner-take-all gap for equivalent providers. It also creates the correct boundary for a later weighted policy:
Weighting must be a separate, explicit selection policy. Scores, ranks, queue depth, or KV-cache pressure must not silently become traffic percentages.
A later weighted increment must define:
traffic_weightschema and valid range;Deliverables
Out of scope for this spike
Exit criteria
The spike is ready to conclude when it provides a compatibility-preserving design and focused runtime evidence that one Praxis consumer can distribute new traffic across three equally eligible provider gateways using only its local in-memory snapshot.
The spike must also leave a concrete, separately scoped path to weighted selection without claiming that equal round-robin distribution is weighted or metric-aware routing.