SSE Stream Tester

Check whether streamed events show up as soon as the server sends them.

A server sends events one at a time over a single open connection. Each event includes the time it was sent, and this page records the time it arrived. If those two times are close, the stream is working. If events pile up and land together at the end, something in between is holding them.

1Pick a situation

Each option changes one thing: how the server behaves, or what sits between the server and your browser. Run a few to see the difference between a stream that works and one that does not.

2Run it

Pick a situation above to see what it does.

Settings

Opens the stream again as soon as the previous one closes, and logs the gap between them. This is the "server closes at 15s, then call it again" test. If the first connection is fine and the second is held back, look at connection reuse and keepalive rather than at the stream itself.

Runs any SSE URL instead of the built-in scenarios, so you can check a real environment. Needs CORS on the target. Per-event delay is measured when the payload carries a send timestamp, otherwise the verdict falls back to delivery pattern alone and says so.

X-Accel-Buffering: no asks nginx and several CDNs to stop buffering a response. Toggle it to see whether a path honours it. Anything that ignores it is doing real inspection, not just proxying.

Clock offset is measured against the server across nine samples, keeping the one with the fastest round trip. Without it, any difference between the two clocks would show up as delay.

Scenarios

Each one is a different server behaviour. The tag shows the verdict it should produce on a clean path. Click to run it.

Current run

Nothing running.

no run yet

Timeline

Top lane is when the server sent each event, bottom lane is when it arrived. Faint vertical lines are TCP chunk boundaries, so several events between two lines means one network read carried them all.

sent
recv

Events

Age counts up while the run is going and stops when it ends, so the final state stays readable. Δsent and Δarrived are the gaps to the previous event. When those two drift apart, delivery is not keeping up with sending.

#sent atage since sentdelay ΔsentΔarrivedchunknote

Log

Response headers, reconnects, stalls, and the server's own record of when it wrote each frame to the socket. That last part is what separates a buffering app from a buffering network.

Run summary

One row per run. The last column compares the verdict against what the scenario should produce, so you can spot a regression without reading the numbers.

scenariopathtransporteventschunks TTFEp50p95maxclusters verdictexpected