A tunnel used to mean buffered responses: the whole body assembled on your machine,
then shipped to the caller in one piece — fine for JSON, useless for a stream.
SchemaClient tunnels now relay streaming responses live: an SSE endpoint on
localhost pushes events through the public URL as they happen.
What streams, what buffers
Two kinds of response are relayed chunk by chunk instead of buffered:
- Server-Sent Events — anything with a
text/event-streamcontent type. - Chunked responses — anything with no declared length, which covers long-lived chunked transfers and most streaming framework output.
Everything else still buffers, and buffered responses cap at 5 MB. Responses without a declared length are no longer subject to that cap, since they stream through instead of assembling in memory.
This is what makes it practical to test an SSE feature from a real phone, hand a teammate a live event feed, or point an actual consumer at your dev server before anything is deployed.
Try it with a local SSE endpoint
Run any local server with an SSE route, then start a tunnel from the Tunnel tab (see exposing localhost for the full walkthrough). From another machine or network:
curl -N https://u1-48213977.schemaclient.com/events
-N disables curl's own buffering. You should see events print the moment your
local server emits them — not all at once when the connection closes. If they arrive
in a burst at the end, the buffering is in your local stack (a proxy or framework
default), not the tunnel.
How the relay works
The desktop app reads the response from your local server and forwards each chunk over its control connection to the gateway, which passes it straight through to the public caller. There is no setting — streaming activates automatically when both the app and the gateway support it, and falls back to buffered relay otherwise. One long-lived stream does not block other requests through the same tunnel; they are handled independently.
Timeouts
Two limits govern a streamed response:
- Start window (~40 seconds). Your local server must begin responding within the normal tunnel request window. A stream that takes a minute to send its first byte times out like any other slow response.
- Idle limit (~2 minutes). Once the stream is open, it stays open as long as
chunks keep arriving. Two minutes of silence closes it. For SSE, keepalive comment
lines (
: ping) count as data — if your event source can go quiet for long stretches, emit one every 15-30 seconds.
There is no overall duration cap: a stream that keeps flowing keeps relaying.
What does not stream
- WebSockets. The upgrade handshake is not relayed, so WebSocket endpoints behind a tunnel do not connect. If you need live updates through a tunnel today, serve them over SSE.
- Native gRPC. Not supported through the tunnel. gRPC-Web works, because it is ordinary chunked HTTP — which streams.
Streamed traffic still appears in the tunnel's request log alongside everything else — see monitoring API traffic.