Performance and reliability
Budgets
Section titled “Budgets”- Measure before optimising. Set budgets early (page weight, JavaScript size, response time, query count) and enforce them in CI.
- Core Web Vitals at the 75th percentile: LCP ≤ 2.5 s, INP ≤ 200 ms, CLS ≤ 0.1. Aim for LCP ≤ 2.0 s on content sites.
- Lighthouse mobile lab scores: performance 90+ for content sites (85+ for apps), accessibility 95+, and SEO 100 for public sites.
- Set p95 latency targets for API endpoints and track them.
Front end
Section titled “Front end”- Ship JavaScript only for interactive parts; content reads without it. Split code by route and lazy-load what is not needed for first render.
- The LCP element is in the initial HTML. An LCP image is never lazy-loaded and normally uses
fetchpriority="high"; preload a CSS background LCP image. - Images use AVIF or WebP,
srcsetandsizes, and explicitwidthandheight(oraspect-ratio). - Self-host and subset fonts with
font-display: swap. Use at most 3 font files and preload the main one. - Lazy-load off-screen images and iframes with
loading="lazy". Preconnect only to critical third-party origins. - Keep pages eligible for the back/forward cache: no
unloadhandlers and noCache-Control: no-storeon normal pages. - Reserve space for embeds, banners and late content so nothing shifts.
- Keep the main thread free: break up long tasks, debounce input handlers, and animate only
transformandopacity. - Every third-party script needs a written reason. Load it after the content, and only after consent where required.
Back end
Section titled “Back end”- Avoid N+1 queries. Select only needed columns, index what you filter and sort on, and check query plans of slow queries.
- Paginate every list with a maximum page size.
- Move slow work (email, uploads, webhooks, LLM calls) out of the request into background jobs.
- Cache with a defined key, lifetime and invalidation. Content-hashed assets get
max-age=31536000, immutable; HTML revalidates. Serve text with Brotli or gzip over HTTP/2 or HTTP/3.
Reliability
Section titled “Reliability”- Every network call has a timeout. Retry only idempotent operations, with backoff, jitter and a limit.
- Background jobs are idempotent and have retries and a dead-letter path.
- Keep servers stateless. Rate-limit public and expensive endpoints, and cap request and upload sizes.
- When a dependency fails, degrade gracefully: show cached or partial data with a clear message.
- Track errors with release versions and set up uptime checks before launch. Alert on what users feel (error rate, latency), not on every log line.
- Deploy from CI on
mainwith health checks. Rollback takes minutes. Migrations run as an explicit step.