Keeping frp Fast and Available: Multiplexing, Pools, and Health
Choosing TCP, HTTP, UDP, or a private visitor mode defines what frp should expose, but it does not determine how well that exposure behaves under load. This chapter examines the layers between a public request and the local service: the transport to frps, the logical streams carried over it, the reserve of work connections, and the feedback that selects healthy backends. The practical goal is to distinguish a physical connection from a logical request and to make performance choices without turning a documented capability into a universal speed promise.
“The tunnel” is a stack of different decisions
A request may travel from frpc to frps over TCP, KCP, QUIC, WebSocket, or WSS. These are not five names for the same wire behavior. TCP is a conventional stream path. KCP uses UDP underneath and adds its own reliability behavior. QUIC supplies encrypted, multiplexed streams over UDP. WebSocket and WSS can make the connection fit environments that expect an HTTP upgrade, with WSS adding TLS. Which option works best depends on what the surrounding network permits, what the server listens for, and what the workload needs.
The connector then decides whether to create a new underlying connection for each logical connection or share an established session. With TCP stream multiplexing enabled, frp wraps one transport connection in a stream multiplexer, so several logical streams can use it. QUIC offers a similar distinction through native streams. A logical stream is the unit the proxy lifecycle allocates to a request; a physical connection is the network relationship carrying one or more streams. Treating them as the same would make it impossible to reason clearly about setup cost, failure scope, or concurrency.
That distinction also explains why a transport can be both efficient and a failure boundary. Sharing an underlying session avoids repeating connection establishment for every short request, but a failure in that session can affect several logical streams at once. Opening separate connections can isolate failures or fit a restrictive network better, but it repeats setup work. frp exposes the choice through transport configuration rather than pretending that one topology is always superior.
The wire protocol and the outer transport are related but not identical. A client can negotiate a frp message format on top of a selected connection method, while the connector decides how the network connection or stream is opened. Keeping those layers separate lets frp add a transport or wire capability without changing the meaning of every proxy mode. It also means an operator should diagnose the right layer: a failed WebSocket upgrade is not the same problem as an unavailable local HTTP backend, even though both may surface as a failed public request.
The diagram’s important point is not that every request passes through every option. It is that these choices act at different layers.