top of page

Set Performance Budgets That Stick

S. West
Jul 30
3 min read

Updated: 4 days ago

Performance Engineering · Part 10

Performance rots quietly — no single change makes the app slow, but a hundred small regressions over a year do, and by then nobody knows which one to blame. A performance budget stops the rot by making "slower" a build failure, not a surprise. This walks through setting budgets, enforcing them in CI so a regression blocks the PR, and backing them with production monitoring.


You optimized. Now don't let it regress. Performance budgets enforce the gains.


Step 1: Pick the Metrics (5 min)


For a web app:


  • p95 response time per endpoint

  • p99 response time

  • Time to first byte (TTFB)

  • Bundle size (frontend)

  • Memory footprint

  • Cold start time


For a service:


  • Request latency

  • Database query time

  • Background job duration

  • Memory usage


Pick what matters; 4-6 metrics is plenty.


Step 2: Set Budgets (5 min)


Based on:


  • User experience research (Google: > 2s = bad)

  • Business requirements (financial: < 100ms)

  • Competitive benchmarks

  • Current performance


Login endpoint:           p95 < 500ms
Search:                   p95 < 800ms
Bundle size (JS):         < 200kb gzipped
Memory:                   < 256MB
Cold start:               < 1s

Budgets aren't aspirations; they're commitments.


Step 3: Measure in CI (10 min)


For frontend bundle:


- name: Build
  run: npm run build

- name: Check bundle size
  run: |
    SIZE=$(stat -c%s build/main.js)
    if [ $SIZE -gt 204800 ]; then
      echo "Bundle $SIZE exceeds 200kb budget"
      exit 1
    fi

For backend latency, run perf tests in CI:


- name: Run perf test
  run: k6 run --vus 10 --duration 1m perf-test.js
  
- name: Check thresholds
  run: |
    P95=$(jq '.metrics.http_req_duration.values.p95' summary.json)
    if (( $(echo "$P95 > 500" | bc -l) )); then
      echo "p95 ${P95}ms exceeds 500ms budget"
      exit 1
    fi

Step 4: Block PRs That Regress (5 min)


CI check failing = PR can't merge.


For frontend, tools like:


  • Lighthouse CI: integrates with GitHub Actions; budgets per metric

  • size-limit: monitors JS bundle size

  • Pulsar: Java bundle analyzer


Configure once; every PR checked.


Step 5: Production Monitoring (10 min)


CI tests on synthetic workload. Production is real:


# Prometheus alerts
- alert: P95LatencyHigh
  expr: |
    histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))
    > 0.5
  for: 10m

If p95 goes above 500ms for 10 minutes, alert.


Step 6: Per-Endpoint Budgets (10 min)


Different endpoints have different budgets:


- alert: SignInLatencyHigh
  expr: |
    histogram_quantile(0.95, 
      rate(http_request_duration_seconds_bucket{endpoint="/api/signin"}[5m]))
    > 0.3
  for: 10m

- alert: SearchLatencyHigh  
  expr: |
    histogram_quantile(0.95,
      rate(http_request_duration_seconds_bucket{endpoint="/api/search"}[5m]))
    > 0.8
  for: 10m

Granular targets per endpoint.


Step 7: User-Centric Metrics (10 min)


Beyond server metrics, real user monitoring (RUM):


  • Core Web Vitals: LCP, FID, CLS

  • Time to Interactive

  • Custom: time to first meaningful render


Tools: Datadog RUM, New Relic Browser, Sentry, custom + analytics.


These capture what users actually experience.


Step 8: Budget Review (5 min)


Periodically (quarterly):


  • Did we meet budgets last quarter?

  • Where did we miss?

  • Should budgets tighten?

  • Should they loosen?


Budgets evolve with product reality.


Step 9: Performance Test Environments (10 min)


Don't load-test production. Use:


  • Dedicated perf environment (production-like)

  • Realistic data volumes

  • Realistic user behavior


If perf env doesn't match prod, results are misleading.


Maintain it carefully. Schedule perf tests regularly.


Step 10: Document and Celebrate (5 min)


Make budgets visible:


  • Dashboard showing each metric against budget

  • Highlight in retrospectives

  • Celebrate when team meets all budgets


Visibility creates accountability.


When you fail a budget: postmortem-ish review, not blame. What caused it? How to prevent?


What You Just Did


Performance is enforced, not hoped for. CI catches regressions; production alerts catch drift; quarterly reviews keep budgets relevant.


Common Failure Modes


Set budgets; never check. Decoration.


Aspirational budgets. Constantly fail; team ignores.


No perf environment. Test against tiny data; production fails.


One-time set. Budgets from year 1 don't fit year 3.


No customer-centric metrics. Server is fast; users still feel slow.


You're Done


You've completed Path 18 — Performance Engineering. Profiling, N+1, indexes, caching, load testing, flame graphs, query optimization, memory, cold start, budgets.


Recommend Security Engineering Hands-On next — performance and security often trade off.



Continue the Performance Engineering path



Part of the Performance Engineering learning path.

bottom of page