Skip to content

fix: implement quota-aware backend failover with Envoy host allowlist routing - #2953

Open
AyushSawant18588 wants to merge 8 commits into
theagentrouter:mainfrom
AyushSawant18588:quota-policy-fix
Open

AyushSawant18588 wants to merge 8 commits into
theagentrouter:mainfrom
AyushSawant18588:quota-policy-fix

Conversation

@AyushSawant18588

@AyushSawant18588 AyushSawant18588 commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Description
This PR implements quota-aware backend failover for AI Gateway routes by connecting QuotaPolicy enforcement across AI Gateway, the rate limit service, and Envoy.
The Agent Router now:

  • Identifies quota enforcement at (backend, model) granularity.
  • Stamps routing metadata only on endpoints with an enforceable quota.
  • Wraps quota-backed clusters with Envoy's host_allowlist load-balancing policy.
  • Preserves existing load-balancing behavior through the wrapped child policy.
  • Avoids wrapping clusters when no quota endpoint was stamped.
  • Adds unit-test coverage for quota matching, endpoint stamping, backend-group mapping, zero-weight backends, and host-allowlist wrapping.

These changes integrate with the related upstream component work:

  • Envoy Ratelimit PR : adds grouped quota enforcement and passedBackends response dynamic metadata. AI Gateway consumes this metadata to determine which (backend, model) quota groups remain available.
  • Envoy PR #47805: adds the host_allowlist load-balancing policy. Agent Router configures this policy on quota-backed clusters so Envoy can exclude backends that are no longer available for the request.

The changes also add multi-backend quota failover manifests and update the e2e RLS image to the upstream build containing the required quota metadata behavior.

Envoy Ratelimit PR: envoyproxy/ratelimit#1243, envoyproxy/ratelimit#1295
Envoy PR #47805: envoyproxy/envoy#47805

@AyushSawant18588
AyushSawant18588 requested a review from a team as a code owner October 31, 2026 15:45
@netlify

netlify Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for theagentrouter canceled.

Name Link
🔨 Latest commit 94eec1b
🔍 Latest deploy log https://app.netlify.com/projects/theagentrouter/deploys/6af187fd7feaaa7ae174c168

@codecov

codecov Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

…error

Signed-off-by: Ayush Sawant <ayush.sawant@nutanix.com>
Signed-off-by: Ayush Sawant <ayush.sawant@nutanix.com>
Signed-off-by: Ayush Sawant <ayush.sawant@nutanix.com>
Signed-off-by: Ayush Sawant <ayush.sawant@nutanix.com>
continue
}
var group *endpointv3.LocalityLbEndpoints
if cluster.LoadAssignment != nil && lbEndpointIndex < len(cluster.LoadAssignment.Endpoints) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use GetLoadAssignment fn

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

made the change

continue
}
namespace := backendRef.GetNamespace(info.namespace)
for _, endpoint := range group.LbEndpoints {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use GetLbEndpoints fn

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

made the change

// resolveClusterRule parses a cluster name and fetches the corresponding AIGatewayRoute rule.
// Cluster name format: "httproute/{namespace}/{routeName}/rule/{ruleIndex}"
func (s *Server) resolveClusterRule(ctx context.Context, clusterName string) *clusterRouteInfo {
parts := strings.Split(clusterName, "/")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this cluster parsing is incomplete, refer to parseAIGatewayClusterName from post_translate_modify.go

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be taken up in next PR

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, will take up handling of other cluster types in a separate PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants