Skip to content
Illustration of a fictional parts shop, separating its public catalog, transaction ledger, and queued work.

A Faster Website Without Overspending, Episode 2: Do Less Work Before Scaling

Reduce browser work, oversized images, font cost, and repeated responses while separating public caches from account-specific prices.
October 18, 2026 by
Tomz

The cover illustrates a fictional store, not a deployed system or real test result.

A full-size parts photo is sent to every phone, several scripts run before the customer searches, and the same product page keeps asking the database for identical information. At the fictional Ready Parts store, I would cut this work before buying more capacity. Work we avoid saves customers time and reduces system load, but we must separate reusable data from data that needs to be fresh and access-controlled.

This episode follows the measurement work in Episode 1. The store’s numbers and events remain hypothetical. The goal is to decide what belongs in the browser, what can be prepared ahead of time, and what can be reused. Installing a CDN does not automatically make every part of a website fast and safe.

Separate network waiting from work on the customer’s device

If the server responds quickly but the page still reacts slowly, the problem may be JavaScript that a phone must download, parse, and run, or repeated layout work. Reducing API latency alone may not change when someone can actually tap. Begin with important journeys and measurements from devices like customers’ devices, not only a developer’s computer.

Browser work includes receiving data, building the page structure, calculating styles, laying out elements, and drawing pixels. A long task blocking the main thread makes taps wait. Hiding a button or showing a spinner does not make the journey faster. Remove unnecessary code, load it where needed, and keep a pile of marketing tools from interfering with the purchase path.

With SSR (server-side rendering) the server builds HTML, so users can often see content before every part of the JavaScript has loaded. But rendering still costs work, and the page may need hydration to restore interactions. Client-side rendering (CSR) can suit some apps, but moves work to the customer’s device. Choose by task and data, not by a framework’s popularity.

Public content that changes infrequently can sometimes be generated in advance as static HTML, reducing per-request rendering. Account-specific data still needs an authorized route. Prebuilt pages also need a publication process for updates and must not accidentally embed one customer’s contract price in a page anyone can read.

Streaming can send part of a page before everything is complete, but it does not erase the remaining work. Attaching JavaScript only to interactive regions, or partial hydration, can reduce browser work in some designs, but adds complexity around boundaries and state transfer. Use it when measured benefits for that page justify maintenance.

Receive

Choose only needed files and bytes

Build

Lay out and paint without jumping

Respond

Do not let long tasks block interaction

The figure shows tasks to examine together, not evidence that SSR or any framework is always fastest.

Send images sized for their actual use

A product image shown a few hundred pixels wide need not download the full original every time. Generate useful sizes, choose formats for the content, and use responsive images so the browser can select the right file. Specify width and height or aspect ratio to reserve space and reduce text jumps during loading.

The main image near the top should not be delayed in the same way as an image near the end. Lazy-loading the main image without checking can worsen LCP. Offscreen images can be loaded lazily when appropriate. Do not preload everything: those files can compete for bandwidth with the most important work.

Thai fonts must remain readable, with vowel and tone marks intact. Choose only the families and weights used, inspect rendering before and after the font loads, and beware of font subsets that omit Thai characters. Compression that breaks text, or replacing a font the owner has approved, is not a successful speed improvement. Measure readability as well.

A cache reuses an earlier answer under defined conditions

Browser and shared CDN caches can avoid repeating transfers or processing. A CDN distributes content to service points closer to users in many places, but the effect depends on geography, networks, data type, and the cache-hit rate. A miss goes to another cache layer or the origin according to the configuration.

The first cache questions are who may reuse an answer and how stale it may be. Public images and a customer’s special price do not share the same answer even on one domain. Setting a cache lifetime before answering the access question can trade speed for a data leak.

Ready Parts might cache versioned images for a long time, while product descriptions need a version change or expiration plan. Contract prices and each account’s cart need routes and policies that enforce authorization. A cookie in a request does not mean a shared cache automatically knows not to store its response.

How the fictional store might classify data, not a ready-made configuration
DataWho may share itDecide before caching
Versioned product imageAnyone allowed to see the public productReal versioned URL, file size, and removal of old files
Product descriptionBy language and publication statusFreshness, edits, and preventing draft leaks
Account priceOnly people authorized under the termsPrevent shared-cache cross-account leakage and test after switching accounts
Order confirmationBy the order’s ownerAuthorize and verify the transaction, not reuse an old answer in place of recording it

Set Cache-Control to match its meaning

Under the HTTP standard, no-cache does not forbid storage: a stored response must be validated with the origin before reuse. No-store directs caches not to store the request or response as specified, while private prevents shared caches from storing that response. Choose for the data sensitivity and desired behavior, then test the actual proxy and CDN configuration.

A cache key distinguishes answers using information such as URL, parameters, and headers that affect the content. If the answer varies by language but the key does not, someone may receive the wrong language. If it varies by access rights but shares a key, the harm can be greater. Putting every header into the key can fragment the cache without proving correctness.

Use Vary for headers that actually change the response, and check the rules of the specific system. For personal data, authorization belongs in the access-control system, not in a secret URL or a hope that a cache will never cross users. Caching helps performance; it does not replace authorization.

Shareable

Public images and content with a defined freshness policy

Access-controlled

Account prices, carts, and orders

A shared cache should hold only answers approved for sharing. A cookie alone does not prove the privacy settings are right.
A fictional customer views a public parts catalog at a counter, separate from a staff desk with account records
Concept illustration: public reads may be shared under a policy, while account data still requires authorization. This is not a deployed system.

A high hit rate does not mean the origin can never fail

Suppose 1,000 public-product read requests arrive in the same period and the cache answers 900. The origin might see 100 requests of that type, but those figures do not include orders, cache bypasses, or subrequests needed to build an answer. They describe only this hypothetical boundary; they do not prove the whole site has ten times the capacity.

When many entries expire together or a new product becomes popular, a surge may reach the origin at once. Plan to coalesce identical requests, stagger expirations, and serve preapproved stale content where allowed. A contract price or stock status at order confirmation may not permit the same exception as a public article.

Track hit ratio, actual origin work, miss latency, and correctness after updates. Test a cold cache, not only an already warmed system. If purging is needed, set an owner and scope. Repeated whole-cache purges can create a new load, and cannot recall every copy already downloaded elsewhere.

Remove work that does not help a customer decide

A product page should not fetch an entire order history merely to show whether there was a recent order. Fetch only what the page displays, paginate, and bound the result count. The browser should not send a search on every keystroke without pacing. An old response can arrive late and overwrite a newer result, so cancel or version requests as the journey requires.

Pagination does not solve the problem if customers must click dozens of times to finish one task. Review search and filters alongside payload size. The aim is to finish the job with reasonable effort and time, not save bytes on one request while causing more requests and a higher total cost.

Inspect what is actually sent, not what the URL says

An image URL labeled “small” does not prove the file is smaller. Check pixel dimensions, bytes, and the file the browser actually chooses. If several URLs serve the same original, a polished srcset still does not help. Compression can reduce transferred bytes, but it does not remove all image decoding, script parsing, or layout work.

HTTP/2 and HTTP/3 improve transport and stream handling at the protocol level, but origin and client-device work remain. If an API waits several seconds for a query, changing the protocol alone will not erase that time. Check the connection and network actually in use before attributing a result, and avoid changing several layers in one round.

Acceptance checks should include the image selected on a narrow screen, the main image not delayed by lazy loading, complete Thai font rendering, and content after a language or account switch, as well as cold-cache and miss paths. Once each part passes, measure the whole page again: fixing one asset may make another the new longest wait.

Actual file

Bytes, pixels, and format

Actual device

Browser-selected file and processing

Actual reading

Clear image, complete font, and correctly authorized data

Check transfer, processing, and the reader’s result. A compression command or URL parameter is not proof of improvement.

I would accept a change when the same journey is faster on representative devices, data is properly authorized and fresh under its rules, and the origin truly does less work. That becomes the new baseline for testing additional servers in the next episode.

This round’s handoff should list removed assets, cache policy by data type, how edits retire stale copies, and account-switch tests that show no cross-account data. Tools can find large files, but the team must decide which answers can safely be shared.

Read the sources and limits of the example

The following sources explain the concepts and limitations and were checked on October 18, 2026. The fictional store numbers and decision suggestions are my synthesis, not provider prices, test results, or guarantees. Before applying them, check the current version, plan, and terms.

Share this article

FacebookX
Illustration of a fictional parts shop, separating its public catalog, transaction ledger, and queued work.
A Faster Website Without Overspending, Episode 1: What to Measure Before Adding Servers
Separate user counts, RPS, concurrency, and completed transactions to set verifiable speed targets and find the real bottleneck.