Hyperliquid: where its trading screen loses time, and what to fix

Measured from the Netherlands in a logged-in Chrome, October 2026.

In short. On a warm reload the screen is trade-ready after 3.1 s (median of 5 loads), 4 of 27 perpetual trading screens, possible rank 2 to 5; after an uncached reload 3.5 s. The largest bottleneck: All first-party files travel over HTTP/1.1. First change to try: Enable HTTP/2 and HTTP/3 on the CloudFront distributions.

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 reloadmedian 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 reloadmedian 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
Standing4 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 ready5 of 5 warm, 5 of 5 uncached
Notesrecent 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.

0 s1 s2 s3 s
Account panel0.8 s
Order form1.7 s +0.9 s
Price1.9 s +0.2 s
Order book2.2 s +0.3 s
Chart2.5 s +0.3 s
Trade-ready3.1 s +0.6 s settling

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.

HostRoleCDN edge seenConnectResponse
app.hyperliquid.xyzpageCloudFront Amsterdam12 ms8 ms
api.hyperliquid.xyzmarket dataCloudFront Amsterdam12 ms226 ms
api-ui.hyperliquid.xyzmarket dataCloudFront Amsterdam13 ms232 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.

WhenWhat
0.02 sHTML arrives (CloudFront, HTTP/1.1).
0.11–0.49 sEntry 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 sThe 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 sFirst paint.
1.54 sLive-feed handshake completes, 0.7 s after it started; first message at 1.95 s.
1.75–2.14 sThe Privy wallet iframe loads 31 scripts, 0.9 MB compressed and 3.4 MB unpacked.
2.40 sPrice shows; order book at 2.63 s.
2.57 sCandle history is requested (46 KB); it answers at 3.56 s.
3.73 sChart 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.

WhenWhat
0.0 sHTML arrives
1.0 sFirst frame sent on a live feed
1.3 saccount-table ready
1.3 saccount-info ready
1.4 sFirst frame received on a live feed
1.4 sOrder form ready
1.6 sPrice ready
1.9 sOrder book ready
2.6 sChart ready
3.3 sTrade-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

0 s0 s1 s1 s2 s2 s3 s3 s1app.hyperliquid.xyz3 kB345 ms2app.hyperliquid.xyz/index…303 kB359 ms3app.hyperliquid.xyz/index…26 kB358 ms4app.hyperliquid.xyz/src-c…36 kB358 ms5app.hyperliquid.xyz/dist-…896 B359 ms6app.hyperliquid.xyz/hmac-…3 kB359 ms7app.hyperliquid.xyz/clsx.…926 B359 ms8app.hyperliquid.xyz/hooks…7 kB360 ms9app.hyperliquid.xyz/trigg…1 kB358 ms10app.hyperliquid.xyz/esm-B…4 kB360 ms11app.hyperliquid.xyz/const…765 B360 ms12app.hyperliquid.xyz/index…231 kB367 ms13app.hyperliquid.xyz/parse…1 kB361 ms14app.hyperliquid.xyz/custo…716 B362 ms15app.hyperliquid.xyz/dist-…4 kB361 ms16app.hyperliquid.xyz/safe-…20 kB362 ms17app.hyperliquid.xyz/confi…537 kB370 ms18app.hyperliquid.xyz/fallb…2 kB363 ms19app.hyperliquid.xyz/Favor…1 kB363 ms20app.hyperliquid.xyz/CoinS…2 kB362 ms21app.hyperliquid.xyz/Badge…474 B363 ms22app.hyperliquid.xyz/serie…13 kB364 ms23app.hyperliquid.xyz/Acros…5 kB365 ms24app.hyperliquid.xyz/LineC…90 kB368 ms25app.hyperliquid.xyz/Cards…3 kB364 ms26app.hyperliquid.xyz/brows…3 kB365 ms27app.hyperliquid.xyz/index…2 kB367 ms28app.hyperliquid.xyz/provi…2 kB367 ms29dzjnlsk4rxci0.cloudfront.…23 kB617 ms30app.hyperliquid.xyz/Inter…134 kB25 ms31api-ui.hyperliquid.xyz567 B1079 ms32explorer-api.walletconnec…175 kB190 ms33auth.privy.io1 kB381 ms34h20qtjygwppc.statuspage.io5 kB92 ms35api-ui.hyperliquid.xyz564 B757 ms36api-ui.hyperliquid.xyz2 kB1164 ms37api.coingecko.com1 kB426 ms38app.hyperliquid.xyz129 kB16 ms39app.hyperliquid.xyz/dist-…99 kB80 ms40auth.privy.io1 kB703 ms41auth.privy.io2 kB10 ms42auth.privy.io/2275-fab236…106 kB329 ms43auth.privy.io/7969-9e9cae…108 kB351 ms44auth.privy.io/1110-0b7ee6…58 kB387 ms45auth.privy.io/1928-086107…32 kB380 ms46auth.privy.io/5187-0f00d7…75 kB387 ms47auth.privy.io/683-c5ab348…9 kB380 ms48auth.privy.io/3185-1fe723…20 kB380 ms49auth.privy.io/embedded-wa…12 kB386 ms50auth.privy.io/_buildManif…9 kB386 ms51auth.privy.io/_ssgManifes…362 B386 ms52app.hyperliquid.xyz510 ms53api-ui.hyperliquid.xyz47 kB992 ms54api-ui.hyperliquid.xyz564 B848 ms55api.hyperunit.xyz110 B705 ms56api-ui.hyperliquid.xyz566 B740 ms57indexer.api.across.to112 B445 ms58indexer.api.across.to87 B737 ms59api-ui.hyperliquid.xyz509 B735 ms60api-ui.hyperliquid.xyz507 B738 ms61rpc.hyperliquid.xyz554 B727 ms62rpc.hyperliquid.xyz10 kB772 ms63rpc.hyperliquid.xyz10 kB854 ms64rpc.hyperliquid.xyz10 kB763 ms65rpc.hyperliquid.xyz10 kB769 ms66rpc.hyperliquid.xyz10 kB851 ms67rpc.hyperliquid.xyz10 kB852 ms68rpc.hyperliquid.xyz2 kB1022 ms69arb1.arbitrum.io142 B614 ms70app.hyperliquid.xyz/Inter…144 kB42 msprice 2.4 sorder book 2.6 schart 3.7 s
Download this figure as an image:

Bottlenecks and fixes, largest firstdiagnostic capture 1 October, uncached

HL-1All first-party files travel over HTTP/1.1.grade B
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.
HL-2Candle history is requested late, just before the order book shows.grade C
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.
HL-3The wallet stack loads before the market is on screen.grade C
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.
HL-4The live feed needs 0.7 s to connect.grade C
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.
HL-5The app files have no cache-control header, and a warm reload re-checks 158 of 194 responses.grade B
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
HL-6The chart is still animating 0.6 s after it has its data.grade B
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.
HL-7The status-page script is loaded twice in the first 0.5 s.grade B
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.