Using multiple proxy providers behind one service is not the same as putting three hostnames in a round-robin list. A customer buys a product with a proxy type, location, session rule, usage allowance, and expected behaviour. Every route must preserve that contract.

The correct request flow is:

authenticate → product eligibility → exact targeting → health filter
→ session affinity → weighted selection → upstream adapter → usage accounting

Weights come late. A weight decides among suitable routes; it cannot make an incompatible or unhealthy route suitable.

In ProxyRequest we keep eligibility, observed health, session state, and weight as separate inputs for this reason: an operator should be able to explain which one removed or selected a route.

Customer
one gateway
Eligibility
health
weights
session
Provider A · 40%Provider B · 35%Own static pool · 25%
Customers use one gateway while the routing layer selects among eligible, healthy upstream routes.

Why operators add several providers

Several providers can improve coverage, add redundancy where capabilities overlap, support quality-based routing, and give the operator more commercial control. The important unit is not provider count but a successful, supportable customer outcome for the requested product and target.

Adding suppliers also adds work: adapters, target normalization, health signals, accounting reconciliation, secret rotation, support paths, and more failure combinations. Add one because it solves a measured constraint.

Use one internal request model

Start with a provider-neutral representation of customer intent. For example:

{
"product": "residential-standard",
"country": "us",
"region": "california",
"session": "customer-session-42",
"protocol": "http-connect"
}

The exact fields depend on your product. The principle is stable: the gateway parses your public grammar once, validates it against the package, and passes a typed request to routing.

Provider adapters receive the selected route and translate that model into the upstream hostname, authentication fields, and supported targeting. They also map raw connection failures into an internal error taxonomy.

Do not pass unknown public fields through to upstream usernames. That creates an accidental provider API inside your gateway and makes validation unpredictable.

Model capabilities as data

Each route needs structured capabilities:

  • proxy type;
  • supported countries and target levels;
  • protocol support;
  • session modes and limits;
  • provider account or endpoint;
  • operational state;
  • pool membership;
  • commercial or capacity attributes used by policy.

Capabilities should be versioned and reviewable. Supplier documentation is an input, but production validation is necessary. A location listed by an upstream may have too little usable capacity for your product.

ProxyRequest upstream provider import review showing normalized configuration before activation
Reviewing normalized provider data before activation prevents raw supplier assumptions from becoming public product rules. Open full size ↗

Build the eligible set first

For each connection, start from the customer’s active package. Then construct the set of routes that satisfy every hard requirement:

  1. package permits the requested proxy type;
  2. route belongs to a pool allowed by the package;
  3. route supports the exact country and target level;
  4. requested protocol and session mode are supported;
  5. customer and package limits allow a new connection;
  6. route is enabled for production traffic.

This is intersection logic. Do not create one catalog by taking the union of all provider features and assume any chosen route can fulfil it.

If the eligible set is empty, return a clear public error. Never broaden from a requested country to “any country” just to make the request succeed. A successful connection to the wrong geography is a product failure.

Filter health before applying weights

Health is route-specific. A provider can be healthy globally and broken for one country, endpoint, protocol, or account. Track health at the smallest level you can operate without creating noisy, sparse signals.

Useful inputs include:

  • active connection failures;
  • time to connect and time to first byte;
  • authentication or account errors;
  • representative synthetic checks;
  • provider maintenance state;
  • capacity or balance warnings;
  • recent success and failure windows.

Separate upstream connectivity from target-site responses. A target returning HTTP 403 does not automatically mean the proxy provider is unavailable. The gateway should classify which layer produced the result.

Use thresholds for removal and recovery. For example, a route may leave selection after a minimum sample count and a sustained failure rate, then return only after several successful probes. The actual values depend on traffic and product. This hysteresis prevents flapping.

Apply weights to eligible, healthy routes

Weights can represent capacity, commercial preference, or a controlled traffic split. Normalize them over the routes that remain after filtering.

Suppose the configured policy is:

Provider A 40
Provider B 35
Own static pool 25

This is an illustrative example. If your actual providers are NetNut, Oxylabs, and an internally operated static pool, the same architecture can represent those inputs; the names here do not imply a partnership or endorsement.

If the static pool is unhealthy, new eligible choices normalize over 40 and 35. That produces approximately 53.3% and 46.7%, not a 25% hole. If Provider A does not support the requested region, the decision is between Provider B and the static pool only.

Weighted random choice is often enough for new sessions at moderate volume. For more deterministic distribution, consistent hashing or capacity-aware selection may fit. Whichever algorithm you use, expose configured weight, effective weight, eligible request count, and selected request count to operators.

ProxyRequest package routing interface with provider pools and weighted selection controls
Package routing joins product policy to provider pools; it is not a global provider toggle. Open full size ↗

Place sticky sessions around the routing decision

A session binding normally stores or derives the chosen route and upstream session representation for a public key. The lookup must be scoped by fields that change eligibility, such as customer, package, country, and possibly region.

For a new session:

  1. build the eligible and healthy set;
  2. choose a route using the product policy;
  3. create the binding after the connection reaches the point defined by your contract;
  4. reuse the binding until expiration while it remains valid.

For an existing session, check that its bound route is still compatible with the request. Then apply your failure policy.

There is no universal correct response to a degraded bound route. You may fail the request to preserve identity, or rebind and clearly accept that the external IP can change. The product documentation must state the behaviour. Silently claiming both permanent stickiness and automatic identity-changing failover is misleading.

Shared state is required when requests can land on several gateways unless the binding is generated deterministically. Design expiration and cleanup so session keys cannot grow forever.

Define safe failover boundaries

Failover is safest before meaningful application bytes reach the upstream. If a TCP connection cannot be established, another eligible route may be attempted within a strict retry budget.

After data has been sent, replay can be unsafe. A target may process a request and close before the response reaches the gateway. Repeating that request can create duplicate orders, messages, or state changes. A general proxy cannot infer idempotency for arbitrary customer traffic.

Use these rules:

  • never widen exact targeting during failover;
  • never change proxy type;
  • keep a small connection-attempt budget;
  • do not retry indefinitely across every provider;
  • stop when application delivery becomes uncertain;
  • return a stable customer-safe error;
  • record internal attempt evidence for operators.

The routing and failures reference documents the boundaries used by ProxyRequest.

Normalize credentials without leaking providers

Customers should authenticate to your gateway using one syntax. The gateway resolves customer, package, targeting, and session. Only the chosen adapter creates upstream authentication.

Do not embed provider account IDs in public usernames. Avoid returning upstream authentication challenges, hostnames, or raw errors. Keep upstream secrets out of customer analytics, public API payloads, browser requests, and support exports.

Internally, preserve full detail behind role-based access. Supplier abstraction is a visibility boundary, not deletion of diagnostic information.

Make accounting independent of provider reports

Different suppliers may count traffic differently or report it later. Your customer contract needs one definition. Gateway counters provide the consistent observation point because every customer byte crosses your data plane.

RequestGateway countersUsage eventLedgerBalance
Customer accounting follows the gateway and ledger. Supplier reports remain an important but separate cost-reconciliation input.

Attach usage to stable internal IDs for customer, package, credential or sub-user, route, gateway, and time bucket. The customer-facing ledger need not reveal the route, but operator analytics should use it for cost and incident analysis.

Reconcile gateway totals with supplier reports over comparable periods. A difference may indicate counting definitions, retries, protocol overhead, clock boundaries, missing events, or upstream reporting delay. Investigate it; do not quietly replace historical customer debits.

Observe decisions, not only totals

A platform with several providers needs to answer “why this route?” Operators should be able to inspect:

  • eligible and rejected routes with reason categories;
  • route health state and the signals that changed it;
  • configured versus effective weights;
  • session hits, misses, rebinding, and expiration;
  • connection attempts and failover outcome;
  • success, latency, traffic, and error category by route and target;
  • accounting event delay and reconciliation differences.
ProxyRequest provider diagnostics showing route traffic, failures, and operational status
Diagnostics connect selection policy with observed provider behaviour without exposing that detail to customers. Open full size ↗

Avoid labels with unbounded customer or session values in time-series metrics. Use logs or traces with controlled retention for high-cardinality investigation, and aggregate metrics for alerting.

Roll out a new provider safely

Do not move half of production traffic immediately after a connection test.

  1. Validate credentials and supported targets outside customer traffic.
  2. Run representative synthetic requests by protocol and country.
  3. Add the route disabled or at zero effective weight.
  4. Send a small controlled cohort or low percentage.
  5. Compare success, latency, session behaviour, and accounting.
  6. Increase gradually while watching support and cost.
  7. Keep a fast operator control to remove the route.

The reverse process applies to retirement. Reduce new selections, respect or expire session bindings according to policy, watch active connections, then remove secrets and configuration after the drain period.

Test the combinations that break in production

A multi-provider test plan should include:

  • requested country exists on only one route;
  • highest-weight route is unhealthy;
  • all routes are unhealthy;
  • provider authentication expires;
  • an existing sticky route degrades;
  • two gateway nodes receive the same session;
  • quota ends during concurrent streams;
  • accounting sink is temporarily unavailable;
  • upstream connects, receives bytes, then closes;
  • provider returns an error containing its own hostname;
  • a route recovers and re-enters without flapping;
  • configuration changes while connections remain open.

Check both behaviour and evidence. A test passes only when the customer receives the documented result and the operator can understand why it happened.

Architecture checklist

Before selling one product across several providers, confirm:

  • Providers are behind adapters and private credentials.
  • Eligibility and health are evaluated before weights.
  • Sessions are shared or deterministic and failover preserves the product.
  • Customer usage follows gateway counters into an auditable ledger.
  • Operators can explain selection and failures without leaking suppliers.

Multi-provider routing is valuable because it lets supply change behind a stable product. That only works when the product contract is stronger than the provider integration.

For the complete operating layer around routing, read what proxy reseller software actually needs. If you are estimating the engineering effort, continue to build versus buy a proxy platform.