mcpField
P
performance

performance

github.com/motormetricsDevelopment2270 installsUpdated 2d ago
Repository

About performance

A performance skill for developers working on web applications. It provides practical guidance for measuring and improving frontend, backend, and database performance, with examples covering common optimization techniques.

Key features

  1. 01Web Vitals and backend targets
  2. 02Lighthouse and k6 measurement
  3. 03Bundle splitting and tree shaking
  4. 04React render and list optimization
  5. 05Database query and index tuning
  6. 06Redis and Next.js caching

Use cases

  1. 01Audit a web app with Lighthouse
  2. 02Load-test an API using k6
  3. 03Reduce React re-renders and bundle size
  4. 04Find slow queries and add indexes

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/motormetrics/motormetrics --skill performance

After installing, type/performancein Claude Code to confirm it loaded.

Details

From the project README

Performance Skill

Performance Targets

Frontend (Web Vitals): LCP < 2.5s, FID < 100ms, CLS < 0.1, FCP < 1.8s, TTFB < 600ms Backend: Response time < 500ms (p95), cold start < 2s, error rate < 1% Database: Query time < 100ms, cache hit rate > 80%

Measure Performance

# Lighthouse audit
npx lighthouse https://motormetrics.app --view

# Bundle analysis
cd apps/web && ANALYZE=true pnpm build

# Load test with k6
k6 run --vus 100 --duration 5m load-test.js

Bundle Size Optimization

Dynamic Imports
// ❌ Static import (loads immediately)
import { HeavyComponent } from "./heavy-component";

// ✅ Dynamic import (lazy load)
import dynamic from "next/dynamic";
const HeavyComponent = dynamic(() => import("./heavy-component"), {
  loading: () => <div>Loading...</div>,
  ssr: false,
});
Tree Shaking
// ❌ Imports entire library
import _ from "lodash";

// ✅ Import only what you need
import uniq from "lodash/uniq";

React Performance

Prevent Re-renders
// useMemo for expensive calculations
const processed = useMemo(() => expensiveOperation(data), [data]);

// useCallback for stable function references
const handleClick = useCallback(() => doSomething(), []);

// React.memo for pure components
const Child = React.memo(function Child({ name }) {
  return <div>{name}</div>;
});
Virtualize Long Lists
import { FixedSizeList } from "react-window";

<FixedSizeList height={600} itemCount={items.length} itemSize={100} width="100%">
  {({ index, style }) => <Item style={style} data={items[index]} />}
</FixedSizeList>

Database Query Optimization

Add Indexes
// packages/database/src/schema/cars.ts
export const cars = pgTable("cars", {
  make: text("make").notNull(),
  month: text("month").notNull(),
}, (table) => ({
  makeIdx: index("cars_make_idx").on(table.make),
}));
Avoid N+1 Queries
// ❌ N+1 queries
for (const post of posts) {
  post.author = await db.query.users.findFirst({ where: eq(users.id, post.authorId) });
}

// ✅ Single query with relation
const posts = await db.query.posts.findMany({ with: { author: true } });
Select Only Needed Columns
// ❌ Selects all columns
const users = await db.query.users.findMany();

// ✅ Select specific columns
const users = await db.select({ id: users.id, name: users.name }).from(users);
Use Pagination
const cars = await db.query.cars.findMany({
  limit: 20,
  offset: (page - 1) * 20,
});

Caching

Redis Caching
import { redis } from "@motormetrics/utils/redis";

export async function getCarsWithCache(make: string) {
  const cacheKey = `cars:${make}`;
  const cached = await redis.get(cacheKey);
  if (cached) return JSON.parse(cached as string);

  const cars = await db.query.cars.findMany({ where: eq(cars.make, make) });
  await redis.set(cacheKey, JSON.stringify(cars), { ex: 3600 });
  return cars;
}
Next.js Caching
// Revalidate every hour
export const revalidate = 3600;

// Or use fetch with caching
const data = await fetch(url, { next: { revalidate: 3600 } });

Image Optimization

import Image from "next/image";

// ✅ Optimized image with priority for above-fold
<Image
  src="/hero.jpg"
  alt="Hero"
  fill
  sizes="(max-width: 768px) 100vw, 50vw"
  priority
/>

Vercel Function Optimization

// API route with optimized config
export const config = {
  maxDuration: 60, // seconds
};

// Use edge functions for low-latency endpoints
export const runtime = "edge";

Profiling

Performance Middleware
// apps/api/src/middleware/performance.ts
export const performanceMiddleware = async (c: Context, next: Next) => {
  const start = performance.now();
  await next();
  const duration = performance.now() - start;

  c.header("X-Response-Time", `${Math.round(duration)}ms`);

  if (duration > 1000) {
    log.warn("Slow request", { path: c.req.path, duration: Math.round(duration) });
  }
};
Query Profiling
const start = performance.now();
const result = await db.query.cars.findMany();
const duration = performance.now() - start;

if (duration > 100) {
  console.warn(`Slow query: ${duration}ms`);
}
Vercel Analytics

Check Vercel Dashboard → Analytics for:

  • Function execution times
  • Edge response times
  • Web Vitals metrics
  • Request volumes and errors

Load Testing

// load-test.js (k6)
import http from "k6/http";
import { check } from "k6";

export const options = {
  stages: [
    { duration: "2m", target: 100 },
    { duration: "5m", target: 100 },
    { duration: "2m", target: 0 },
  ],
  thresholds: {
    http_req_duration: ["p(95)<500"],
    http_req_failed: ["rate<0.01"],
  },
};

export default function() {
  const res = http.get("https://api.motormetrics.app/api/v1/cars/makes");
  check(res, { "status 200": (r) => r.status === 200 });
}

Performance Checklist

  • Bundle size < 200KB (initial load)
  • LCP < 2.5s, FID < 100ms, CLS < 0.1
  • API responses < 500ms
  • Database queries < 100ms
  • Images optimized (WebP/AVIF)
  • Code splitting implemented
  • Caching strategy in place
  • Long lists virtualized
  • Compression enabled

Quick Wins

  1. Compression: Enable gzip/brotli (60-80% size reduction)
  2. Image Optimization: Use Next.js Image component
  3. Caching: Cache expensive operations in Redis
  4. Indexes: Add indexes to frequently queried columns
  5. Code Splitting: Lazy load heavy components
  6. Memoization: Use useMemo/useCallback for expensive operations

References

Comments

Markdown supported