Server optimization: measure first, change second
An internal response around 3 ms does not explain a user's full wait. Separate processing, network time and asset loading before upgrading a server.

“How do we make the website faster?” is often answered before anyone measures it. Teams add CPU or RAM, then discover that the page still feels slow.
This article follows the measurements recorded in our project draft, explains what they suggest, and identifies what they cannot establish.
The system described
The original draft dates these observations to 18 October 2026. The underlying logs are not available in this folder for independent verification. These are observations from one configuration, not a representative benchmark; repeat them under realistic load.
A VPS with four CPU cores and 2.9 GB of RAM in Vietnam.
A Node server-rendered public site, static admin interface, Go API and PostgreSQL 16.
Another company's application sharing the same server.
Step 1: measure internally
A slow page can combine application work, network time, CDN behavior and large assets. Start by separating them.
A loopback request removes the external network from the measurement. The draft records:
Internal SSR: 3.1 ms 3.3 ms 2.9 ms
Internal /members API: 5.1 ms
Internal /menus API: 4.3 ms
Internal /settings: 3.7 ms
Load average: 0.06
Free RAM: 1.9 GBThese samples show no obvious server bottleneck at that moment. A load average of 0.06 does not mean the CPU is idle 99% of the time. Check CPU, I/O, memory, concurrency and p95/p99 latency under load before drawing a capacity conclusion.
Even a short internal measurement is valuable because it tells you where to investigate next.
Step 2: measure from the user's location
From a user machine in Vietnam, direct connection:
TLS handshake: 0.06–0.08 s
TTFB: 0.08–0.10 s
Total: 0.10–0.13 sDo not subtract an internal response time from an external total and call the remainder “network delay.” Use the same URL and content. Separate DNS, TCP, TLS, TTFB and body download; repeat measurements while controlling cache state and connection reuse. Also record whether a timing is an individual phase or a cumulative timestamp.
Step 3: weigh the page's assets
The draft's largest opportunities were outside application processing:
Asset | Original | Compressed or converted |
|---|---|---|
| 482 KB | 152 KB |
| 318 KB | Not recorded |
CSS | 135 KB | 30 KB |
One profile image | 697 KB | 516 KB, WebP |
| 140 KB | Not recorded |
| 49 KB | Not recorded |
18 font files | 290 KB | Not recorded |
That profile image is larger than the compressed entry-client.js file. The table does not establish the total size of all compressed JavaScript. Even so, 516 KB deserves attention for an image displayed about 320 pixels wide.
The draft also reports that adding ?w=320 still returned the original image. A resizing parameter is useful only if the server actually implements it.
A reasonable investigation order is images, compression, static asset caching, JavaScript, then hardware when CPU, memory or I/O measurements justify it. Let your actual page data change that order when necessary.
Step 4: verify compression on the response
An nginx configuration containing gzip on; is not proof that every intended asset is compressed. The gzip module supports text/html; CSS and JavaScript need appropriate MIME types in gzip_types.
Ask for a compressed response and inspect the transferred size:
curl -s -o /dev/null --compressed -w '%{size_download}' https://your-domain/Check Content-Encoding too, and compare the same response without compression. A smaller body alone does not identify the algorithm. The draft records roughly 91 KB of HTML and about 21 KB transferred, but no original header is available here to verify its earlier attribution to zstd.
Step 5: avoid a convenient but misleading test
The first CDN test in the draft ran from the origin server itself. It recorded 348–838 ms, but followed origin → internet → CDN → origin: a route different from a real user's request.
A later client-side test recorded 0.31–0.49 seconds. However, the direct and CDN routes then tested different applications. Their difference cannot quantify the CDN's overhead.
Measure where users are, and compare like with like.
Step 6: use a control measurement
The project account describes certificate issuance failing with a connection reset. Packet capture reportedly showed no incoming SYN on port 80 from an overseas network, while a domestic connection reached the server normally.
That comparison helps locate a possible routing or filtering problem before the server. It does not by itself prove the hosting provider intentionally blocked the port.
The useful lesson is broader: a measurement that finds nothing needs a control that finds something. Otherwise you cannot distinguish absence of traffic from a faulty capture or test setup.
A practical sequence
Measure loopback responses.
Measure from real user locations.
Sort assets by transferred size.
Check compression headers and bytes.
Inspect edge cache status.
Evaluate hardware when the evidence points there.
Figures are retained from the Zukatek draft for October 2026 and have not been independently reproduced in this review. Keep the method, and save the logs of your own measurements.
Reference: nginx gzip module.


