Skip to main content

vercel-optimize

Optimizes Vercel-deployed applications for cost, performance, and reliability through cold start mitigation, caching strategy, edge function optimization, bundle auditing, and monitoring.

Jump to install

Source facts

Repository
paulpas/agent-skill-router
Last source activity
June 9, 2026 at 16:28
Detected SKILL.md language
English
Stars
4
Forks
1

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
vercel-optimize
description
Optimizes Vercel-deployed applications for cost, performance, and reliability through cold start mitigation, caching strategy, edge function optimization, bundle auditing, and monitoring.
license
MIT
compatibility
opencode
archetypes
["tactical","diagnostic","strategic"]
anti_triggers
["brainstorming","vague ideation"]
response_profile
{"verbosity":"medium","directive_strength":"high","abstraction_level":"operational"}
metadata
{"version":"1.0.0","domain":"coding","triggers":"vercel optimize, vercel performance, cold start, vercel caching, vercel analytics, edge functions, vercel cost","role":"implementation","scope":"implementation","output-format":"code","content-types":["code","guidance","do-dont","examples","config"],"related-skills":"react-native-rendering","author":"https://github.com/vercel-labs","source":"https://github.com/vercel-labs/agent-skills"}
# Vercel Application Optimization A senior Vercel platform engineer who optimizes deployed applications for cost, performance, and reliability — mitigating cold starts, tuning CDN caching, optimizing Edge Functions, reducing bundle size, and setting up monitoring dashboards. ## TL;DR Checklist - [ ] Audit performance baseline with Vercel Analytics or Lighthouse CI before optimizing - [ ] Mitigate cold starts by migrating latency-sensitive endpoints to Edge Functions - [ ] Configure CDN caching with `stale-while-revalidate` for dynamic content and `immutable` for static assets - [ ] Split bundles at route level with `next/dynamic` and lazy-load heavy dependencies - [ ] Optimize images with next/image configuration (formats, sizes, remotePatterns, loader) - [ ] Use Next.js Script component with appropriate strategy for third-party scripts - [ ] Set up Vercel Analytics, Speed Insights, and Logs for ongoing monitoring - [ ] Track per-function execution cost to identify expensive operations --- ## When to Use Use this skill when: - A Next.js app on Vercel has slow page loads or high Time-to-First-Byte (TTFB) - Serverless function cold starts are noticeable (response times >500ms on first request) - The monthly Vercel bill is growing faster than traffic - Lighthouse scores are below 90 for Performance - Images are unoptimized (large file sizes, wrong formats, missing dimensions) - Third-party scripts block page rendering (no strategy-based loading) - You need to implement ISR (Incremental Static Regeneration) with on-demand revalidation --- ## When NOT to Use Avoid this skill for: - Apps not deployed on Vercel (different platform, different optimization strategies) - Static sites with zero server-side computation — Vercel's defaults are already optimal - Prototyping or staging environments where optimization overhead isn't justified - Before establishing performance baselines — always measure the problem first --- ## Core Workflow 1. **Audit Performance** — Establish baseline metrics: - Enable Vercel Analytics and Speed Insights in the project dashboard - Run Lighthouse CI on critical pages and record LCP, CLS, INP scores - Identify pages with high TTFB (above 500ms), large bundle sizes, or unoptimized images - Check Vercel Logs for function execution duration and error rates **Checkpoint:** Document baseline values for every metric you plan to improve. Without baselines, you cannot measure success. 2. **Address Cold Starts** — Reduce serverless function latency: - Migrate latency-sensitive endpoints from Serverless Functions to Edge Functions (sub-50ms start) - Implement lambda warmers for Serverless Functions that cannot be migrated - Use `keep-alive` connections to reuse database and API connections across invocations - Decrease function memory allocation if underutilized (cold starts scale with memory) **Checkpoint:** Verify that cold start latency drops below 200ms for critical paths. Retest from a fresh region. 3. **Optimize Caching Strategy** — Reduce origin requests: - Configure `Cache-Control` headers with `s-maxage` + `stale-while-revalidate` for dynamic pages - Set `immutable` with `max-age=31536000` for static assets (fonts, images, compiled CSS) - Implement ISR with appropriate `revalidate` intervals and on-demand revalidation webhooks - Use `next.config.js` `headers` for global cache policies **Checkpoint:** Verify cache hit rate in Vercel Analytics is above 80% for static assets and above 50% for dynamic pages. 4. **Reduce Bundle Size** — Ship less JavaScript: - Use `next/dynamic` with `ssr: false` for heavy client-only components (charts, maps, editors) - Tree-shake unused exports from large dependencies (lodash, moment, date-fns) - Analyze bundle with `@next/bundle-analyzer` and identify large chunks - Lazy-load below-the-fold components and route segments - Replace large dependencies with lighter alternatives **Checkpoint:** Run `ANALYZE=true next build` — total JS per page must be under 150KB (gzipped) for pages above the fold. 5. **Set Up Monitoring** — Ensure ongoing visibility: - Configure Vercel Analytics for real-user monitoring (RUM) - Set up Speed Insights for Core Web Vitals tracking (LCP, CLS, INP) - Export Vercel Logs and create custom metrics for function duration, error rate, and cache hit ratio - Set up budget alerts: alert when LCP exceeds 2.5s or error rate exceeds 1% **Checkpoint:** Verify dashboards are populated with data within 24 hours of enabling. 6. **Review Cost Metrics** — Optimize the Vercel bill: - Identify top-spending Serverless Functions by execution duration and invocation count - Migrate high-traffic Serverless Functions to Edge Functions or ISR to reduce compute cost - Optimize `next/image` configuration to reduce image optimization bandwidth charges - Review function memory allocation — over-allocated memory costs more per invocation **Checkpoint:** Compare current projected monthly cost vs. previous month — target 20% reduction. --- ## Implementation Patterns ### Pattern 1: Edge Function Migration (Cold Start Mitigation) ```typescript // ❌ BAD: Serverless Function for a simple API proxy — 500ms+ cold start // pages/api/proxy.ts (Serverless Function) import type { NextApiRequest, NextApiResponse } from 'next'; export default async function handler( req: NextApiRequest, res: NextApiResponse ) { const response = await fetch('https://api.example.com/data'); const data = await response.json(); res.status(200).json(data); } // ✅ GOOD: Edge Function for the same proxy — sub-50ms cold start // app/api/proxy/route.ts (Edge Function — works in App Router) export const runtime = 'edge'; export async function GET(request: Request) { const response = await fetch('https://api.example.com/data'); const data = await response.json(); return Response.json(data); } // ✅ GOOD: Keep-alive connection reuse for database-backed endpoints // lib/db.ts — reuse connection across invocations let dbClient: DatabaseClient | null = null; export async function getDb(): Promise<DatabaseClient> { if (!dbClient) { dbClient = await createClient({ connectionString: process.env.DATABASE_URL!, poolSize: 1, // Keep connection alive between function invocations idleTimeoutMillis: 60_000, }); } return dbClient; } // app/api/users/route.ts — uses the cached connection export const runtime = 'nodejs'; export async function GET() { const db = await getDb(); // Reuses connection on warm invocations const users = await db.query('SELECT * FROM users LIMIT 10'); return Response.json(users); } ``` ### Pattern 2: Advanced Caching Strategy ```typescript // next.config.js — global cache headers /** @type {import('next').NextConfig} */ const nextConfig = { async headers() { return [ { // Static assets: cache forever in CDN and browser source: '/:path*.(svg|png|jpg|jpeg|gif|webp|woff2|ttf|eot|css|js)', headers: [ { key: 'Cache-Control', value: 'public, max-age=31536000, immutable', }, ], }, { // API routes: CDN cache with stale-while-revalidate source: '/api/:path*', headers: [ { key: 'Cache-Control', value: 'public, s-maxage=60, stale-while-revalidate=600', }, ], }, { // HTML pages: short CDN cache, fallback to server source: '/:path((?!api|_next|static).*)', headers: [ { key: 'Cache-Control', value: 'public, s-maxage=10, stale-while-revalidate=59', }, ], }, ]; }, }; // ✅ GOOD: ISR with on-demand revalidation // app/blog/[slug]/page.tsx interface BlogPageProps { params: { slug: string }; } export default async function BlogPost({ params }: BlogPageProps) { const post = await getPost(params.slug); return <article>{/* ... */}</article>; } // Revalidate every 60 seconds, but also trigger on-demand when content changes export const revalidate = 60; // app/api/revalidate/route.ts — on-demand revalidation webhook export async function POST(request: Request) { const { secret, slug } = await request.json(); // Validate secret to prevent unauthorized revalidation if (secret !== process.env.REVALIDATION_SECRET) { return Response.json({ message: 'Invalid secret' }, { status: 401 }); } try { await revalidatePath(`/blog/${slug}`); return Response.json({ revalidated: true }); } catch (err) { return Response.json({ message: 'Revalidation failed' }, { status: 500 }); } } ``` ### Pattern 3: Bundle Optimization with next/dynamic ```tsx // ❌ BAD: Heavy chart library imported eagerly — adds 120KB to the main bundle import { LineChart } from 'recharts'; export default function Dashboard() { const [showChart, setShowChart] = useState(false); return ( <div> <button onClick={() => setShowChart(true)}>Show Chart</button> {showChart && ( <LineChart width={600} height={300} data={data}> {/* ... */} </LineChart> )} </div> ); } // ✅ GOOD: Chart library lazy-loaded — added to a separate chunk, loaded on demand import dynamic from 'next/dynamic'; const LazyLineChart = dynamic( () => import('recharts').then((mod) => mod.LineChart), { ssr: false, // Charts are client-only — no SSR needed loading: () => <div className="chart-skeleton h-[300px] w-[600px] bg-gray-100 animate-pulse" />, } ); export default function Dashboard() { const [showChart, setShowChart] = useState(false); return ( <div> <button onClick={() => setShowChart(true)}>Show Chart</button> {showChart && <LazyLineChart width={600} height={300} data={data} />} </div> ); } // ✅ GOOD: Route-level code splitting with Next.js App Router // app/dashboard/page.tsx — automatically code-split at route boundaries export default function DashboardPage() { return ( <main> <h1>Dashboard</h1> {/* Heavy components loaded per-route, not in the global layout */} </main> ); } // app/analytics/page.tsx — separate chunk, no impact on dashboard load time export default function AnalyticsPage() { return ( <main> <h1>Analytics</h1> </main> ); } ``` ### Pattern 4: Image Optimization with next/image ```tsx import Image from 'next/image'; // ❌ BAD: Unoptimized image — no sizes, wrong format fallback, large dimensions function BadHero() { return ( <img src="/hero.png" // Large PNG — no WebP, no AVIF alt="Hero" style={{ width: '100%', height: 'auto' }} /> ); } // ✅ GOOD: Fully optimized with next/image function OptimizedHero() { return ( <Image src="/hero.jpg" alt="Hero" width={1920} height={1080} sizes="(max-width: 768px) 100vw, (max-width: 1200px) 75vw, 50vw" priority // LCP element — load immediately, don't lazy-load quality={85} // Balance quality vs. file size /> ); } // ✅ GOOD: next.config.js with remote image configuration // next.config.js const nextConfig = { images: { formats: ['image/avif', 'image/webp'], // AVIF preferred, WebP fallback deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048], imageSizes: [16, 32, 48, 64, 96, 128, 256, 384], minimumCacheTTL: 60 * 60 * 24 * 30, // Cache optimized images for 30 days remotePatterns: [ { protocol: 'https', hostname: 'images.unsplash.com', pathname: '/**', }, { protocol: 'https', hostname: 'cdn.example.com', pathname: '/images/**', }, ], }, }; export default nextConfig; ``` ### Pattern 5: Script Loading Strategies ```tsx // ❌ BAD: Script tag blocks rendering — no strategy, loads synchronously export default function MarketingPage() { return ( <div> <script src="https://www.googletagmanager.com/gtag/js?id=GA_MEASUREMENT_ID" /> <script dangerouslySetInnerHTML={{ __html: `window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);}` }} /> {/* Main content — blocked until scripts load */} </div> ); } // ✅ GOOD: Next.js Script component with appropriate strategies import Script from 'next/script'; export default function OptimizedMarketingPage() { return ( <> {/* Critical analytics — load before page becomes interactive, but don't block render */} <Script src="https://www.googletagmanager.com/gtag/js?id=GA_MEASUREMENT_ID" strategy="afterInteractive" /> {/* Chat widget — load after everything else is done */} <Script src="https://widget.intercom.io/widget/abc123" strategy="lazyOnload" /> {/* Heatmap tool — not needed on mobile */} <Script src="https://static.hotjar.com/c/hotjar-123456.js" strategy="lazyOnload" /> {/* Main page content renders immediately — not blocked by scripts */} <main> <h1>Welcome</h1> <p>This content renders before any third-party scripts load.</p> </main> </> ); } ``` --- ## Constraints ### MUST DO - Measure performance baselines with Vercel Analytics or Lighthouse CI before and after each optimization - Use `stale-while-revalidate` caching for dynamic content with `s-maxage` set to acceptable freshness TTL - Set `Cache-Control: public, max-age=31536000, immutable` for all static assets (fonts, images, compiled CSS/JS) - Use `runtime: 'edge'` for API routes that need sub-50ms cold starts and low latency globally - Use `next/dynamic` with `ssr: false` for heavy client-only components that are not visible above the fold - Configure `next/image` with `formats: ['image/avif', 'image/webp']` and appropriate `remotePatterns` - Use Next.js `<Script>` component with explicit `strategy` — never plain `<script>` tags - Monitor Serverless Function execution durations and migrate expensive ones to Edge or ISR ### MUST NOT DO - Use Serverless Functions for high-traffic, latency-sensitive endpoints — prefer Edge Functions or ISR - Set `revalidate: 0` on ISR pages that don't need real-time freshness — set a reasonable TTL - Include heavy npm packages (chart libraries, moment.js, lodash) in the main bundle — dynamic import them - Use `<img>` tags for anything that is not a user-uploaded image with unknown dimensions - Block page rendering with third-party scripts — always use `afterInteractive` or `lazyOnload` strategy - Ignore Vercel Analytics data — it reveals real user performance, not just synthetic Lighthouse scores - Optimize without cost awareness — a 10ms function improvement isn't worth 2x memory allocation --- ## Related Skills | Skill | Purpose | |---|---|
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub