/reference/http-client.llms.txt
HTTP Client & Proxy Pools
Every upstream you configure gets its own persistent, pre-warmed connection — 256 idle connections per host, unlimited active, and TCP keepalives that kill wedged flows in ~45 seconds instead of two hours. Add a named proxy pool and eRPC rotates requests round-robin across any number of SOCKS5 or HTTP proxies on every call — useful for IP diversity, egress compliance, or budget isolation.
What you get:
- One connection pool per upstream, created once and reused forever
- Transparent gzip in both directions, pooled to avoid allocation pressure
- SOCKS5 / HTTP proxy rotation via lock-free round-robin
- OTel
traceparentinjected on every outbound call automatically
Quick taste
Illustrative, not a tuned production config — enable gzip and route one upstream through a proxy pool:
# route this upstream's requests through the named proxy poolproxyPools: - id: my-proxies urls: - socks5://proxy1.example.com:1080 - http://proxy2.example.com:3128
projects: - id: main upstreams: - endpoint: https://mainnet.infura.io/v3/KEY jsonRpc: # reference the pool by id — eRPC rotates requests round-robin proxyPool: my-proxies # compress request bodies; responses are always decompressed enableGzip: trueAgent reference
Copy one of these prompts into your AI agent session (Claude Code, Cursor, …) — each one points the agent at this page's machine-readable reference so it can do the work correctly:
Prompt Example #1: configure proxy rotation for IP-diverse egress
I want to route eRPC upstream requests through a pool of SOCKS5 proxies to spread the source IP fingerprint across providers that rate-limit by IP. Set up a proxyPool in my config and wire it to the right upstreams. Work with my existing eRPC config. Read the full reference first: https://docs.erpc.cloud/reference/http-client.llms.txt
Prompt Example #2: enable batch aggregation for a high-QPS indexer
My indexer fires hundreds of eth_getTransactionReceipt calls per second and I want to coalesce them into batches to reduce HTTP round-trips. Enable supportsBatch with sane batchMaxSize and batchMaxWait values on my upstream(s) — and warn me about the footguns (batchMaxSize: 0, batchMaxWait: 0, forwarded-header loss). Work with my existing eRPC config. Reference: https://docs.erpc.cloud/reference/http-client.llms.txt
Prompt Example #3: debug unexpected upstream errors or timeout behavior
My eRPC instance is returning ErrUpstreamMalformedResponse and occasional ErrEndpointRequestTimeout errors I don't understand. Explain the HTTP client error classification table, check my eRPC config for misconfigured batchMaxSize/batchMaxWait or missing timeout settings, and suggest what to look for in the upstream request logs. Reference: https://docs.erpc.cloud/reference/http-client.llms.txt
Prompt Example #4: apply shared JSON-RPC client defaults across all upstreams
I want gzip compression and batch settings applied to every upstream without repeating config. Show me how to use upstreamDefaults.jsonRpc in my eRPC config, and explain the all-or-nothing inheritance footgun so I don't accidentally drop settings on upstreams that already have a jsonRpc block. Reference: https://docs.erpc.cloud/reference/http-client.llms.txt
HTTP Client & Proxy Pools — full agent referenceExpand for every option, default, and edge case — or copy this entire section into your AI assistant.
How it works
Client lifecycle. ClientRegistry.GetOrCreateClient (clients/registry.go:L47-L53) uses a sync.Map keyed on common.UniqueUpstreamKey(ups). The first call creates the client; all subsequent calls for the same upstream return the cached instance. Creation is guarded by sync.Once. The registry also holds a reference to a ProxyPoolRegistry, resolving the proxy pool by ID at creation time.
Scheme dispatch. CreateClient inspects parsedUrl.Scheme. http/https → NewGenericHttpJsonRpcClient. grpc/grpc+bds → GrpcBdsClient. ws/wss → error (not yet implemented). Any other scheme → error (clients/registry.go:L84-L117).
Transport construction. Each GenericHttpJsonRpcClient owns its own http.Transport:
DialContextviautil.DefaultOutboundDialer():net.Dialer{Timeout: 10s, KeepAlive: 15s}. The 15-second probe interval means wedged TCP flows die in ~45 seconds (3 probes), versus the Linux kernel default of ~7200 seconds.MaxConnsPerHost: 0(unlimited) is intentional. The prior default of 2 capped throughput at ~5 req/s per host with 400ms upstream latency; removing the cap makes the OS TCP stack the only limit. Validated inclients/http_connection_test.go.- Overall
http.Client.Timeoutis 60 seconds (includes body read).
Request preparation. Every outbound call gets: Content-Type: application/json, Accept-Encoding: gzip, User-Agent: erpc (<version>/<sha>; Project/<projectId>). Custom headers from jsonRpc.headers are applied via Header.Set after those defaults — they can override Content-Type or User-Agent. OTel W3C traceparent/baggage injection runs last and cannot be overridden.
Gzip. The client always sends Accept-Encoding: gzip and decompresses any gzip response regardless of enableGzip. When enableGzip: true, request bodies are also compressed using pooled gzip.Writer instances. Both reader and writer are pooled via sync.Pool to avoid allocation pressure.
Forwarded headers. Inbound headers matching project.forwardHeaders patterns are forwarded to the upstream only on single (non-batch) requests — the batch path aggregates multiple caller contexts into one outbound call.
Batch aggregation. When supportsBatch: true, SendRequest queues calls into a map keyed by JSON-RPC ID. A time.AfterFunc(batchMaxWait, ...) fires processBatch when the timer elapses; the batch also fires immediately when the queue reaches batchMaxSize. The batch context deadline is set to the earliest deadline among queued requests. Responses are matched back to callers by JSON-RPC id. A single-object response (e.g. a rate-limit error with "id": null) is broadcast to all queued callers. Duplicate IDs within a window flush the pending batch immediately and start fresh.
Proxy pool. createProxyPool builds one http.Client per proxy URL, with identical transport settings to the direct path plus Proxy: http.ProxyURL(proxyURL). On every outbound call, GetClient() selects the next client via atomic.AddUint64(&counter, 1) % len(clients) — a lock-free round-robin. Counter wraps naturally at uint64 overflow; it is never reset. On error (empty pool), the client falls back to the direct transport and logs an error.
Proxy URL validation uses a case-insensitive prefix check, not url.Parse: only http://, https://, and socks5:// are accepted. socks4://, ws://, and any other scheme fail at startup.
Shutdown. A goroutine watches appCtx.Done() and drains the in-flight batch. Already-canceled contexts in the queue are dropped silently.
Test mode. When util.IsTest() is true, the client substitutes http.DefaultTransport to allow gock mock interceptors.
Config schema
proxyPools[] — top-level array (common/config.go:L48 (opens in a new tab))
| Field | Type | Default | Behavior / footguns |
|---|---|---|---|
proxyPools[].id | string | required | Pool name referenced by upstream.jsonRpc.proxyPool. Must be unique. Non-existent ID referenced by an upstream fails at startup. Source: clients/proxy_pool_registry.go:L58 |
proxyPools[].urls | []string | required, min 1 | Proxy URLs. Empty list fails with "proxyPool.*.urls is required...". Each URL is lowercased then checked via strings.HasPrefix against "http://", "https://", or "socks5://" — not url.Parse. socks4:// and all other schemes fail validation and prevent eRPC from starting. Each valid URL gets its own http.Client with identical transport settings. Source: common/validation.go:L230-247 |
upstreams[].jsonRpc.* (also upstreamDefaults.jsonRpc.*)
All fields are optional. JsonRpcUpstreamConfig.SetDefaults() is a no-op; pointer-zero fields retain Go zero values. Important: when an upstream has no jsonRpc: block at all, the full upstreamDefaults.jsonRpc struct is shallow-copied. But if any jsonRpc: block is present (even jsonRpc: {}), field-level defaults are not merged — inheritance is all-or-nothing.
| Field | Type | Default | Behavior / footguns |
|---|---|---|---|
supportsBatch | *bool | nil (false) | Enables batch aggregation. nil or false → every request is a direct single HTTP call. Source: clients/http_json_rpc_client.go:L132-137 |
batchMaxSize | int | 0 | Max requests per batch; batch fires immediately when reached. Footgun: 0 with supportsBatch: true evaluates as 1 >= 0 (always true) and fires on the first queued request, disabling coalescing. Use ≥ 2. Source: clients/http_json_rpc_client.go:L294-300 |
batchMaxWait | Duration | zero (instant) | How long to wait before flushing. time.AfterFunc(0, fn) schedules immediately. Footgun: zero disables coalescing. Set "10ms" or similar for meaningful batching. Source: clients/http_json_rpc_client.go:L289-291 |
enableGzip | *bool | nil (false) | Compresses outbound request body with a pooled gzip.Writer; adds Content-Encoding: gzip. Decompression of responses is always active regardless. Independent of server.enableGzip. Source: clients/http_json_rpc_client.go:L139-142 |
headers | map[string]string | nil | Static headers on every outbound request. Applied via Header.Set (overwrites). Runs after built-in defaults but before OTel injection — traceparent cannot be overridden. Source: clients/http_json_rpc_client.go:L838-847 |
proxyPool | string | "" (direct) | ID of a proxyPools[] entry. Resolved at client creation; non-existent ID fails at startup. Empty string → direct transport. Source: clients/proxy_pool_registry.go:L107-111 |
Fixed transport parameters (not user-configurable)
Same values apply to both direct and proxy transports (source: clients/http_json_rpc_client.go:L109-128, clients/proxy_pool_registry.go:L82-98).
| Parameter | Value | Purpose |
|---|---|---|
DialContext | net.Dialer{Timeout: 10s, KeepAlive: 15s} | Dial timeout + TCP keepalive probe interval |
MaxIdleConns | 1024 | Global idle connection pool |
MaxIdleConnsPerHost | 256 | Per-host idle connection limit |
MaxConnsPerHost | 0 (unlimited) | Prevents connection queuing under high RPS / high latency |
IdleConnTimeout | 90s | Idle connection closure |
ResponseHeaderTimeout | 30s | Time to first response header byte |
TLSHandshakeTimeout | 10s | TLS negotiation deadline |
ExpectContinueTimeout | 1s | 100-continue wait |
http.Client.Timeout | 60s | End-to-end timeout including body read |
Worked examples
1. SOCKS5 proxy rotation for IP-diverse egress. Multiple providers rate-limit by source IP. Routing requests through a pool of residential or datacenter proxies distributes the source IP fingerprint and avoids per-IP throttles:
proxyPools: - id: egress-proxies urls: - socks5://proxy1.example.com:1080 - socks5://proxy2.example.com:1080 - socks5://proxy3.example.com:1080
projects: - id: main upstreams: - endpoint: https://mainnet.infura.io/v3/KEY jsonRpc: proxyPool: egress-proxies2. Batch aggregation for high-QPS read workloads. An indexer fires hundreds of eth_getTransactionReceipt calls per second. Batching coalesces them into fewer HTTP round-trips, reducing latency and upstream connection overhead. Set batchMaxSize and batchMaxWait together so batches fill before the timer fires:
upstreams: - endpoint: https://mainnet.infura.io/v3/KEY jsonRpc: supportsBatch: true batchMaxSize: 50 batchMaxWait: 10ms3. Gzip + custom API-key header. Enable request compression and inject a bearer token on every upstream call. The token is sent via Header.Set after the built-in defaults, so it cannot accidentally stomp traceparent:
upstreams: - endpoint: https://rpc.example.com jsonRpc: enableGzip: true headers: Authorization: "Bearer my-secret-key"4. Shared defaults across all upstreams. Use upstreamDefaults.jsonRpc to apply batch + gzip to every upstream without repeating config. Note: any upstream that defines its own jsonRpc: block (even empty) does not inherit from upstreamDefaults.jsonRpc:
projects: - id: main upstreamDefaults: jsonRpc: supportsBatch: true batchMaxSize: 20 batchMaxWait: 5ms enableGzip: true upstreams: - endpoint: https://rpc-a.example.com - endpoint: https://rpc-b.example.comRequest/response behavior
Outbound HTTP request shape (single):
POST <upstream endpoint URL>
Content-Type: application/json
Accept-Encoding: gzip
User-Agent: erpc (<ErpcVersion>/<ErpcCommitSha>; Project/<projectId>)
[Content-Encoding: gzip] — only when enableGzip=true
[<custom headers>] — from jsonRpc.headers, via Header.Set
[traceparent: ...] — OTel W3C trace context (injected last)
[baggage: ...]
[<forwarded headers>] — only on single requests, from project.forwardHeaders
Body: {"jsonrpc":"2.0","method":"...","params":[...],"id":...}Outbound HTTP request shape (batch):
Same headers except forwarded headers (absent). Body is a JSON array of JsonRpcRequest objects.
Batch response matching:
- Array response: each element's
idis looked up in the queued request map; matched response returned to caller. Unmatched IDs produce"no response received for request ID: N"(logged as ERROR with full body). - Single-object response: broadcast to ALL callers. Handles rate-limit errors returned as
{"error":{...},"id":null}for the whole batch. - Non-JSON response: parsed as JSON-RPC error and broadcast; if that fails, all callers receive the parse error.
Error type mapping:
| Condition | Error type |
|---|---|
| Transport-level failure | ErrEndpointTransportFailure |
context.DeadlineExceeded / ErrDynamicTimeoutExceeded | ErrEndpointRequestTimeout |
context.Canceled | ErrEndpointRequestCanceled |
JSON-RPC error message containing "context canceled" | ErrEndpointRequestCanceled (reclassified) |
JSON-RPC error message containing "context deadline exceeded" | ErrEndpointRequestTimeout (reclassified) |
| Unparseable JSON body | ErrJsonRpcExceptionInternal/ParseException |
Upstream error field in response | ErrJsonRpcExceptionInternal/ServerSideException (after extractor) |
| Batch response body is not array or object | ErrUpstreamMalformedResponse (retryable) |
Pre-request creation error (e.g. failed to build http.Request) | ErrHttp (BaseError) |
Behavioral invariants:
ClientRegistry.GetOrCreateClientusessync.Map+sync.Once; all callers for the same upstream share exactly one client instance. [clients/registry.go:L47-125]- OTel
traceparent+baggageare injected on every request, including retried and batched calls. [clients/http_json_rpc_client.go:L845-847] - Both single and batch paths decompress gzip responses whenever
Content-Encoding: gzipis present. [clients/http_json_rpc_client.go:L852-867] - At shutdown,
appCtx.Done()triggersprocessBatch(true)to drain in-flight batches; already-canceled contexts in the queue are dropped silently. [clients/http_json_rpc_client.go:L211-217] - Pre-queue cancellation check.
queueRequestinspectsreq.ctx.Err()before inserting into the batch map. Already-canceled requests are immediately failed withErrEndpointRequestTimeoutorErrEndpointRequestCanceledwithout touching the network. [clients/http_json_rpc_client.go:L241-253] - Post-queue pre-send cancellation drop. Inside
processBatch, a pass over the queued requests drops any entry whosectx.Err()is non-nil before the HTTP call is made. [clients/http_json_rpc_client.go:L349-361]
Best practices
- Set both
batchMaxSizeandbatchMaxWaittogether. Either alone produces degenerate behavior:batchMaxSize: 0fires on every first request (size check1 >= 0);batchMaxWait: 0fires before other requests can join. Use at minimumbatchMaxSize: 10+batchMaxWait: "10ms"for meaningful coalescing. - Do not use
supportsBatch: truefor upstreams receiving forwardedAuthorizationheaders. Forwarded headers are applied only on single requests; batch requests share one outbound call and carry no per-caller headers. - Prefer
upstreamDefaults.jsonRpcto avoid repetition — but know it is all-or-nothing. Any upstream with an explicitjsonRpc:block (evenjsonRpc: {}) does not inherit defaults field-by-field. Either use defaults everywhere or configure each upstream fully. enableGzip: trueis worth enabling for most RPC endpoints. JSON-RPC responses (especiallyeth_getLogs,debug_traceTransaction) compress well. The reader and writer are pooled, so CPU overhead is minimal.- Add at least 3 proxy URLs per pool. With a single-URL pool the round-robin is meaningless (always index 0); with 2 the distribution is uneven under any non-even request count. Three or more gives meaningful rotation.
- Proxy scheme validation is strict at startup. Test proxy URLs locally before deploying —
socks4://and other schemes will prevent eRPC from starting with no graceful fallback. - There is no per-upstream TLS configuration. Custom CA bundles, client certs, and
InsecureSkipVerifyare not supported. If an upstream requires mutual TLS or a private CA, the connection must be proxied through a sidecar or gateway that handles TLS termination.
Edge cases & gotchas
batchMaxSize: 0withsupportsBatch: truefires instantly. The request is added to the queue before the size check (len >= batchMaxSize), so the check evaluates as1 >= 0(always true). UsebatchMaxSize: 2or higher. Source:clients/http_json_rpc_client.go:L294batchMaxWait: 0(default) fires instantly.time.AfterFunc(0, fn)schedules in a new goroutine immediately. Set a non-zero duration to enable coalescing. Source:clients/http_json_rpc_client.go:L291- Duplicate JSON-RPC IDs within a batch window flush the pending batch. The in-flight batch fires immediately and the duplicate starts a fresh batch. Clients that reuse IDs will see reduced batch efficiency. Source:
clients/http_json_rpc_client.go:L255-261 - Custom
headersoverwrite built-in defaults.Header.Setreplaces any existing value. Aheaders: {Content-Type: text/plain}will overwriteapplication/json. OTel headers are injected after and cannot be overridden. Source:clients/http_json_rpc_client.go:L838-847 - Forwarded headers are absent on batch requests. Callers relying on
Authorizationor custom headers forwarded to upstreams must not enablesupportsBatchfor those upstreams. Source:clients/http_json_rpc_client.go:L736-742 upstreamDefaults.jsonRpcis all-or-nothing. If an upstream has anyjsonRpc:block (even emptyjsonRpc: {}), defaults are not merged field-by-field. Source:common/defaults.go:L1550-1558- Proxy URL scheme check is a
strings.HasPrefixafterstrings.ToLower, noturl.Parse.socks4://,ws://,ftp://, and other schemes fail at startup regardless of syntactic validity. Onlyhttp://,https://,socks5://are accepted. Source:common/validation.go:L238-244 - Empty proxy pool falls back to direct transport. If
GetClientreturns an error (pool created with zero URLs), the client logs an error and uses the direct transport. Startup validation should prevent this in production. Source:clients/proxy_pool_registry.go:L69-71 MaxConnsPerHost: 0is deliberate. Go's prior default of 2 capped throughput at ~5 req/s per host with 400ms latency. Unlimited removes the queue; the OS TCP stack becomes the only cap. Source:clients/http_connection_test.go:L141-414- No per-upstream TLS configuration. Custom CA bundles, client certificates, and
InsecureSkipVerifyare not supported for HTTP upstreams. Go uses the system CA bundle. Source:clients/http_json_rpc_client.go:L109-118 - HTTP/2 is not explicitly enabled.
ForceAttemptHTTP2is not set. HTTP/2 may negotiate via ALPN onhttps://upstreams that offer it, but this is unverified. Proxy transports are HTTP/1.1 tunnels. Source:clients/http_json_rpc_client.go:L109-118 - Batch single-object response broadcasts to all callers. When an upstream returns
{"jsonrpc":"2.0","error":{...},"id":null}, every pending request in the batch receives the same response — intended for upstream-wide rate-limit errors. Source:clients/http_json_rpc_client.go:L606-636 - Partial batch response leaves unmatched callers with an error. If the array is shorter than queued requests, absent IDs receive
"no response received for request ID: N", logged as ERROR with the full response body. Source:clients/http_json_rpc_client.go:L597-605 - 5ms race-fix window for timeout sentinels in batch. When
batchCtxexpires withDeadlineExceeded, the per-request contextCausemay lag by a few microseconds. The client waits up to 5ms for the cause to stabilize soErrDynamicTimeoutExceededsentinels are preserved for the upstream classifier. Source:clients/http_json_rpc_client.go:L471-479 ErrUpstreamMalformedResponseis retryable. Raised when a batch response body is neither a JSON array nor object. Not in the non-retryable allowlist — eRPC will try another upstream. If all upstreams return malformed responses, the request ends asErrUpstreamsExhausted. Source:common/errors.go:L835-858ErrEndpointServerSideException.originalStatusCodezero-value fallback is 500. WhenoriginalStatusCode == 0(e.g. synthetic gRPC status),ErrorStatusCode()returns 500. A 500 from eRPC does not necessarily mean the upstream returned 500. Source:common/errors.go:L1974-1979JsonRpcErrorExtractoris wired once at startup. The EVM extractor is injected atUpstreamsRegistryconstruction and cannot be changed at runtime. Non-EVM architectures require a code change to swap extractors. Source:upstream/registry.go:L79ErrUpstreamMalformedResponsemethod-level 400 vs wire-level 200 discrepancy.ErrorStatusCode()returns 400, which appears in eRPC logs and metrics labels. However, the HTTP response to the calling client is sent with wire-level HTTP 200 (standard JSON-RPC transport), and the 400 appears only inside the JSON-RPC error envelope's metadata. The 400 is not visible in the HTTP response line seen by callers — only in logs anderpc_upstream_request_errors_total. Source:common/errors.go:L856-858ErrEndpointServerSideExceptionis retryable toward both upstream and network. The error code is not in the non-retryable allowlist inIsRetryableTowardsUpstream, so eRPC will attempt another upstream. A 500 fallback (whenoriginalStatusCode == 0) does not mean the error is deterministic. Source:common/errors.go:L1951-1979proxyPoolis set twice whenjsonRpcCfg != nil.NewGenericHttpJsonRpcClientassignsclient.proxyPool = proxyPoolin the struct literal and then again unconditionally inside theif jsonRpcCfg != nilblock. The net effect is always the passed value — harmless but worth noting when reading the code. Source:clients/http_json_rpc_client.go:L91-148
Observability
The HTTP client layer emits no Prometheus metrics directly. All upstream-level metrics are recorded by upstream/upstream.go and health/tracker.go which wrap the client calls. Errors originating in the HTTP client surface under these metrics:
| Metric | Type | Labels | When it fires |
|---|---|---|---|
erpc_upstream_request_total | counter | project, network, upstream, category, method | Every upstream attempt including batched calls |
erpc_upstream_request_errors_total | counter | project, network, upstream, category, error_type | Transport failures, timeouts, malformed responses; error_type=ErrUpstreamMalformedResponse visible here |
erpc_upstream_request_duration_seconds | histogram | project, network, upstream, category | End-to-end duration per upstream call |
Trace spans. Single requests produce an HttpJsonRpcClient.sendSingleRequest span with network.id, upstream.id, and (at detailed tracing level) request.id and request.method attributes. Batch requests do not create per-call spans; they run under the propagated caller context.
Log messages (key entries):
DEBUG"sending json rpc POST request (single|batch)"— host, raw request body, headersDEBUG"queuing request ... for batch (current batch size: N)"DEBUG"processing batch with N requests"TRACE"using client from proxy pool"— pool ID, transport pointer, resolved proxy URLTRACE"starting batch timer","setting batch deadline to earliest request deadline","committing batch to process total of N requests"TRACEresponse body (first 20 KiB + last 20 KiB when response body is oversized)ERROR"failed to get client from proxy pool"— whenProxyPool.GetClientreturns error (empty pool)WARN"unexpected response received without ID"— batch response element has noidfieldWARN"unexpected response received with ID: <id>"— batch response ID not in pending request mapERROR"some requests did not receive a response (matching ID)"— with full response body
Source code entry points
clients/http_json_rpc_client.go:L89-L148(opens in a new tab) —NewGenericHttpJsonRpcClient: transport construction, field initialization, gzip and batch configclients/http_json_rpc_client.go:L786-L951(opens in a new tab) —prepareRequest,sendSingleRequest,normalizeJsonRpcError: request shape, OTel injection, error classificationclients/http_json_rpc_client.go:L241-L479(opens in a new tab) —queueRequest,processBatch: batch aggregation, deadline propagation, context pre-checksclients/registry.go:L47-L125(opens in a new tab) —ClientRegistry.GetOrCreateClient/CreateClient: sync.Map cache, scheme dispatch, proxy pool resolutionclients/proxy_pool_registry.go:L23-L98(opens in a new tab) —ProxyPool.GetClient(round-robin),createProxyPool, proxy transport constructionutil/http_dialer.go:L8-L24(opens in a new tab) —DefaultOutboundDialer:net.Dialer{Timeout: 10s, KeepAlive: 15s}common/validation.go:L230-L247(opens in a new tab) —ProxyPoolConfig.Validate: ID required, URLs non-empty, prefix scheme checkcommon/error_extractor.go:L10-L21(opens in a new tab) —JsonRpcErrorExtractorinterface +JsonRpcErrorExtractorFuncadaptercommon/errors.go:L835-L858(opens in a new tab) —ErrUpstreamMalformedResponse: meaning,ErrorStatusCodereturns 400, retryablecommon/errors.go:L1951-L1979(opens in a new tab) —ErrEndpointServerSideException:originalStatusCodefield, 500 fallbackclients/http_connection_test.go(opens in a new tab) — behavior-locking tests validatingMaxConnsPerHost: 0fix under loadcommon/config.go:L1072-L1079(opens in a new tab) —JsonRpcUpstreamConfigstruct definitioncommon/config.go:L1985-L1988(opens in a new tab) —ProxyPoolConfigstruct definitioncommon/defaults.go:L1700-L1704(opens in a new tab) — unconditionalu.JsonRpc = &JsonRpcUpstreamConfig{}if nil beforeSetDefaults()
Related pages
- Retry — retry policy wrapping upstream calls; transport errors flow through here.
- Timeout — per-request timeout bounds that feed
ErrDynamicTimeoutExceededinto the batch deadline path. - Rate limiters — cap outbound RPS per upstream or proxy pool to stay within provider budgets.
- Upstreams — full upstream config including
endpoint,jsonRpc, andupstreamDefaults. - Selection policies — how eRPC chooses which upstream (and which proxy-pool-backed client) receives each request.