Skip to content

Waterfall Timeline

The Waterfall Timeline shows the timing of every request in your session as horizontal bars on a shared time axis — like a Gantt chart for network traffic. Each bar represents one HTTP request, and its position and width show when the request started and how long it took. Color-coded segments within each bar break down where time was spent: DNS resolution, TCP connection, TLS handshake, waiting for the server to respond (TTFB), and transferring the response data.

This view answers questions that the regular flow list can’t: “Which requests happened in parallel?”, “Where’s the bottleneck — is it DNS, TLS, or the server?”, “How do the requests triggered by this button click relate to each other in time?”

Ghost has two waterfall views: the multi-flow timeline (replaces the traffic list) and the single-flow timing detail (an overlay in the flow inspector). Both are described below.

Switch to the waterfall view using the view mode toggle in the toolbar (list icon / waterfall icon). The toggle is stored in Ghost’s UI state — switching back to list mode preserves your position.

┌──────────────────────────────────────────────────────────────────┐
│ 0ms 200ms 400ms 600ms 800ms 1000ms │
├────────────────┬─────────────────────────────────────────────────┤
│ ◆ Click #cart │ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░ POST /api/cart 142ms│
│ │ ▓▓▓▓▓▓▓░░░░░ GET /api/stock 89ms │
│ │ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ GET /images/cart.png │
├────────────────┼─────────────────────────────────────────────────┤
│ Background │ ▓▓░░ GET /api/heartbeat 12ms │
│ │ ▓▓░░ GET /api/config 8ms │
└────────────────┴─────────────────────────────────────────────────┘
■ DNS ■ TCP ■ TLS ■ TTFB ■ Transfer

The waterfall has three main areas:

AreaWidth/HeightPurpose
Label column260px (fixed)Shows the HTTP method badge, status code, and path (truncated to 35 characters) for each flow
Time axis28px tall, sticky at topShows 6 evenly-spaced tick marks with timestamps (milliseconds or seconds). Stays visible as you scroll. Has a frosted glass background (bg-ghost-900/95 backdrop-blur-sm).
Bar areaRemaining widthThe actual timing bars, with vertical grid lines at each tick position

Each flow row is 32px tall. The timing bars themselves are 22px tall (centered within the row). Group header rows are 28px tall.

When Ghost has detailed timing data for a flow (DNS, TCP, TLS, TTFB, Transfer), the bar is segmented — each phase gets a proportional colored segment:

PhaseColorWhat It Measures
DNSEmeraldHow long it took to look up the domain name (e.g., api.example.com192.168.1.1). High DNS times may indicate DNS server issues or cold DNS caches.
TCPAmberHow long the TCP connection took to establish (the “three-way handshake”). High values suggest network latency or congestion.
TLSPurpleHow long the TLS/SSL handshake took to negotiate encryption. High values may indicate slow certificate validation or cipher negotiation.
TTFBCyanTime To First Byte — how long the server took to start sending the response after receiving the complete request. This is the server’s “thinking time.”
TransferBlueHow long it took to download the complete response body after the first byte arrived. Proportional to response size and bandwidth.

Each segment has a minimum width of 1 pixel (if the phase duration is greater than zero), so even very fast phases are visible. All segments render at 70% opacity to prevent visual harshness.

When detailed timing phases aren’t available (for imported flows, replayed flows, or flows where the proxy couldn’t capture timing breakdown), the bar uses a single color based on the status code:

Status RangeBar Style
2xx (success)Cyan-to-blue gradient
3xx (redirect)Ghost gray
4xx (client error)Amber
5xx (server error)Red

The minimum bar width is 3 pixels — even sub-millisecond flows are visible (you’d need to zoom in to see their timing, but they’re never invisible).

When a bar occupies more than 4% of the visible timeline width, a duration label appears inside the bar (e.g., “142ms” or “1.2s”). Labels use a tiny monospace font (9px) in a light color so they’re readable against any bar color. For narrower bars, hover to see the full timing in a tooltip.

Flows are automatically organized by browser interaction — each interaction (click, navigation, form submit) becomes a collapsible group header with all its triggered flows beneath it.

How grouping works:

  1. Flows with an interaction field are grouped by {event_type}:{selector} — for example, all flows triggered by a click on #add-to-cart become one group
  2. Flows without interactions go into a “Background” group (heartbeats, polling, analytics, etc.)
  3. Groups are sorted chronologically by the earliest flow’s timestamp
  4. If there’s only one group and it’s all background traffic, group headers are hidden (flat list)

Group header appearance:

  • Click the collapse indicator (triangle ▸/▾) to expand or collapse a group
  • Event type badge (purple background with monospace text) — shows “click”, “input”, “navigate”, etc.
  • Selector label — the CSS selector of the interacted element, truncated to 30 characters
  • Flow count — how many flows are in this group

Diamond markers: Flows that have an associated interaction show a small purple diamond marker (rotated 45-degree square) at the flow’s start position in the bar area, making it easy to spot interaction-triggered requests.

The waterfall uses @tanstack/react-virtual for efficient rendering — only the visible rows (plus 20 rows of overscan above and below the viewport) are rendered in the DOM. This means you can view sessions with thousands of flows without any performance degradation. Rows are absolutely positioned using CSS transforms.

Zoom lets you focus on a specific time range within the session.

Ctrl + Scroll wheel (or Cmd + Scroll on macOS):

  • Scroll up: zooms in by 0.7x factor (each tick narrows the visible range to 70%)
  • Scroll down: zooms out by 1.3x factor (each tick expands the visible range to 130%)
  • Zoom is anchored to the cursor position — the point under your cursor stays fixed while the timeline scales around it
  • Maximum zoom: 100x (minimum visible span is 1% of the total timeline)

Toolbar buttons (top-right corner):

  • Zoom In (magnifying glass +) — halves the visible range, centered on the current midpoint
  • Zoom Out (magnifying glass −) — doubles the visible range, centered on the current midpoint
  • Reset (arrows out icon) — returns to full timeline view. Only visible when zoomed.
  • Zoom indicator — shows current magnification (e.g., “2.5x”) in monospace text. Only visible when zoomed.

Toolbar legend (top-left): Five colored dots with phase labels (DNS, TCP, TLS, TTFB, Transfer) so you always know what the colors mean.

Zoom and collapse state automatically reset when the underlying flow data changes — detected by a fingerprint of {flowCount}:{firstFlowID}. This prevents stale zoom positions when you switch sessions, apply filters, or new traffic arrives.

  • Click a row to select it (highlights with a subtle purple tint). Click again to deselect.
  • Hover over a row to see it highlighted with bg-ghost-850.
  • The selected flow can be inspected in the flow detail panel alongside the waterfall.

The per-flow timing view is an overlay in the flow inspector — toggle it with the timer icon in the inspector’s hero bar. It provides deep analysis of one flow’s timing.

The flow’s total duration is classified with a speed label and color:

DurationLabelColorWhat It Means
≤ 0 msPendingGrayThe request hasn’t completed yet or has no timing data
< 100 msBlazingCyanExtremely fast — typical for cached responses, CDN hits, or localhost
< 500 msFastGreenGood performance — typical for well-optimized API calls
< 1,500 msNormalBlueAcceptable for most operations — typical for database queries or moderate computation
< 5,000 msSlowAmberNoticeable delay — may indicate performance issues worth investigating
≥ 5,000 msVery SlowRedUser-impacting delay — likely a timeout, cold start, or heavy computation

A horizontal bar showing this flow’s duration relative to the slowest flow in the session:

  • Fill width: proportional to duration / sessionMax (so the slowest flow always fills 100%)
  • Fill color: a gradient that shifts with duration — cyan-to-blue for fast flows, cyan-to-purple for normal, purple-to-amber for slow, amber-to-red for very slow
  • P50 marker: a thin vertical line (gray, 60% opacity) at the 50th percentile (median) position, with hover label showing the exact P50 value
  • P95 marker: a thin vertical line (amber, 60% opacity) at the 95th percentile position, with hover label
  • Bottom labels: 0ms, P50: {value}, P95: {value}, Max: {value} — spanning the full bar width

How percentiles are calculated: All flows in the current store with a duration > 0 are sorted. P50 = value at the 50% position. P95 = value at the 95% position. The current flow’s percentile rank is calculated as the percentage of flows with duration ≤ this flow’s duration. Displayed as “Faster than {100 − percentile}% of flows.”

When the flow has detailed timing data, a horizontal stacked bar shows all five phases proportionally:

PhaseColorDescription
DNSTealDNS lookup time
ConnectBlueTCP connection time
TLSPurpleTLS handshake time
TTFBCyanTime to first byte
TransferPinkData transfer time

Each segment has a minimum width of 2 pixels and shows a hover tooltip with the phase name and exact duration. Below the bar, a 5-column grid shows each phase with a colored dot, label, and formatted duration.

When the flow has non-zero content, this section shows:

  • Request size bar — cyan-to-blue gradient, width proportional to the larger of request/response
  • Response size bar — purple-to-pink gradient, same proportional scaling
  • Total — combined size in human-readable format (KB, MB)
  • Ratio — response-to-request size ratio (e.g., “1:4.2”), helping identify requests where the response is disproportionately large

Four stat cards showing the current session’s timing profile:

StatWhat It Shows
AverageMean duration across all flows with timing data
P50Median duration — half the flows are faster, half are slower
P9595th percentile — only 5% of flows are slower than this. Often used as a performance target.
Total FlowsCount of flows with timing data (formatted with locale separators, e.g., “1,247”)

A two-column grid showing metadata about the connection:

FieldWhat It Shows
StartedFormatted timestamp of when the request began
DurationTotal request duration
ProtocolHTTP protocol version from the request (e.g., HTTP/1.1, HTTP/2)
SourceHow the flow was captured (proxy, replay, import, script)
HostThe target hostname
Content TypeResponse content type (falls back to request content type, then ---)
StatusResponse status code and text (only shown if a response exists)
Response ProtoHTTP protocol version from the response (only shown if a response exists)
MetadataAny additional flow metadata entries, shown below a separator line

When comparing two sessions, Ghost shows a timing diff for matched flows:

ColumnWhat It Shows
PhaseDNS Lookup, TCP Connect, TLS Handshake, TTFB, Transfer, Total
SourceDuration in the source session
TargetDuration in the target session
DeltaDifference (red if > 10ms slower, green if > 10ms faster, gray if within 10ms)

The phase with the largest absolute delta (if ≥ 50ms) is highlighted as the bottleneck — shown in red bold text to draw attention to where the performance change is concentrated.

Identify parallelism opportunities — The waterfall shows which requests happen sequentially vs. in parallel. If five API calls run one-after-another (a “staircase” pattern), you might be able to batch them or run them concurrently.

Find the slow phase — A request took 2 seconds, but was it DNS (change your DNS server), TLS (warm up TLS sessions), TTFB (optimize your backend), or Transfer (compress the response)? The timing breakdown answers this instantly.

Spot waterfall bottlenecks — When Request B can’t start until Request A finishes (because A returns data that B needs), you see a clear sequential pattern. The waterfall makes these dependency chains visible at a glance.

Group by user action — See all the network activity triggered by a single button click. If clicking “Add to Cart” fires 12 requests taking a total of 800ms, the interaction group shows exactly which requests contribute to the perceived delay.

Compare performance across sessions — The timing diff view in session comparison highlights exactly which phases got slower or faster, with the bottleneck automatically identified.

Monitor P95 drift — The single-flow detail view shows where the current request sits relative to the session’s P50 and P95 markers. If a request that was consistently at P50 is now at P95, something changed.