Performance Optimization Guide

Diagnose a user-facing performance problem, test the responsible layer, and release a measured improvement with correctness, capacity, and recovery gates.

trigger="A user journey misses its response or completion objective, or expected demand exceeds tested capacity." owner="The service owner accountable for the journey's correctness, responsiveness, and operating cost." participants={["Product owner", "Frontend engineer", "Backend engineer", "Database owner", "Operations lead", "Security and data reviewers"]} prerequisites={[ "A named journey, affected users, baseline workload, and measurable acceptance conditions.", "Approved access to field measurements, traces, profiles, and a representative test environment.", "A bounded experiment, production stop conditions, and a compatible recovery path." ]} outputs={[ "A reproducible baseline and a ranked bottleneck hypothesis with supporting evidence.", "A tested change with before-and-after results under comparable conditions.", "A staged release record, regression checks, and a recovery runbook." ]} doneWhen={[ "The target journey improves under the agreed workload without a correctness or access regression.", "Tail behavior, failed requests, resource saturation, and cost remain within accepted limits.", "Representative field evidence supports the change, or its remaining evidence gap is explicitly accepted.", "Operators can disable or recover the optimization without losing accepted work." ]} />

Start with the slow journey

A search screen may load quickly while its first filter interaction freezes. An API can respond quickly at low demand and spend most of its time waiting for a database connection during a burst. These are different problems and need different measurements.

Performance affects user experience, operating cost, and capacity. Set targets from the actual journey and workload rather than borrowing conversion multipliers or vendor benchmarks. This playbook follows one bottleneck from report to release. It does not promise that a particular technique will improve every application.

The product owner names what a user is trying to finish, how delay affects that task, and which users matter to the decision. Include users on constrained devices and networks when they are part of the product's audience.

1. Establish the measurement contract

The service owner defines the operation's start and end, units, observation window, sample count, release version, and workload. Keep successful, failed, cancelled, and timed-out operations distinguishable. A faster successful-request percentile can hide an increase in rejected or timed-out work.

| Evidence | Question it answers | Limitation to record | | --- | --- | --- | | Field browser data | What do participating users experience? | Consent, coverage, browser support, route and device mix | | Controlled browser trace | Which work delayed this load or interaction? | A repeatable lab case is not the entire population | | Server trace and profile | Where did this request wait or consume resources? | Sampling and instrumentation can miss rare failures | | Load test | How does the system behave as demand changes? | Results depend on arrival pattern, data, and dependencies | | Business task outcome | Did the user finish the intended work? | Product changes and traffic mix can confound attribution |

The current Core Web Vitals are LCP, INP, and CLS. FID has been replaced by INP. Google's Web Vitals guidance evaluates the three at the 75th percentile, segmented by mobile and desktop. A Lighthouse navigation run does not measure real-user INP; its Total Blocking Time is a diagnostic proxy. Use field measurement alongside lab investigation.

Choose additional service percentiles from the failure you need to detect and the available sample size. Do not average percentiles from different instances. Retain an aggregatable distribution or analyze comparable cohorts. A thin sample at a high percentile needs an uncertainty note, not a confident success claim.

Gate: another engineer can reproduce the measurement and explain which users it excludes.

2. Reproduce the problem without distorting it

The test owner records device class, browser, region, network conditions, authentication state, data size, and cache state. Capture both cold and warm paths where users encounter both. Do not compare a warm candidate against a cold baseline.

For load testing, specify offered arrival rate as well as completed throughput. A generator that waits for each response can reduce offered load when the service slows, hiding queue buildup. Monitor generator CPU, network capacity, scheduling delays, and dropped iterations so the test client does not become the unreported bottleneck.

Use protected representative data. Disable consequential external effects or use approved test integrations. Confirm that load tests cannot send real notifications, charge accounts, or exhaust shared production quotas. Production testing needs explicit service-owner authorization, a small scope, and stop controls.

Preserve the baseline artifact: trace, profile, query fingerprint, workload configuration, deployment identifier, and raw measurement summary. If the problem cannot be reproduced, gather better evidence before making broad changes.

3. Locate the waiting or work on the critical path

Follow the user operation across browser, network, application, datastore, and external dependencies. Separate queueing from active work. Use correlation identifiers without copying sensitive payloads into telemetry.

A request with parallel calls is not the sum of every child span. Find the dependency that controls completion, then inspect its own waiting and work. Correlated timestamps and span boundaries must be checked before treating a waterfall as a precise accounting ledger.

| Observation | Investigate first | Avoid assuming | | --- | --- | --- | | Delayed visible content | Server response, resource discovery, image transfer, rendering | Every delay is a large JavaScript bundle | | Slow interaction after load | Input delay, handler work, style, layout, paint | A good navigation score proves responsive interactions | | Latency rises with demand | Queues, connection pools, locks, throttling, saturation | More application instances remove the shared limit | | One expensive endpoint | Query count, payload size, serialization, dependencies | Asynchronous syntax removes CPU work or dependency time | | Fast median, poor tail | Cold paths, skew, retries, long queries, noisy neighbors | The average represents affected users | | Fast response, late outcome | Background queue and downstream completion | An accepted request is a completed task |

The Chrome performance tools can connect browser work to a recorded interaction. Match browser evidence with service traces before choosing which layer to change.

4. Choose one bounded optimization

The responsible engineer writes a hypothesis that names the measured cause, proposed change, expected signal, and possible regression. For example, a repeated query within one request may justify batching. A large dependency that is absent from the initial task may justify deferred loading.

"type": "flow", "title": "A performance change must survive the whole evidence chain", "steps": [ ], "caption": "A smaller bundle or faster query is intermediate evidence. Acceptance belongs to the user journey and its operating constraints." }} />

Rank candidates by affected traffic, task impact, implementation risk, and confidence in the cause. A broad rewrite is usually a poor first experiment when a query plan or one rendering trace identifies a narrower issue.

Do not combine a cache change, schema change, and runtime upgrade in one unmeasurable performance release. When several changes are inseparable, record the bundle as the experiment and avoid attributing its outcome to one component.

5. Apply frontend changes with rendering checks

Reduce unnecessary initial work before moving it elsewhere. Evaluate route splitting, deferred nonessential features, dependency removal, and third-party script controls against the recorded journey. Splitting can introduce extra network requests or loading failures, so exercise the first use of each deferred feature.

A task longer than 50 milliseconds meets the browser's long-task definition. That threshold is not a smooth-animation budget. At 60 Hz, a refresh interval is about 16.7 milliseconds, shared with rendering and other browser work. Work below 50 milliseconds can still miss frames. Measure interaction and frame behavior on representative devices. See long-task guidance.

Yielding and workers are candidate techniques, not automatic fixes. Splitting a function does not itself yield execution. Workers add startup, messaging, and data-transfer costs and cannot directly perform main-thread DOM updates. Preserve ordering, cancellation, and error handling when moving work.

For images, test supported encodings, visual quality, transfer size, decoding, and responsive selection. Provide dimensions to reserve layout space. Do not lazy-load a likely LCP image; avoid indiscriminate preloading that competes with more urgent resources. Verify the chosen request in a network trace rather than assuming an attribute had the intended effect.

6. Apply backend and data changes with correctness checks

The backend owner measures query frequency, lock waits, connection wait time, CPU, allocation, serialization, and external calls. Optimize the resource that controls the operation, then repeat the same workload.

Ask the database owner to inspect the engine's query plan and relevant statistics. Execution-based analysis can run the statement and consume resources; use a protected representative environment for effectful or expensive queries. An index can improve reads while adding write work, storage, and maintenance. Test its creation, resulting plans, and write-path impact.

Batching can reduce calls while increasing memory or waiting. A read replica can add capacity but may serve lagging data. Background processing changes completion semantics and requires durable work tracking, duplicate handling, and an observable outcome. None is a transparent substitute for a synchronous correctness requirement.

Changing pool limits can move saturation into the database. Test connection demand across all application replicas, including deployments and failure recovery. Reuse read-replica and caching decision guidance when the measured bottleneck points to either option.

7. Treat caching as a data contract

Before adding a cache, the data and security owners define the key, authorization scope, freshness limit, invalidation behavior, allowed stale use, and miss or outage behavior. Test distinct users and tenants, revoked access, updates, deletes, and cold-cache load.

RFC 9111 distinguishes shared and private caching and defines Cache-Control behavior. In particular, private does not mean “never stored,” and no-cache requires validation rather than prohibiting storage. Use no-store where storage must be prevented, while recognizing that a response directive cannot retroactively erase copies already disclosed or stored.

Long-lived caching is appropriate only when resource identity and update handling make it safe. Keep old content-hashed assets available for compatible clients during a release window. A fresh HTML document pointing at a deleted bundle can break an otherwise successful rollback.

When bypassing a failing cache, protect the origin from a sudden miss surge. Capacity limits, bounded concurrency, and request coalescing need tests alongside hit-rate improvements. A faster response containing the wrong user's data is a release-blocking security incident.

8. Release with stop and recovery gates

The release owner compares baseline and candidate under comparable demand, then exposes a bounded cohort. Check correctness and user completion alongside latency, errors, resource use, and cost. Record cache warmup and cohort differences that affect interpretation.

| Failure | Immediate control | Recovery evidence | | --- | --- | --- | | Faster response changes results | Disable the changed path | Output comparison and corrected regression tests | | Cache leaks or serves invalid data | Disable affected caching and restrict exposure | Scope investigation, safe invalidation, access tests | | Origin overload after cache bypass | Bound traffic or degrade an approved feature | Stable queues and tested cold-cache capacity | | Index or query change harms writes | Stop rollout and follow database-owner procedure | Lock, write, and recovery measurements | | Deferred feature fails to load | Restore compatible assets or feature path | First-use and old-client tests | | Change improves lab only | Pause expansion | Field cohort and instrumentation diagnosis |

Rollback must restore compatible application, configuration, cache, and data behavior. If a change has transformed stored data, a code revert may be insufficient. Use the approved recovery or reconciliation procedure and preserve evidence of affected operations.

9. Keep a reusable experiment record

Journey and accountable owner:
Affected population and business consequence:
Measurement boundaries, units, sample size, and window:
Baseline release, workload, cache state, and environment:
Trace or profile supporting the bottleneck hypothesis:
Change, expected signal, and correctness risks:
Before-and-after distributions, errors, and resource use:
Field cohort, observation plan, and remaining uncertainty:
Stop triggers, recovery steps, and recovery test:
Accepted result, approver, and regression test owner:

"The baseline includes failed and timed-out work, not only successful operations.", "Test clients, environment, cache state, and data are representative and recorded.", "The change addresses a measured cause on the journey's critical path.", "Correctness, authorization, freshness, and completion semantics still pass.", "Tail behavior, load, and dependency failures have been exercised.", "The release has a bounded cohort, stop conditions, and tested recovery.", "Field confirmation or its explicit evidence gap is in the acceptance record." ]} />

10. Establish regression budgets and ownership

A performance budget should protect a user journey or capacity constraint, not an arbitrary score. Define the measurement point, population, percentile or completion condition, environment, sample requirements and owner. Include an error or correctness guardrail so a faster failure cannot pass.

Use separate budgets for development feedback and production acceptance. A synthetic check can detect a large bundle or query regression quickly, while field evidence reveals device, network and workload diversity. Do not compare the two as if they were the same population.

When a budget fails, provide the changed components, evidence window and owner. Allow a time-bounded exception only with the consequence, compensating control and review trigger recorded. Repeated exceptions indicate that the budget, architecture or ownership model needs review.

11. Account for efficiency, cost and displaced work

A lower latency can require more replicas, larger caches or expensive precomputation. A cheaper architecture can increase queue time or on-call burden. Record resource use, data transfer, storage, cache churn and operating effort beside the user outcome.

Measure cost per useful completed operation where the workload permits it. Keep the raw totals visible. A unit-cost improvement may accompany higher total cost because demand increased, while a lower bill may reflect lost traffic or degraded service.

Check where work moved. Client-side deferral may improve initial rendering while making the first interaction slower. A cache can reduce database work while increasing invalidation and security complexity. A batch can reduce request overhead while increasing freshness delay. The optimization decision should include those tradeoffs and the team that will operate them.

12. Run the next-action review

Choose the slowest important journey whose measurement is trustworthy. Produce one trace or profile that supports a bottleneck hypothesis, then select the smallest reversible change that can disprove it. Write the correctness, security, cost and recovery gates before implementation.

After the bounded release, compare the same distributions under comparable demand. Expand only when the measured user or capacity benefit survives field conditions and the operating cost remains acceptable. If evidence is inconclusive, improve the measurement or stop. Do not stack additional optimizations until the current mechanism is understood.

13. Preserve accessibility and product behavior

Performance work must not remove keyboard support, readable focus, semantic structure, error explanation or content required by assistive technology. Test the affected journey with the same accessibility checks used for ordinary release acceptance.

Avoid hiding important content or controls behind interaction solely to improve an initial metric. If loading is deferred, verify the first-use delay, failure message and focus behavior. A fast page that prevents a user from completing the task has failed the performance objective.

Include accessibility tooling and representative assistive-technology checks in the candidate comparison when the interface changes. Record any known coverage limit rather than treating an automated scan as complete evidence. Performance, accessibility and correctness are release conditions for the same user journey, not independent scores that can cancel one another.

Assign each unresolved regression to a named owner and block expansion when it prevents task completion.

Retest the complete journey after the correction.

Retain the result as release evidence.

Limitations and continuing checks

Lab results cannot establish every user's experience. Field coverage can be incomplete, privacy controls can limit detail, and production mixes change. Revisit the workload after material product, dependency, traffic, or data changes.

Set regression budgets from the measured baseline and accepted objectives. Treat noisy results as a reason to investigate, not a reason to remove the check or claim a guaranteed gain. Domain approval and the production release decision remain with the named owners.