- Evidence
- 1 October capture: 2.4 s of main-thread work starts in react-router-BGcoL_jj.js, one of the two largest such figures in this test; it counts everything that script sets off, not only router code. 22 long tasks add up to 3.1 s before trade-ready. The logged-out follow-up recordings name one concrete part: a function (pt) in the react-router chunk forces layout recalculations of 44 and 38 ms in one recording and 48 ms in the other, and the chart's bottom toolbar another 29 ms.
- Gap observed
- 2.4 s of main-thread work that starts in the react-router chunk
- Holds back
- Not established: the captures do not show which panel waits for this.
- Fix
- Record a start-up profile and find what runs from the react-router chunk (route modules imported at start-up are the first thing to check); split it by route. Batch the element-size reads in the function the profile labels pt.
- Where
- Router configuration and lazy routes.
- Verify
- DevTools → Performance → Bottom-up: react-router-*.js time.
TxFlow: 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 4.3 s, range 4.1 s–4.5 s; loads: 4.1 s, 4.3 s, 4.4 s, 4.5 s, 4.1 s |
| Uncached reload | median 4.7 s, range 4.5 s–5.2 s; loads: 5.2 s, 4.7 s, 4.8 s, 4.5 s, 4.7 s |
| Standing | 12 of 27 by median; possible rank 10 to 15. 1.9 s behind the fastest, Thalex (2.4 s): 1.8 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 with React Router, built with Vite; TradingView chart library plus ECharts; web3 and ethers bundles; Privy and WalletConnect; Sentry.
Delivery
app.txflow.com through Cloudflare over HTTP/3; HTML no-cache; app files cached a year; market data and feed from api.txflow.com.
| Host | Role | CDN edge seen | Connect | Response |
|---|---|---|---|---|
| app.txflow.com | page | Cloudflare Amsterdam | 13 ms | 363 ms |
| api.txflow.com | market data | Cloudflare Amsterdam | 13 ms | 254 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.28 s | HTML arrives. |
| 0.47–0.79 s | web3 (0.8 MB compressed, 2.8 MB unpacked), index (1.2 MB unpacked) and ethers. The react-router chunk later starts 2.4 s of main-thread work. |
| 0.99 s | The market socket opens; handshake at 1.90 s, 0.9 s later; first message at 2.43 s. |
| 1.32–1.63 s | Trade, PositionsModule and ECharts chunks. |
| 1.58–3.50 s | An api.txflow.com request takes 1.9 s. |
| 1.61 s | First paint. |
| 2.41 s | Page header shows the market; order book at 2.65 s. |
| 2.53–3.20 s | The chart library (library.js, 0.9 MB compressed, 6.2 MB unpacked); Privy loads 35 requests from 2.71 s. |
| 3.46–4.36 s | trading.js (0.5 MB unpacked). |
| 4.36 s | Price shows, 1.7 s after the book. |
| 6.80 s | Chart drawn, 2.4 s after the price: trade-ready in this load. 22 long tasks took 3.1 s of main thread. |
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.
Not recorded: an unidentified pop-up covered the chart in both recorded loads (it did not appear during the timed campaign).
Request waterfalldiagnostic capture 1 October, uncached
72 of the 348 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 requestwaiting for the serverdownloading
Bottlenecks and fixes, largest firstdiagnostic capture 1 October, uncached
- Evidence
- 1 October capture: chart 2.4 s after the price. library.js is 6.2 MB unpacked; trading.js loads after it; 31 Privy scripts and WalletConnect's 1.2 MB wallet list load in the same window, and the follow-up recordings show Privy's module set-up taking about 100 ms of main thread inside a 250 ms task at 3.5 s, before the price; ECharts is a second chart library on the page. In the warm campaign loads the chart is not the last panel (TX-5).
- Gap observed
- 2.44 s between the price and the chart
- Holds back
- Chart (median 3.4 s in the timed loads).
- Fix
- Preload library.js and trading.js with the trade route; drop ECharts from the trade page if TradingView draws the chart; load Privy after the chart.
- Where
- Trade route entry; wallet provider.
- Verify
- DevTools → Network: library.js starts before 1.5 s; no privy request before the chart paint.
- Evidence
- 1 October capture: first feed message at 2.43 s, book at 2.65 s, price only at 4.36 s, after a 1.9 s api.txflow.com request (1.57–3.50 s). In 10 older timed loads the price and the book show together; in a second set of 10, four loads repeat the gap (0.35 to 0.92 s). So it comes and goes.
- Gap observed
- 1.71 s between the order book and the price
- Holds back
- Price (median 3.4 s in the timed loads).
- Fix
- Reproduce the case first; if the price waits for a REST call, render it from the feed's first ticker message.
- Where
- Price component data source.
- Verify
- DevTools → Performance: price paint within 200 ms of the first ticker message.
- Evidence
- An unidentified pop-up covered the chart in both diagnostic loads; it did not appear in the timed campaign.
- Measured
- a chart-covering pop-up in both 3 October diagnostic loads
- Holds back
- Chart (median 3.4 s in the timed loads).
- Fix
- Find what puts a layer over the chart on a logged-in load and show it after the trading screen is ready, away from the chart.
- Where
- Whatever opens the overlay (it was not identified; two logged-out recordings did not show it).
- Verify
- Reload: no overlay on the chart during the first seconds.
- Evidence
- Warm campaign loads: the order form and the positions panel are last in 3 of 5 loads and tied with the others in 2; the chart is never last alone. The page's main parts are in place at a median 3.4 s, the last panel at 4.3 s and trade-ready at 4.3 s: once the last panel is ready, trade-ready follows at once in 4 of 5 loads. In the 0.9 s in between, the order form fails its check or still shows a placeholder, the positions panel likewise, and the chart is still animating.
- Gap observed
- 0.92 s median between the main parts being in place and trade-ready in the five warm loads; no wait after the last panel
- Holds back
- The order form and positions panel (last panel median 4.3 s in the timed loads).
- Fix
- Find what the order form and positions panel wait for after the market panels are shown (account or wallet state), and end the chart's loading animation when its data is in.
- Where
- Order-form and positions components; the chart panel's loading states.
- Verify
- DevTools → Performance: the order form and positions fill within 0.3 s of the order book; nothing in the chart animates after the candles appear.
- Likely saving
- Up to ~0.9 s on trade-ready
- Evidence
- The 5 older warm timed loads contain 47 or 48 requests to the same /info address each; in one, two of them take 1.0 and 1.3 s and end just before price and book show at 3.88 s. A logged-out follow-up recording shows 23 /info calls with 19 OPTIONS requests (CORS preflights) for that address in the first burst, and /info calls that take over 2 s (1.86–4.09 s). The page is on app.txflow.com and the API on api.txflow.com, so the browser asks permission before the calls. The request bodies are not recorded, so the calls may ask for different things.
- Measured
- 47 requests to one endpoint per load; 19 permission requests for it in the follow-up recording
- Holds back
- Not established: the captures do not show which panel waits for this.
- Fix
- Combine the start-up /info calls into a few, and send Access-Control-Max-Age: 7200 on api.txflow.com so the browser remembers the permission, or serve the API under app.txflow.com.
- Where
- The API client for /info (batching); CORS response headers of api.txflow.com.
- Verify
- DevTools → Network, filter "info": under 10 requests before the price shows; filter "method:OPTIONS": none on a reload.
- Likely saving
- Unknown: the slowest /info calls end just before the price shows
- Evidence
- Both logged-out follow-up recordings: the second socket to api.txflow.com completes its handshake at 3.78 s (3.80 s in the other) but sends its first frame only at 5.13 s (5.18 s), 1.35 to 1.38 s later, and receives its first at 5.39 s (5.45 s). The frames are not recorded, so it is not known whether this socket carries the market subscription.
- Gap observed
- 1.35 to 1.38 s between the second socket connecting and its first sent frame, in two recordings
- Holds back
- Not established: the captures do not show which panel waits for this.
- Fix
- Find what the second socket waits for before subscribing; if it carries market data, subscribe as soon as it connects, otherwise open it later.
- Where
- Feed client: the consumer of the second api.txflow.com socket.
- Verify
- DevTools → Network → WS: the first frame on each socket is sent within 100 ms of the handshake.
- Likely saving
- Up to ~1.3 s if a trading panel waits for this socket; unknown otherwise
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.