Skip to content

Profiling and Application Performance ​

Performance optimization reduces a measured bottleneck against user impact and capacity goals. Without profiling, adding cache, threads, or instances can hide symptoms while increasing cost.

Quick Decision ​

SymptomMeasure firstTypical intervention
High CPUCPU profile, allocations, serializationAlgorithm, batching, threads, payload
Growing memoryHeap/live objects, GC, allocation profileLifecycle, bounded cache, leak
Slow APITrace, DB plan, downstream latencyQuery/index, parallelism, timeout
Low throughputQueue, pool saturation, lock contentionBackpressure, pools, scaling

Production Checklist ​

  • Problem: Which user flow or SLO is affected?
  • Solution: Is there a baseline, hypothesis, change, and before/after measurement?
  • Trade-off: Lower latency can require more cache, CPU, memory, or operational cost.
  • Failure mode: Inspect cache stampedes, thread starvation, pool exhaustion, GC pauses, and compression CPU.
  • Measurement: Track p50/p95/p99, throughput, errors, CPU, memory, GC, queue age, and unit cost together.
  • Security/cost: Profiling data must not leak PII; bound production sampling and retention.

Profiling Method ​

  1. Establish a baseline with representative traffic and workload.
  2. Separate CPU, allocation/heap, lock, I/O, and database-trace signals.
  3. Make one small change that tests one hypothesis.
  4. Compare latency, errors, and resources under the same workload.
  5. Record the gain and new trade-off in an ADR or performance record.

Sampling profilers show general hot paths; tracing shows where a request waits; heap dumps help find retained objects and leaks. Profiling itself adds latency and storage, so scope and duration must be controlled.

API and I/O Optimization ​

  • Return only needed DTO fields; bound payloads with pagination and field selection.
  • Use gzip/Brotli for large text payloads after measuring CPU cost for small responses.
  • Configure HTTP client pools, keep-alive, connect/read timeouts, and pending-request limits separately.
  • Run independent downstream calls with bounded parallelism; without deadline propagation, parallelism can extend the timeout.
  • Use lazy loading only when access patterns and transaction boundaries are clear; avoid hidden ORM N+1 queries.

Database and Cache ​

Do not add cache before measuring query plans, index selectivity, lock wait, pool utilization, and replica lag. Repository/ORM abstractions can hide the real query cost.

Track cache hits, misses, evictions, hot keys, stampedes, and origin fallback. Warm only popular, low-volatility data with bounded concurrency; do not overload the origin during deploys.

Scaling ​

Horizontal scaling increases capacity through stateless applications, load distribution, and autoscaling. It cannot fix a database, license, or shared connection-pool bottleneck. Vertical scaling is simpler but has a node limit and rising cost.

Autoscaling should not rely on CPU alone; consider request concurrency, queue age, latency, error budget, and downstream saturation. A CDN can move static assets and cacheable responses to the edge; separate personal or authorization-dependent responses carefully.

Outcome ​

Successful optimization improves measurements without violating correctness, security, availability, or cost goals. Record the profile, change, expected gain, and rollback signal together.

Created by Eren Demir.