- Evidence
- The document and app files come from CloudFront over HTTP/1.1 (protocol column: http/1.1): 69 files from app.hyperliquid.xyz before trade-ready in the 1 October capture, and 173 HTTP/1.1 requests in the 3 October recorded load. HTTP/1.1 allows about six requests at a time per host, so files wait their turn. The first four scripts (index-VjaZKeGd.js, config-DWzED1yW.js, index-CUao1WyN-C4wB_l4q.js, LineChart-DV47HQLT.js) are requested at 0.11 s and arrive at 0.47–0.49 s.
- Measured
- 69 app files over HTTP/1.1 in the capture; 173 HTTP/1.1 requests in the recorded load
- Holds back
- Start-up as a whole; which panel waits for this work is not established.
- Fix
- Enable HTTP/2 and HTTP/3 on the CloudFront distributions.
- Where
- CloudFront distribution settings, "Supported HTTP versions", for app.hyperliquid.xyz.
- Verify
- DevTools → Network → Protocol column shows h2 or h3 for app files.
Hyperliquid: where its trading screen loses time, and what to fix
Measured from the Netherlands in a logged-in Chrome, October 2026.
Three measurements appear on this page, and their times differ. Rank and results come from the campaign's timed reloads. The diagnostic capture and the recorded reload are single loads made with recording switched on, which slows the page: read them for the order of events and the gaps, not for totals.
Resultscampaign: 5 warm and 5 uncached reloads
| Warm reload | median 3.1 s, range 2.7 s–3.3 s; loads: 3.1 s, 3.3 s, 2.7 s, 3.2 s, 2.8 s |
| Uncached reload | median 3.5 s, range 3.0 s–3.9 s; loads: 3.5 s, 3.0 s, 3.9 s, 3.7 s, 3.2 s |
| Standing | 4 of 27 by median; possible rank 2 to 5. 0.6 s behind the fastest, Thalex (2.4 s): 1.3 times as long. The possible rank is the range the measurements leave open: it counts only the exchanges that clearly beat this one and those it clearly beats. Exchanges whose ranges overlap cannot be told apart. |
| Loads ready | 5 of 5 warm, 5 of 5 uncached |
| Notes | recent trades not measured: inactive tab |
Where the time goescampaign medians, warm reload
Panels in the order they first showed real, usable data on a warm reload. The coloured part of each row is the time that panel added after the one before it. The last row is trade-ready: every panel is ready and the page has stopped moving.
Stack
React, built with Vite; TradingView charting library; Privy wallet iframe and WalletConnect; Statuspage embed.
Delivery
Page and files from AWS S3 through CloudFront over HTTP/1.1, compressed, with no cache-control header on the app files; market data from api-ui.hyperliquid.xyz through CloudFront. No service worker.
| Host | Role | CDN edge seen | Connect | Response |
|---|---|---|---|---|
| app.hyperliquid.xyz | page | CloudFront Amsterdam | 12 ms | 8 ms |
| api.hyperliquid.xyz | market data | CloudFront Amsterdam | 12 ms | 226 ms |
| api-ui.hyperliquid.xyz | market data | CloudFront Amsterdam | 13 ms | 232 ms |
Median of up to 10 attempts from the test machine. Response time includes the server's own time, so it is not a distance.
What happened, in orderdiagnostic capture 1 October, uncached
From one uncached diagnostic load recorded on 1 October 2026 (cache disabled, browser extensions active), so totals are slower than the campaign's timed loads; file names, sizes, headers, order of events and main-thread times are what the findings rely on. A main-thread time given for a script counts all the work that starts in that script, including code it calls in other files, so it shows where start-up work begins, not what one library costs. Endpoint paths were masked when the capture was saved.
| When | What |
|---|---|
| 0.02 s | HTML arrives (CloudFront, HTTP/1.1). |
| 0.11–0.49 s | Entry scripts download: index (296 KB compressed, 1.3 MB unpacked), config (525 KB, 2.1 MB), index-CUao (226 KB, 0.8 MB), LineChart (88 KB). |
| 0.85 s | The app opens the live feed to api-ui.hyperliquid.xyz and, at the same moment, fetches the WalletConnect wallet registry: 170 KB compressed, 1.2 MB unpacked. |
| 0.91 s | First paint. |
| 1.54 s | Live-feed handshake completes, 0.7 s after it started; first message at 1.95 s. |
| 1.75–2.14 s | The Privy wallet iframe loads 31 scripts, 0.9 MB compressed and 3.4 MB unpacked. |
| 2.40 s | Price shows; order book at 2.63 s. |
| 2.57 s | Candle history is requested (46 KB); it answers at 3.56 s. |
| 3.73 s | Chart drawn: trade-ready in this load. react-dom alone started 0.86 s of main-thread work. |
Recorded warm reload, 3 October
One warm reload recorded with Chrome's performance trace. Recording slows the page, so read the order and the gaps, not the total.
| When | What |
|---|---|
| 0.0 s | HTML arrives |
| 1.0 s | First frame sent on a live feed |
| 1.3 s | account-table ready |
| 1.3 s | account-info ready |
| 1.4 s | First frame received on a live feed |
| 1.4 s | Order form ready |
| 1.6 s | Price ready |
| 1.9 s | Order book ready |
| 2.6 s | Chart ready |
| 3.3 s | Trade-ready |
238 requests before trade-ready; 10 long main-thread tasks (over 50 ms) before trade-ready, longest 114 ms; 101 script requests before the first panel; 173 requests over HTTP/1.1.
Request waterfalldiagnostic capture 1 October, uncached
70 of the 138 requests (the page itself, the longest and the largest) started before market data was ready in the 1 October uncached capture, in start order. The outlined part of a bar is waiting for the server; the solid part is downloading. Rows are numbered so a request can be pointed to. The numbers on the right are the size received and the total time. Vertical lines mark when a panel had data in this capture.
PageScriptData requestFont, media, other fileImagewaiting for the serverdownloading
Bottlenecks and fixes, largest firstdiagnostic capture 1 October, uncached
- Evidence
- 1 October capture: the candle-sized request starts at 2.57 s, 0.06 s before the book shows at 2.63 s, waits 0.73 s for its first byte and ends at 3.56 s; the chart is drawn 1.1 s after the book. The market is in the URL from the first byte. A timed load shows eight requests to https://api-ui.hyperliquid.xyz/info: three at 0.9–1.0 s and five at 2.8 s; the candle request is probably in the second group. In the campaign the chart is the last panel in 3 of 5 warm loads and the book in 2.
- Gap observed
- 1.10 s between the order book and the chart
- Holds back
- Chart (median 2.5 s in the timed loads).
- Fix
- Send the candle-history request to /info together with the first three /info requests at 0.9 s, before the chart component mounts.
- Where
- The trade page's data bootstrap and chart datafeed.
- Verify
- DevTools → Network, filter "info": the candle request starts before 1 s; the chart appears close to the book.
- Evidence
- 1 October capture: WalletConnect's wallet list (1.2 MB unpacked, 175 KB compressed) at 0.85 s, and 31 scripts from auth.privy.io at 1.75 s (3.4 MB unpacked, 0.9 MB compressed), all before the price shows at 2.4 s. They share the connections and the main thread with the trading code. All 10 older timed loads also make eight calls to rpc.hyperliquid.xyz/evm before trade-ready (at 2.85 s in one, the longest taking 0.78 s).
- Measured
- a 1.2 MB wallet list and 31 Privy scripts (3.4 MB unpacked) before the price
- Holds back
- Not established: the captures do not show which panel waits for this.
- Fix
- Load WalletConnect and Privy after the price, book and chart are shown, or on the first wallet action, and make the eight chain RPC calls after trade-ready.
- Where
- Wallet provider initialisation in the app shell.
- Verify
- DevTools → Network sorted by start: no walletconnect, privy or rpc.hyperliquid.xyz request before the first price paint.
- Evidence
- 1 October capture: WebSocket created at 0.85 s, handshake done at 1.54 s, first message at 1.95 s. 3 October recorded warm load: first frame sent at 1.00 s, first received at 1.40 s. The captures hold no DNS or TLS timing for the socket, so they do not show where the 0.7 s goes.
- Gap observed
- 0.70 s from creating the feed socket to its handshake
- Holds back
- Not established: the captures do not show which panel waits for this.
- Fix
- Open the market-data socket from the first script (or preconnect to api-ui.hyperliquid.xyz in the HTML head) and measure where the 0.7 s goes (DNS, TLS, server) before moving the socket endpoint.
- Where
- HTML head and feed client.
- Verify
- DevTools → Network → WS: socket created within ~200 ms of the document.
- Evidence
- 1 October capture: none of the 69 files from app.hyperliquid.xyz carries a cache-control header, although the names are content-hashed (config-DWzED1yW.js, 2.1 MB unpacked; index-VjaZKeGd.js, 1.3 MB). 3 October recorded warm load: of 194 responses, 6 came straight from the browser cache and 158 were re-checked with the server first. The record does not list which responses those 158 are. Over HTTP/1.1 each re-check waits for one of six connections.
- Measured
- 158 of 194 responses re-checked with the server on a warm reload
- Holds back
- Not established: the captures do not show which panel waits for this.
- Fix
- Serve the hashed files under app.hyperliquid.xyz with cache-control: max-age=31536000, immutable.
- Where
- S3 object metadata or a CloudFront response headers policy for the app's asset path.
- Verify
- DevTools → Network on a normal reload: the app's .js files show "(disk cache)" or "(memory cache)", not 304.
- Likely saving
- Unknown: fewer round trips on a warm reload
- Evidence
- 3 October recorded warm load: the chart has its data at 2.63 s and trade-ready follows at 3.27 s; in 7 of the 8 samples in between the chart panel still has a running animation. The same shows in all 10 timed loads we could replay; in the 5 warm ones a font is also still loading during this wait (Inter-Bold is requested only at 3.36 s in the 1 October capture). Both Inter files are in the older WOFF format, 134 and 144 KB; as WOFF2 subsets they would be a fraction of that.
- Gap observed
- 0.64 s between the chart having its data and trade-ready, in the recorded load
- Holds back
- Trade-ready itself: the page counts as ready only when nothing in a panel is still animating or loading.
- Fix
- Record a reload with DevTools → Animations and find what still animates in the chart after the candles are drawn, for example a toolbar loading spinner or a fade-in; end it when the data is in. Preload the Inter-Bold font and ship both Inter files as WOFF2 subsets.
- Where
- The chart panel and its loading states. The font-face rules for Inter.
- Verify
- DevTools → Animations during a reload: nothing in the chart container animates after the candles appear.
- Evidence
- 1 October capture: the Statuspage embed script (hyperliquid.statuspage.io/embed/script.js) is requested at 0.12 s and again at 0.51 s (0.34 and 0.19 s each), both before the first market request at 0.84 s; a Statuspage document follows at 0.87 s.
- Measured
- one small third-party script requested twice at start-up
- Holds back
- Not established: the captures do not show which panel waits for this.
- Fix
- Load the Statuspage embed once, after trade-ready.
- Where
- The Statuspage embed in the HTML or app shell.
- Verify
- DevTools → Network, filter "statuspage": one script request, after the chart is drawn.
- Likely saving
- Not measured
Grade B: the capture shows the problem directly. Grade C: the order of events in the capture points to it; the dependency is for the team to confirm. The order is our judgement of each finding's effect on trade-ready, largest first; it is not sorted by gap. A gap is the time between two observed events or the time one piece of work takes; gaps overlap and do not add up. Where a finding is about size or count and no time was measured, the row says what was measured instead. Holds back names the panel the finding delays. Nothing here is graded higher, because no fix was confirmed by changing a page and measuring again.
Savings are estimates from the timeline, not measured after a change. They overlap, so they do not add up; the summary gives the combined estimate.
How this was measured
Timings: 5 warm and 5 uncached reloads in a seeded random order across all exchanges, each judged against a checklist frozen for this page before the campaign; trade-ready is the first moment every checklist panel shows real data, nothing is still loading, and the layout holds still for 0.5 s. The findings on this page come from separate recorded loads, which are never part of the timings. Full method.