
A professional cyclist preparing for a time trial is not told simply to pedal harder.
At elite level, performance comes from understanding where time is being lost. Engineers measure aerodynamic drag, rolling resistance, equipment choices and riding position. Coaches study pacing and power output. A change that feels faster is not automatically accepted; it is measured against the clock, and improvements in one area are weighed against what they might cost somewhere else.
Application performance optimization works much the same way.
When an application feels slow, the instinctive response is often to start changing things: add servers, introduce caching, rewrite a query, reduce JavaScript or replace part of the architecture. Any of those changes might help, but without evidence they are guesses.
Application performance optimization is the systematic process of measuring how an application behaves, locating the constraints that matter to users, making targeted improvements, and verifying that those changes improve real performance without creating unacceptable trade-offs elsewhere.
AWS's Performance Efficiency guidance makes the same principle explicit: performance decisions should be data-driven, architecture choices should be reviewed regularly, and monitoring should reveal when behaviour moves away from expected performance.
For Levelworks, this is the practical meaning of Performant App Health. Performance is not something an application achieves once at launch. Users increase, datasets grow, dependencies change, browsers and devices evolve, and new features add work to previously fast workflows. Optimization therefore needs to become a repeatable engineering process rather than an occasional emergency response.
Teams commonly begin performance work by opening an infrastructure dashboard.
CPU is at 72%. Memory looks healthy. Database utilization seems acceptable.
None of those numbers tells you whether a customer waits six seconds to complete checkout.
Start instead with a specific user or business workflow:
Then define what is slow about it.
For a web page, that could involve loading, responsiveness or visual stability. Google's Core Web Vitals currently measure those dimensions through Largest Contentful Paint (LCP), Interaction to Next Paint (INP) and Cumulative Layout Shift (CLS), and Google recommends evaluating them at the 75th percentile rather than treating the fastest or average experience as representative.
For a backend workflow, the relevant measurements may include request latency, throughput, queue time or completion time.
A useful performance statement looks like:
For customers with more than 10,000 records, the dashboard's p95 response time has increased from 1.2 seconds to 4.6 seconds.
That gives engineering a target.
"Make the application faster" does not.
[Internal Link: “Why Is My App Slow? 10 Common Causes of Poor Application Performance”]
Performance optimization needs a before-and-after comparison.
Without a baseline, a change can feel faster without producing a meaningful improvement, or improve a laboratory benchmark while making little difference to actual users.
Record the current behaviour of the workflow you are optimizing.
Depending on the application, the baseline might include:
Area
Useful measurements
User experience
page load, interaction latency, workflow completion
API
p50, p95 and p99 response time
Application
CPU time, memory, worker utilization
Database
query duration, waits, connections, rows scanned
Dependencies
downstream request latency and error rate
Network
request count, payload size, transfer time
Capacity
throughput, queue depth, saturation
Capture traffic or dataset conditions too.
A response time measured with ten test users cannot be compared meaningfully with production under 5,000 concurrent sessions unless that difference is understood.
The baseline also protects against accidental trade-offs. A change might improve response time while doubling infrastructure cost or increasing error rates. Optimization should consider the whole outcome, not one attractive number.
Average response time can hide the users having the worst experience.
Imagine 95 requests complete in 300 milliseconds while five take seven seconds. The overall average may still appear acceptable even though one customer in twenty experiences severe delay.
Google's SRE guidance recommends percentile measurements such as p50, p95 and p99 because they expose the tail of the latency distribution that averages conceal.
A useful interpretation is:
Do not automatically optimize p99 at any cost. Very rare cases can have unusual causes and may be expensive to eliminate.
But if the average remains stable while p95 steadily worsens, users are already experiencing a performance problem that the headline metric hides.
Segment performance further where useful by customer size, geography, device type, endpoint or application version. The overall application may look fast while one valuable customer segment experiences very different behaviour.
Once the slow workflow is defined, follow the time.
Suppose an API request takes 2.8 seconds.
The important question is where those 2.8 seconds go.
A trace might reveal:
Request handling 90 ms
Authentication 60 ms
Database query 1,850 ms
External API 620 ms
Serialization 80 ms
Other 100 ms
Optimizing the application controller from 90 ms to 40 ms would technically make the code twice as fast.
The user would barely notice.
The database and external API dominate the latency.
This is why optimization should usually begin with profiling and tracing rather than rewriting code based on intuition.
For browser performance, Chrome's current DevTools Performance tooling allows developers to record and inspect performance traces, analyze runtime work and investigate Core Web Vitals.
On the backend, distributed traces, application profilers, query analysis and infrastructure metrics can reveal whether time is spent computing, waiting, querying or communicating.
The general rule is simple:
Optimize the constraint, not the component that is easiest to edit.
One of the highest-value performance techniques is elimination.
Before asking how to execute an operation faster, ask whether the operation needs to happen at all.
Common examples include:
Imagine a dashboard retrieves 50 fields for each customer but displays only eight.
The first optimization may not require a faster database server. It may simply be retrieving less information.
This principle applies throughout the application stack:
Less work → fewer resources → less latency → more capacity.
It is often safer and more durable than making an unnecessary operation marginally faster.
Most user actions contain a chain of work that must complete before the application can respond.
That chain is the critical path.
Consider checkout:
Validate cart
↓
Calculate price
↓
Check inventory
↓
Authorize payment
↓
Create order
↓
Send email
↓
Update analytics
Do email delivery and analytics really need to finish before the customer sees order confirmation?
Perhaps not.
If they can safely happen afterwards, removing them from the synchronous path reduces the number of operations that determine checkout latency.
Do this carefully. Moving work asynchronously changes failure behaviour and consistency assumptions, so it is not simply a performance trick.
The useful question is:
What absolutely must succeed before this user can safely receive a response?
Anything outside that requirement deserves scrutiny.
Database optimization deserves special attention because growing data can turn previously insignificant queries into dominant sources of latency.
Typical areas include:
Do not begin by adding indexes indiscriminately.
Inspect how the database actually executes the slow query.
PostgreSQL's current performance documentation, for example, recommends using EXPLAIN and EXPLAIN ANALYZE to inspect execution plans and understand whether queries perform sequential scans, index scans, joins and other operations as expected.
An application-level trace may tell you that the database consumes 70% of request latency.
The query plan helps explain why.
Optimize the particular data access responsible for the delay, then measure again.
[Internal Link: “How Database Performance Affects the Speed of Your App”]
Latency accumulates each time a workflow crosses a network boundary.
An application can therefore become slow without containing any individually slow service.
Suppose a page sequentially requests:
The individual services may all look healthy, yet their combined critical path creates a noticeable delay.
Look for opportunities to:
Parallelization should not become automatic either. Ten simultaneous calls can overload downstream resources or create contention.
The objective is not simply fewer milliseconds inside each service.
It is a shorter and more efficient path from user action to useful response.
Caching can provide dramatic improvements when many requests repeatedly retrieve or calculate the same information.
Useful candidates can include:
But caching introduces freshness, invalidation and consistency questions.
Before adding a cache, ask:
AWS explicitly lists caching as one possible architectural trade-off for improving performance, but performance guidance more broadly emphasizes using evidence and workload characteristics to choose the appropriate mechanism rather than treating any technique as universally beneficial.
A cache with poor hit rates, expensive invalidation or dangerous stale data can add complexity without solving the underlying problem.
A backend can respond in 100 milliseconds while the application still feels slow.
Web users may be waiting for:
This is where user-centric metrics are more valuable than server response time alone.
Google's Web Vitals documentation explicitly distinguishes laboratory and field measurement. Laboratory testing is useful during development, but field data captures the diversity of real devices, networks and user interactions that cannot be recreated completely in a controlled environment.
If poor responsiveness is the issue, investigate main-thread work. Google's performance guidance notes that long JavaScript tasks can block user input and recommends reducing or breaking up expensive work so the browser can respond between tasks.
Do not reduce this to "make the JavaScript bundle smaller." Sometimes bundle size is the problem; sometimes runtime execution, rendering or third-party code dominates instead.
Measure first.
[Internal Link: “How to Improve Web App Performance Without Rebuilding Your Application”]
A third-party service can dominate application latency even when your own infrastructure is performing well.
Measure downstream calls separately.
For important external dependencies, understand:
You may not be able to make the provider faster.
You may still be able to redesign how much of the user's workflow waits for it.
For example, a payment authorization must usually stay on the checkout path.
An analytics event usually does not.
Optimization frequently means making better architectural decisions around latency you do not control.
Adding infrastructure is sometimes exactly the correct performance optimization.
If application instances reach safe capacity during demand peaks and work parallelizes effectively, additional capacity may reduce latency immediately.
But scaling does not repair every performance problem.
More application servers will not necessarily solve:
AWS's Performance Efficiency pillar defines performance partly as using resources efficiently while demand changes, which means scaling and efficiency belong together rather than being competing goals.
Before scaling, identify the constrained resource.
If doubling application servers leaves the database bottleneck unchanged, you may simply send requests toward the bottleneck faster.
An optimization that works for one request may fail once thousands arrive concurrently.
This is why load testing should be part of performance optimization when capacity or concurrency matters.
AWS includes load testing as a specific practice in its performance-efficiency process guidance.
A useful load test should reproduce relevant characteristics of production:
Do not reduce load testing to asking:
How many requests can the system process before it crashes?
The more useful questions are:
That reveals the application's operating envelope rather than one impressive maximum-throughput number.
A laboratory benchmark can prove that an optimization works under controlled conditions.
It cannot prove that every user benefits.
A frontend optimization may dramatically improve a high-end developer laptop while making little difference on budget mobile devices.
A backend improvement may help typical accounts but leave large enterprise customers slow.
Compare production behaviour after the change with the original baseline.
For web applications, field measurement is particularly important because network quality, hardware and user interaction substantially affect perceived performance. Google's Web Vitals guidance explicitly states that laboratory testing is not a substitute for field measurement.
Segment the result where necessary.
An optimization that improves p50 by 20% but leaves p95 unchanged may still require more work if the original problem was tail latency.
Optimization becomes easier to maintain when teams define boundaries around acceptable performance.
A performance budget might state that:
These are not universal numbers.
They should reflect user and business expectations.
Budgets help because performance regressions are often incremental. A feature adds 100 ms, another introduces another database call, and a third increases the page bundle slightly.
No individual release feels catastrophic.
Six months later, the application is noticeably slower.
A budget creates a point at which teams have to investigate the accumulating cost rather than discovering it through customer complaints.
Performance work should not live entirely in periodic optimization projects.
Changes likely to affect performance deserve appropriate measurement during delivery.
That may include:
Do not try to run expensive production-scale performance tests on every tiny commit.
Use proportional testing.
The goal is to identify meaningful regression close enough to the change that engineers can still understand why it happened.
This turns performance from an occasional firefight into an engineering constraint that can be managed continuously.
Performance engineering has opportunity cost.
Reducing an internal process from 20 ms to 10 ms sounds like a 50% improvement, but it may be irrelevant if users spend three seconds waiting elsewhere.
Prioritize using a combination of:
User impact: How noticeable is the delay?
Frequency: How often does the workflow occur?
Business importance: How important is the workflow?
Optimization potential: How much latency can realistically be removed?
Cost and risk: How difficult is the change?
A simple prioritization table can help:
Candidate
User impact
Frequency
Likely gain
Priority
Checkout query
High
High
1.4 s
Very high
Admin report
Medium
Low
8 s
Medium
Internal API helper
None directly
High
5 ms
Low
Homepage JavaScript
High
Very high
400 ms
High
This keeps performance work aligned with outcomes rather than engineering curiosity.
Every optimization has trade-offs.
Caching may improve latency while increasing staleness.
Concurrency may reduce response time while increasing load on dependencies.
Compression can reduce network transfer while consuming CPU.
Denormalizing data can accelerate reads while making writes and consistency harder.
Larger instances can solve immediate saturation while increasing cost.
AWS's guidance explicitly emphasizes architectural trade-offs when improving performance rather than assuming optimization is free.
After every meaningful optimization, recheck:
The fastest possible application is not the goal.
The goal is performance that meets requirements without creating unacceptable problems elsewhere.
For most performance work, the following sequence is more useful than jumping directly to a particular technique:
Define where users or systems experience unacceptable delay.
Measure the current latency, throughput and relevant resource conditions.
Determine whether it varies by account, endpoint, region, device, dataset or load.
Separate frontend, network, application, database and dependency latency.
Do not optimize several layers simultaneously unless evidence justifies it.
Remove unnecessary work before adding architectural complexity.
Verify performance with realistic data and, where relevant, realistic concurrency.
Measure the actual improvement and any new trade-offs.
Observe the change in production and confirm that real users benefit.
Add monitoring, tests or budgets that make future regression visible.
This creates an optimization loop:
Measure → locate → change → validate → observe → repeat
That loop matters more than any particular tool.
Applications rarely become slow all at once.
Data accumulates. Features add requests. Dependencies become more important. Customer accounts grow. Traffic patterns change, while small increases in frontend and backend work accumulate release after release.
That is why Levelworks treats Performant as an App Health condition rather than a launch benchmark.
It is closely supported by Observable, because teams need evidence about where latency comes from; by Tested, because optimizations and regressions need verification; and by Scalable, because performance under increasing demand eventually becomes a capacity question.
A practical performance optimization process does not begin by adding a cache, increasing server size or rewriting the slowest-looking function.
It begins by establishing what users are waiting for, measuring where that time is actually spent and changing the part of the system capable of producing a meaningful improvement.
The best performance work is therefore not the optimization with the cleverest implementation.
It is the one where the team can say, with evidence:
This was the constraint. This is what we changed. This is how much faster the important workflow became. And this is how we will know if it starts getting slower again.