Files
asepharyana-hub-guide/skills/performance/SKILL.md
T
asepharyana e513cddd68 feat(hub-guide): expand plugin with 26 best-practice skills, hooks, and references
Transform hub-guide from a single-skill Hub monorepo guide into a
comprehensive programming best-practice plugin covering all situations.

Skills (26):
- Core: engineering-principles, clean-code, clean-architecture,
  design-patterns, testing, error-handling, security, api-design,
  git-workflow, documentation, logging-observability, performance
- Languages: typescript, python, rust, go
- Frameworks: react-frontend, elysiajs, hono-backend, drizzle-database, nextjs
- Infrastructure: docker, ci-cd, monitoring
- Monorepo: monorepo, hub-guide (existing)

Hooks:
- SessionStart: auto-detect project type and activate relevant skills
- PreToolUse (Write|Edit): inject language-specific rules per file type

Reference files for deep dives:
- clean-architecture/references/solid.md (SOLID + component principles)
- design-patterns/references/catalog.md (full GoF catalog with examples)
- testing/references/mocks.md (test double taxonomy)

Restructure plugin to modern skills/ directory format.
2026-07-25 11:35:16 +07:00

5.3 KiB

name, description
name description
performance Best practices for software performance — caching, query optimization, lazy loading, profiling, CDN, database indexing, and memory management. Use when optimizing slow endpoints, reducing load times, designing caching strategies, or whenever the user mentions "performance," "optimization," "slow," "cache," "lazy loading," "profiling," "bottleneck," "N+1," "latency," "throughput," or "scalability."

Performance Best Practices

Core Principle

Measure before optimizing. A guess is wrong more than half the time. Profile first, then fix the real bottleneck.

Frontend Performance

Loading

  • Lazy load — images, components, routes, heavy modules. Only what's needed now.
  • Code splitting — split by route (dynamic imports), not by random chunks.
  • Preload critical assets<link rel="preload"> for fonts, hero images, critical CSS.
  • Prefetch likely navigations<link rel="prefetch"> for pages user is likely to visit.

Rendering

  • Virtual lists — for 100+ items. windowing (react-window, tanstack-virtual).
  • Debounce/throttle — search inputs (300ms debounce), scroll handlers (throttle 100ms).
  • Avoid layout thrashing — batch DOM reads/writes. Use requestAnimationFrame.
  • CSS containmentcontain: contents isolates sub-trees from layout recalc.

Assets

  • Images — next-gen formats (WebP, AVIF), responsive (srcset), lazy loading (loading="lazy").
  • Fontsfont-display: swap, subset fonts, preload critical ones.
  • Bundles — tree-shaking enabled, minification, compression (brotli > gzip).

Backend Performance

Database

Issue Fix
N+1 queries Eager loading (.with(), .include(), JOIN)
Missing index EXPLAIN ANALYZE to find sequential scans. Add indexes on WHERE/JOIN/ORDER BY columns
Too many rows Pagination, cursor-based, limit queries
Expensive joins Denormalize, materialized view, or caching layer
Large JSON fields Only select columns needed, not SELECT *
-- ❌ N+1
for each order: SELECT * FROM items WHERE order_id = ?
-- ✅ Eager load
SELECT * FROM items WHERE order_id IN (?, ?, ?, ...)

Caching Strategy

Request → CDN (static assets) → API Gateway → App Cache → DB
Layer Cache TTL Invalidates
CDN Static assets, API responses Long (1yr for assets) Version hash
HTTP Cache-Control, ETag Varies If-None-Match
App Redis, in-memory Seconds-minutes Write-through / TTL
DB Query cache, connection pool Intrinsic Row changes

Cache patterns:

// Cache-aside (most common)
async function getUser(id: string): Promise<User> {
  const cached = await cache.get(`user:${id}`);
  if (cached) return JSON.parse(cached);
  const user = await db.select().from(users).where(eq(users.id, id));
  await cache.set(`user:${id}`, JSON.stringify(user), 'EX', 300); // 5 min TTL
  return user;
}

Connection Pooling

  • Database: pool of 10-50 connections (not 1, not unlimited).
  • HTTP: keep-alive, connection reuse. H2 multiplexing.
  • Redis: single connection reused, not new connection per request.

Network Performance

  • Compression — brotli for static, gzip as fallback. Enable in Traefik (compress middleware).
  • HTTP/2 — multiplexing, header compression, server push. Enabled by default in Traefik.
  • CDN — CloudFlare, Fastly, CloudFront for static assets and API edge caching.
  • Keep-alive — reuse TCP connections. Default Timeout 60s.
  • Latency budget — 200ms total is good for most apps. Track per service.

Profiling

When you think something is slow:

  1. Define the measurement — what's slow? p50? p99? cold start?
  2. Profile — flame graphs (pyroscope, pprof), APM (Jaeger spans).
  3. Find the bottleneck — is it CPU? IO? Network? Database? Memory?
  4. Fix one thing — measure again. If no improvement, revert and try next.

Tools by Language

Language Profiling Flame Graphs
TypeScript Chrome DevTools, Node --prof 0x tool
Rust perf, flamegraph, pprof-rs cargo flamegraph
Go pprof (runtime built-in) go tool pprof -http
Python cProfile, py-spy flameprof

Performance Budgets

Set measurable limits and enforce them:

  • Lighthouse — 90+ Performance score
  • Bundle size — <200KB JS (compressed), <50KB CSS
  • LCP (Largest Contentful Paint) — <2.5s
  • FID (First Input Delay) — <100ms
  • CLS (Cumulative Layout Shift) — <0.1
  • API p99 — <500ms
  • First byte — <200ms

Anti-patterns

  • Premature optimization — optimizing before measuring. "Make it work, make it right, make it fast."
  • Caching everything — cache invalidation is hard. Cache what's expensive and stable.
  • Over-indexing — too many indexes slow writes. Index what's queried, not every column.
  • **SELECT *** — fetches columns you don't need. Increases memory and network.
  • Sync over async — blocking calls in async context (Node event loop blocking).
  • Fat dependencies — importing a 50KB library for one function. Prefer tree-shakeable modules.