Official agent skill

V8 Jit

by vercel in vercel/next.js

V8 JIT optimization patterns for writing high-performance JavaScript in Next.js server internals.

OfficialMITAuto-check passedBackend & APIs

Install V8 Jit

skills CLI
$ npx skills add vercel/next.js --skill v8-jit -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install vercel/next.js v8-jit --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/vercel/next.js.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/v8-jit .claude/skills/v8-jit && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
v8-jit
GitHub stars
143k
Token cost
~3.6k tokens
SKILL.md length
1,061 words
Files
1
Skills in repo
27
Repo updated
First seen
Licence
MIT

At a glance

V8 JIT optimization patterns for writing high-performance JavaScript in Next.js server internals.

  • Works in 4 steps: Ignition (interpreter) — executes… → Sparkplug — fast baseline compiler (no… → Maglev — mid-tier optimizing compiler. → …
  • Reviewing hot-path code in app-render
  • SKILL.md covers Background: V8's Tiered…, Hidden Classes (Shapes / Maps), Monomorphic vs Polymorphic vs… and Closure and Allocation Pressure, plus 7 more sections
  • Calls node

What it does

V8 Jit is an agent skill from vercel/next.js, published by the product's own GitHub organization. V8 JIT optimization patterns for writing high-performance JavaScript in Next.js server internals. Use when writing or reviewing hot-path code in app-render, stream-utils, routing, caching, or any per-request code path. Covers hidden classes / shapes, monomorphic call sites, inline caches, megamorphic deopt, closure allocation, array packing, and profiling with --trace-opt / --trace-deopt.

Its SKILL.md is about 3.6k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Backend & APIs, covering Caching. It works with Next.js and JavaScript. The licence is MIT.

When your agent uses it

  • Reviewing hot-path code in app-render
  • Any per-request code path

Example prompts

  • “/v8-jit”

Requirements

  • Node.js

Workflow steps

4 steps, taken from the first numbered list in SKILL.md.

  1. Ignition (interpreter) — executes bytecode immediately.
  2. Sparkplug — fast baseline compiler (no optimization).
  3. Maglev — mid-tier optimizing compiler.
  4. Turbofan — full optimizing compiler (speculative, type-feedback-driven).

What it can do on your machine

Read from SKILL.md and the folder at commit a32ddfd. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • node

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

V8 Jit loads about 3.6k tokens when it runs. Until then it costs about 100 tokens; SKILL.md has 1,061 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~100
When it runs · the whole SKILL.md, loaded when a task matches
~3.6k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from vercel/next.js at commit a32ddfd, republished under its MIT licence (© vercel). 1,061 words, ~3,620 tokens.

Download SKILL.mdSave it as .claude/skills/v8-jit/SKILL.md (or your agent's skills folder).
name
v8-jit
description
V8 JIT optimization patterns for writing high-performance JavaScript in Next.js server internals. Use when writing or reviewing hot-path code in app-render, stream-utils, routing, caching, or any per-request code path. Covers hidden classes / shapes, monomorphic call sites, inline caches, megamorphic deopt, closure allocation, array packing, and profiling with --trace-opt / --trace-deopt.
user-invocable
false
metadata.internal
true

V8 JIT Optimization

Use this skill when writing or optimizing performance-critical code paths in Next.js server internals — especially per-request hot paths like rendering, streaming, routing, and caching.

Background: V8's Tiered Compilation

V8 compiles JavaScript through multiple tiers:

  1. Ignition (interpreter) — executes bytecode immediately.
  2. Sparkplug — fast baseline compiler (no optimization).
  3. Maglev — mid-tier optimizing compiler.
  4. Turbofan — full optimizing compiler (speculative, type-feedback-driven).

Code starts in Ignition and is promoted to higher tiers based on execution frequency and collected type feedback. Turbofan produces the fastest machine code but bails out (deopts) when assumptions are violated at runtime.

The key principle: help V8 make correct speculative assumptions by keeping types, shapes, and control flow predictable.

Hidden Classes (Shapes / Maps)

Every JavaScript object has an internal "hidden class" (V8 calls it a Map, the spec calls it a Shape). Objects that share the same property names, added in the same order, share the same hidden class. This enables fast property access via inline caches.

Initialize All Properties in Constructors
ts
// GOOD — consistent shape, single hidden class transition chain
class RequestContext {
  url: string
  method: string
  headers: Record<string, string>
  startTime: number
  cached: boolean

  constructor(url: string, method: string, headers: Record<string, string>) {
    this.url = url
    this.method = method
    this.headers = headers
    this.startTime = performance.now()
    this.cached = false // always initialize, even defaults
  }
}
ts
// BAD — conditional property addition creates multiple hidden classes
class RequestContext {
  constructor(url, method, headers, options) {
    this.url = url
    this.method = method
    if (options.timing) {
      this.startTime = performance.now() // shape fork!
    }
    if (options.cache) {
      this.cached = false // another shape fork!
    }
    this.headers = headers
  }
}

Rules:

  • Assign every property in the constructor, in the same order, for every instance. Use null / undefined / false as default values rather than omitting the property.
  • Prefer factory functions when constructing hot-path objects. A single factory makes it harder to accidentally fork shapes in different call sites.
  • Never delete a property on a hot object — it forces a transition to dictionary mode (slow properties).
  • Avoid adding properties after construction (obj.newProp = x) on objects used in hot paths.
  • Object literals that flow into the same function should have keys in the same order:
  • Use tuples for very small fixed-size records when names are not needed. Tuples avoid key-order pitfalls entirely.
ts
// GOOD — same key order, shares hidden class
const a = { type: 'static', value: 1 }
const b = { type: 'dynamic', value: 2 }

// BAD — different key order, different hidden classes
const a = { type: 'static', value: 1 }
const b = { value: 2, type: 'dynamic' }
Real Codebase Example

Span in src/trace/trace.ts initializes all fields in the constructor in a fixed order — name, parentId, attrs, status, id, _start, now. This ensures all Span instances share one hidden class.

Monomorphic vs Polymorphic vs Megamorphic

V8's inline caches (ICs) track the types/shapes seen at each call site or property access:

IC StateShapes SeenSpeed
Monomorphic1Fastest — single direct check
Polymorphic2–4Fast — linear search through cases
Megamorphic5+Slow — hash-table lookup, no inlining

Once an IC goes megamorphic it does NOT recover (until the function is re-compiled). Megamorphic ICs also prevent Turbofan from inlining the function.

Keep Hot Call Sites Monomorphic
ts
// GOOD — always called with the same argument shape
function processChunk(chunk: Uint8Array): void {
  // chunk is always Uint8Array → monomorphic
}

// BAD — called with different types at the same call site
function processChunk(chunk: Uint8Array | Buffer | string): void {
  // IC becomes polymorphic/megamorphic
}

Practical strategies:

  • Normalize inputs at the boundary (e.g. convert Buffer → Uint8Array once) and keep internal functions monomorphic.
  • Avoid passing both null and undefined for the same parameter — pick one sentinel value.
  • When a function must handle multiple types, split into separate specialized functions and dispatch once at the entry point:
ts
// Entry point dispatches once
function handleStream(stream: ReadableStream | Readable) {
  if (stream instanceof ReadableStream) {
    return handleWebStream(stream) // monomorphic call
  }
  return handleNodeStream(stream) // monomorphic call
}

This is the pattern used in stream-ops.ts and throughout the stream-utils code (Node.js vs Web stream split via compile-time switcher).

Closure and Allocation Pressure

Every closure captures its enclosing scope. Creating closures in hot loops or per-request paths generates GC pressure and can prevent escape analysis.

Hoist Closures Out of Hot Paths
ts
// BAD — closure allocated for every request
function handleRequest(req) {
  stream.on('data', (chunk) => processChunk(chunk, req.id))
}

// GOOD — shared listener, request context looked up by stream
const requestIdByStream = new WeakMap()
function onData(chunk) {
  const id = requestIdByStream.get(this)
  if (id !== undefined) processChunk(chunk, id)
}

function processChunk(chunk, id) {
  /* ... */
}

function handleRequest(req) {
  requestIdByStream.set(stream, req.id)
  stream.on('data', onData)
}
ts
// BEST — pre-allocate the callback as a method on a context object
class StreamProcessor {
  id: string
  constructor(id: string) {
    this.id = id
  }
  handleChunk(chunk: Uint8Array) {
    processChunk(chunk, this.id)
  }
}
Avoid Allocations in Tight Loops
ts
// BAD — allocates a new object per iteration
for (const item of items) {
  doSomething({ key: item.key, value: item.value })
}

// GOOD — reuse a mutable scratch object
const scratch = { key: '', value: '' }
for (const item of items) {
  scratch.key = item.key
  scratch.value = item.value
  doSomething(scratch)
}
Real Codebase Example

node-stream-helpers.ts hoists encoder, BUFFER_TAGS, and tag constants to module scope to avoid re-creating them on every request. The bufferIndexOf helper uses Buffer.indexOf (C++ native) instead of a per-call JS loop, eliminating per-chunk allocation.

Array Optimizations

V8 tracks array "element kinds" — an internal type tag that determines how elements are stored in memory:

Element KindDescriptionSpeed
PACKED_SMISmall integers only, no holesFastest
PACKED_DOUBLENumbers only, no holesFast
PACKED_ELEMENTSMixed/objects, no holesModerate
HOLEY_*Any of above with holesSlower (extra bounds check)

Transitions are one-way — once an array becomes HOLEY or PACKED_ELEMENTS, it never goes back.

Rules
  • Pre-allocate arrays with known size: new Array(n) creates a holey array. Prefer [] and push(), or use Array.from({ length: n }, initFn).
  • Don't create holes: arr[100] = x on an empty array creates 100 holes.
  • Don't mix types: [1, 'two', {}] immediately becomes PACKED_ELEMENTS.
  • Prefer typed arrays only when you need binary interop/contiguous memory or have profiling evidence that they help. For small/short-lived collections, normal arrays can be faster and allocate less.
ts
// GOOD — packed SMI array
const indices: number[] = []
for (let i = 0; i < n; i++) {
  indices.push(i)
}

// BAD — holey from the start
const indices = new Array(n)
for (let i = 0; i < n; i++) {
  indices[i] = i
}
Show full SKILL.md (404 more words)Show less
Real Codebase Example

accumulateStreamChunks in app-render.tsx uses const staticChunks: Array<Uint8Array> = [] with push() — keeping a packed array of a single type throughout its lifetime.

Function Optimization and Deopts

Hot-Path Deopt Footguns
  • arguments object: using arguments in non-trivial ways (e.g. arguments[i] with variable i, leaking arguments). Use rest params instead.
  • Type instability at one call site: same operation sees both numbers and strings (or many object shapes) and becomes polymorphic/megamorphic.
  • eval / with: prevents optimization entirely.
  • Highly dynamic object iteration: avoid for...in on hot objects; prefer Object.keys() / Object.entries() when possible.
Favor Predictable Control Flow
ts
// GOOD — predictable: always returns same type
function getStatus(code: number): string {
  if (code === 200) return 'ok'
  if (code === 404) return 'not found'
  return 'error'
}

// BAD — returns different types
function getStatus(code: number): string | null | undefined {
  if (code === 200) return 'ok'
  if (code === 404) return null
  // implicitly returns undefined
}
Watch Shape Diversity in switch Dispatch
ts
// WATCH OUT — `node.type` IC can go megamorphic if many shapes hit one site
function render(node) {
  switch (node.type) {
    case 'div':
      return { tag: 'div', children: node.children }
    case 'span':
      return { tag: 'span', text: node.text }
    case 'img':
      return { src: node.src, alt: node.alt }
    // Many distinct node layouts can make this dispatch site polymorphic
  }
}

This pattern is not always bad. Often the main pressure is at the shared dispatch site (node.type), while properties used only in one branch stay monomorphic within that branch. Reach for normalization/splitting only when profiles show this site is hot and polymorphic.

String Operations

  • String concatenation in loops is usually fine in modern V8 (ropes make many concatenations cheap). For binary data, use Buffer.concat().
  • Template literals vs concatenation: equivalent performance in modern V8, but template literals are clearer.
  • string.indexOf() > regex for simple substring checks.
  • Reuse RegExp objects: don't create a new RegExp() inside a hot function — hoist it to module scope.
ts
// GOOD — regex hoisted to module scope
const ROUTE_PATTERN = /^\/api\//

function isApiRoute(path: string): boolean {
  return ROUTE_PATTERN.test(path)
}

// BAD — regex recreated on every call
function isApiRoute(path: string): boolean {
  return /^\/api\//.test(path) // V8 may or may not cache this
}

Map and Set vs Plain Objects

  • Map is faster than plain objects for frequent additions/deletions (avoids hidden class transitions and dictionary mode).
  • Set is faster than obj[key] = true for membership checks with dynamic keys.
  • For static lookups (known keys at module load), plain objects or Object.freeze({...}) are fine — V8 optimizes them as constant.
  • Never use an object as a map if keys come from user input (prototype pollution risk + megamorphic shapes).

Profiling and Verification

V8 Flags for Diagnosing JIT Issues
bash
# Trace which functions get optimized
node --trace-opt server.js 2>&1 | grep "my-function-name"

# Trace deoptimizations (critical for finding perf regressions)
node --trace-deopt server.js 2>&1 | grep "my-function-name"

# Combined: see the full opt/deopt lifecycle
node --trace-opt --trace-deopt server.js 2>&1 | tee /tmp/v8-trace.log

# Show IC state transitions (verbose)
node --trace-ic server.js 2>&1 | tee /tmp/ic-trace.log

# Print optimized code (advanced)
node --print-opt-code --code-comments server.js
Targeted Profiling in Next.js
bash
# Profile a production build
node --cpu-prof --cpu-prof-dir=/tmp/profiles \
  node_modules/.bin/next build

# Profile the server during a benchmark
node --cpu-prof --cpu-prof-dir=/tmp/profiles \
  node_modules/.bin/next start &
# ... run benchmark ...
# Analyze in Chrome DevTools: chrome://inspect → Open dedicated DevTools

# Quick trace-deopt check on a specific test
node --trace-deopt $(which jest) --runInBand test/path/to/test.ts \
  2>&1 | grep -i "deopt" | head -50
Using % Natives (Development/Testing Only)

With --allow-natives-syntax:

js
function hotFunction(x) {
  return x + 1
}

// Force optimization
%PrepareFunctionForOptimization(hotFunction)
hotFunction(1)
hotFunction(2) % OptimizeFunctionOnNextCall(hotFunction)
hotFunction(3)

// Check optimization status
// 1 = optimized, 2 = not optimized, 3 = always optimized, 6 = maglev
console.log(%GetOptimizationStatus(hotFunction))

Checklist for Hot Path Code Reviews

  • All object properties initialized in constructor/literal, same order
  • No delete on hot objects
  • No post-construction property additions on hot objects
  • Functions receive consistent types (monomorphic call sites)
  • Type dispatch happens at boundaries, not deep in hot loops
  • No closures allocated inside tight loops
  • Module-scope constants for regex, encoders, tag buffers
  • Arrays are packed (no holes, no mixed types)
  • Map/Set used for dynamic key collections
  • No arguments object — use rest params
  • try/catch at function boundary, not inside tight loops
  • String building via array + join() or Buffer.concat()
  • Return types are consistent (no string | null | undefined mixes)
  • $dce-edge — DCE-safe require patterns (compile-time dead code)
  • $runtime-debug — runtime bundle debugging and profiling workflow

© vercel, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .agents/skills/v8-jit of vercel/next.js.

Open the folder on GitHubat commit a32ddfd

Compare with similar skills

V8 Jit next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

V8 Jit compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
V8 Jit this skillvercel/next.js143k—~3.6kAutomated safety check: PassMIT
Qstash JSupstash/qstash-js2691 repos~746Automated safety check: PassMIT
Holm Webvolfpeter/holm132—~1.2kAutomated safety check: PassMIT
Documentation Guidevolfpeter/holm132—~1.4kAutomated safety check: PassMIT
Apollo Clientapollographql/skills117—~1.9kAutomated safety check: PassMIT
Nextjs Turbopackkurealnum/dotfiles2905 repos~540Automated safety check: PassNone

Similar skills

  • Qstash JS

    upstash/qstash-js

    Official

    Work with the QStash JavaScript/TypeScript SDK for serverless messaging, scheduling.

    269 GitHub starsUsed in 1 repo~746 tokens
    Backend & APIsAuto-check passed
  • Holm Web

    volfpeter/holm

    A skill your agent uses when working on web apps built with holm, or to answer questions about holm.

    132 GitHub stars~1.2k tokensUpdated 21 days ago
    Backend & APIsAuto-check passed
  • Documentation Guide

    volfpeter/holm

    A skill your agent uses when writing or modifying documentation, guides, or example READMEs.

    132 GitHub stars~1.4k tokensUpdated 21 days ago
    Backend & APIsAuto-check passed
  • Apollo Client

    apollographql/skills

    Guide for building React applications with Apollo Client 4.x.

    117 GitHub stars~1.9k tokensUpdated today
    Backend & APIsAuto-check passed
  • Nextjs Turbopack

    kurealnum/dotfiles

    Next.js 16+ and Turbopack — incremental bundling, FS caching, dev speed, and when to use Turbopack vs webpack.

    290 GitHub starsUsed in 5 repos~540 tokens
    Backend & APIsAuto-check passed
  • Wp Headless And Wpgraphql

    jorgerosal/wordpress-skills

    Headless WordPress and WPGraphQL review guidance. An agent skill from jorgerosal/wordpress-skills.

    101 GitHub stars~1.7k tokensUpdated 4 mo ago
    Backend & APIsAuto-check passed

More from vercel/next.js

All 27 skills in this repo
  • Gh Stack

    vercel/next.js

    Official

    Manages stacked PRs and splits multi-part work into reviewable branches with gh-stack.

    143k GitHub starsUsed in 7 repos~2.3k tokens
    Auto-check passed
  • Sandbox Bench

    vercel/next.js

    Official

    Benchmark React or Next.js changes on Vercel Sandbox VMs with paired A/B statistics: react PR/commit vs base, or Next.js PR/commit vs base, measured end-to-end through the bench/render-pipeline app…

    143k GitHub stars~4.1k tokensUpdated today
    Auto-check passed
  • Next Dev Loop

    vercel/next.js

    Official

    Verify Next.js runtime behavior after editing app code. An agent skill from vercel/next.js.

    143k GitHub starsUsed in 9 repos~2.3k tokens
    Auto-check passed
  • Docs Diagrams

    vercel/next.js

    Official

    Draw diagrams for the Next.js docs in the style of the ones already published there: the light/dark PNGs an mdx references with <Image srcLight="/docs/light/<name.png" srcDark="/docs/dark/<name.png".

    143k GitHub stars~2.9k tokensUpdated today
    Auto-check passed
  • Official

    Turn on Cache Components in a Next.js app and resolve the blocking routes it surfaces.

    143k GitHub starsUsed in 6 repos~8.3k tokens
    Auto-check passed
  • React Sync

    vercel/next.js

    Official

    Build local React changes in the bundle variants consumed by Next.js, sync them into a local Next.js checkout, and test the resulting integration.

    143k GitHub stars~486 tokensUpdated today
    Auto-check passed

Categories

Questions about V8 Jit

What does V8 Jit do?

V8 JIT optimization patterns for writing high-performance JavaScript in Next.js server internals. js, published by the product's own GitHub organization.js server internals.

When should I use V8 Jit?

V8 Jit fits situations like: reviewing hot-path code in app-render; any per-request code path.

How do I install V8 Jit in Claude Code?

Run `npx skills add vercel/next.js --skill v8-jit -a claude-code`. Or copy the skill folder (.agents/skills/v8-jit in vercel/next.js) into .claude/skills/v8-jit in your project. Claude Code loads it when a task matches its description.

How do I install V8 Jit in Codex?

Run `npx skills add vercel/next.js --skill v8-jit -a codex`. Or copy the skill folder (.agents/skills/v8-jit in vercel/next.js) into .agents/skills/v8-jit in your project. Codex loads it when a task matches its description.

Can I use V8 Jit in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add vercel/next.js --skill v8-jit -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/v8-jit, .gemini/skills/v8-jit, .github/skills/v8-jit and .opencode/skills/v8-jit in your project.

What does V8 Jit need to run?

Going by SKILL.md and its folder, V8 Jit needs the command-line tools its instructions call (node). Our summary lists: Node.js.

Does V8 Jit access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is V8 Jit safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does V8 Jit use?

V8 Jit is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does V8 Jit use?

About 3.6k tokens (SKILL.md is roughly 14k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to V8 Jit?

Skills that share tags, products or a category with V8 Jit: Qstash JS (upstash/qstash-js, 269 stars), Holm Web (volfpeter/holm, 132 stars), Documentation Guide (volfpeter/holm, 132 stars) and Apollo Client (apollographql/skills, 117 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains V8 Jit?

vercel (a GitHub organization, an official publisher) maintains it in vercel/next.js, which has 143,241 GitHub stars. The repository holds 27 skills in this directory. The repository was last updated on October 8, 2026.

Source: vercel/next.js on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.