top of page

Set Performance Budgets That Stick

  • Shawn West
  • Jul 30
  • 3 min read

Updated: Aug 6

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