Performance Benefits of Using FastHTTP in FastProxy: A Deep Dive into High-Performance Proxy Architecture

Enabling FastHTTP mode in FastProxy eliminates per-request heap allocations, reduces GC pressure, and achieves zero-copy I/O by switching from Go's standard net/http to the high-performance fasthttp library.

FastProxy, an open-source API gateway in the kingson4wu/fast_proxy repository, offers a runtime-selectable transport layer that lets operators trade compatibility for raw speed. When the fastHttp.enable configuration flag is set to true, the proxy bypasses Go's standard net/http stack entirely in favor of valyala/fasthttp, a library optimized for high-throughput microservice communication. This architectural shift delivers measurable gains in latency, throughput, and memory efficiency.

How FastHTTP Mode Activates in FastProxy

The proxy implements a clean abstraction that branches at initialization based on a single boolean flag.

Configuration-Driven Activation

In common/config/yaml_config.go, the FastHttpEnable() method parses the YAML configuration to determine which server implementation to instantiate:

// common/config/yaml_config.go#L77
func (c *Config) FastHttpEnable() bool {
    return c.FastHttp.Enable
}

Setting fastHttp.enable: true triggers the alternative code path without requiring changes to business logic.

Server Listener Selection

The common/server/server.go file contains the branching logic that selects between the standard library and fasthttp:

  • Traditional path: Uses http.Server with ListenAndServe at line 92 (httpServerStart)
  • FastHTTP path: Uses fasthttp.ListenAndServe with a custom request handler at line 101 (fasthttpListen)

The fasthttp server avoids allocating http.Request and http.ResponseWriter objects for every connection, instead reusing byte buffers from an internal pool.

Zero-Copy Request Handling Architecture

The most significant performance benefit emerges in the request proxying layer, implemented in inproxy/internal/proxy/httpclientProxy.go.

Eliminating Body Allocation Churn

Standard net/http requires reading the request body into a slice, wrapping it in an http.Request, and forwarding it. In contrast, the fastDoProxy function (line 31, fastDoProxyBody) directly copies the original body bytes into a fasthttp.Request without an intermediate io.ReadAll call:

// Direct body transfer without extra allocation
req.SetBodyRaw(bodyBytes)

This zero-copy approach preserves memory locality and eliminates the CPU overhead associated with double-buffering.

Optimized Header Processing

Header manipulation in standard Go requires looping over http.Request.Header maps and allocating strings. FastProxy's fasthttp implementation (line 24, fastHeaderCopy) uses fasthttp.Request.Header.Set methods backed by a byte-slice pool:

// O(N) complexity but uses pooled buffers
for key, values := range headers {
    for _, value := range values {
        fastReq.Header.Set(key, value)
    }
}

While both paths are O(N), the fasthttp version dramatically reduces allocation churn by reusing header key/value buffers from the pool.

Connection Management and Client Performance

Reusable Client Infrastructure

The BuildClient function in inproxy/internal/proxy/httpclientProxy.go instantiates both client types but routes traffic based on the configuration flag:

  • Standard client: http.Client created at line 30 (httpClientDo)
  • FastHTTP client: fasthttp.Client created at line 39 (fastClientInit)

The fasthttp.Client maintains internal connection pools with native TCP keep-alive support, eliminating the Transport configuration overhead required by net/http.

Timeout Handling Without Goroutine Explosion

Standard http.Client timeout implementations often spin up additional goroutines per request. FastProxy leverages fasthttp.Client.DoTimeout or DoDeadline (line 48, fastTimeout), which implement timeout logic using a single system call and a shared timer that does not create new goroutines:

// No extra goroutine created for timeout management
err := client.DoTimeout(req, resp, timeoutDuration)

This reduction in goroutine count decreases context switches and scheduler pressure, enabling higher sustained request-per-second rates on the same hardware.

Response Processing Efficiency

The outbound path in inproxy/internal/proxy/httpclientProxy.go uses EncodeFastResp (line 73, fastResponseEncode) to handle upstream responses:

// Direct byte slice access, no extra copy
body := resp.Body()
io.Copy(w, bytes.NewReader(body))

By working directly on the fasthttp.Response.Body() byte slice and streaming via io.Copy, the proxy avoids allocating a new slice to hold the response payload. The outbound proxy in outproxy/internal/proxy/httpclientProxy.go implements identical logic in outFastDoProxy (line 71), ensuring consistent performance for both ingress and egress traffic.

Measurable Performance Impact

Deploying FastProxy with FastHTTP enabled produces three primary benefits in production environments:

  • Lower latency: Fewer system calls and eliminated per-request heap allocations reduce p99 response times, particularly for small JSON payloads.
  • Higher throughput: Connection reuse pools and zero-copy I/O allow the proxy to sustain thousands of QPS on modest hardware without CPU saturation.
  • Reduced GC pressure: The extensive use of fasthttp's internal buffer pools keeps the Go garbage collector from triggering stop-the-world pauses during traffic spikes.

These gains become pronounced in high-traffic microservice meshes where the proxy serves as a critical path for every RPC call.

Implementation Examples

Enable FastHTTP mode with a single YAML change:

fastHttp:
  enable: true

The programmatic initialization remains identical regardless of transport mode:

cfg, _ := config.LoadYamlConfig(yamlBytes)
logger := logger.NewZapLogger()
proxy := server.NewServer(cfg, logger, myHandler)
proxy.Start() // Automatically selects fasthttp if cfg.FastHttpEnable() is true

For upstream calls, the proxy automatically selects the fast path. To use fasthttp.Client directly outside the proxy context:

client := &fasthttp.Client{
    MaxConnsPerHost: 100,
}
req := fasthttp.AcquireRequest()
resp := fasthttp.AcquireResponse()
defer fasthttp.ReleaseRequest(req)
defer fasthttp.ReleaseResponse(resp)

req.SetRequestURI("http://upstream/service")
req.Header.SetMethod("GET")
if err := client.Do(req, resp); err != nil {
    log.Fatal(err)
}
fmt.Println(string(resp.Body()))

Summary

  • FastProxy switches to high-performance mode via the fastHttp.enable flag in common/config/yaml_config.go, activating fasthttp.ListenAndServe in common/server/server.go.
  • Zero-copy I/O in fastDoProxy eliminates double-buffering of request bodies, reducing memory allocations and CPU cycles.
  • Pooled buffers for header processing replace per-request map allocations, decreasing GC pressure during high-traffic periods.
  • Goroutine-efficient timeouts via DoTimeout avoid the scheduler overhead associated with net/http deadline management.
  • Connection pooling in fasthttp.Client reuses TCP connections aggressively, maximizing throughput for microservice communication.

Frequently Asked Questions

How do I enable FastHTTP mode in FastProxy?

Set fastHttp.enable: true in your YAML configuration file. The FastHttpEnable() method in common/config/yaml_config.go reads this value, and common/server/server.go automatically routes to fasthttp.ListenAndServe instead of http.Server when the flag is active.

What is the performance difference between net/http and FastHTTP in FastProxy?

FastHTTP mode eliminates per-request allocations of http.Request objects, uses zero-copy body transfers in fastDoProxy, and manages timeouts without spawning extra goroutines. According to the implementation in inproxy/internal/proxy/httpclientProxy.go, this reduces latency and GC pressure while increasing sustainable QPS.

Does FastProxy support both transport modes simultaneously?

No, FastProxy uses a global configuration flag to select the transport layer at startup. The BuildClient function in inproxy/internal/proxy/httpclientProxy.go creates either an http.Client or fasthttp.Client based on the configuration, and the server layer commits to one implementation for the process lifetime.

Can I use fasthttp.Client features like MaxConnsPerHost with FastProxy?

Yes, when FastHTTP mode is enabled, FastProxy utilizes fasthttp.Client with configurable connection pools. The client initialization in inproxy/internal/proxy/httpclientProxy.go supports standard fasthttp tuning parameters such as MaxConnsPerHost, allowing operators to optimize connection reuse for their specific upstream topology.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →