Active CPU reflects the compute time your code is actively executing on a virtual CPU. When it climbs, the cause is usually one of two things: you're serving more traffic, or each request is doing more CPU work than it used to. A project-level chart can confirm the increase, but the useful question is route-level: which routes changed, and did traffic rise, or did the work per request get heavier?
Vercel Observability gives you route-level views and filters to make that comparison and verify the impact after you ship a change. Use it to inspect requests, resource usage, function duration, invocations, regions, and time windows, then verify whether a change reduced CPU per invocation after deployment.
In this guide, you'll learn how to:
- Identify the routes driving Active CPU usage
- Separate traffic growth from per-request CPU growth
- Find and fix the most common CPU-heavy patterns
- Run a safe, read-only agent investigation
- Verify a change after shipping
Copy link to headingUnderstand Active CPU
In Fluid compute, Active CPU is the CPU time your code consumes. It excludes time spent waiting on external I/O. These signals measure different parts of function usage:
| Signal | What it means |
|---|---|
| Active CPU | Time spent actively executing code |
| Function invocations | Number of function requests |
| Active CPU per invocation | Approximate CPU work per request |
| Invocation duration | Wall-clock time, including waiting and streaming |
| Provisioned memory | Memory allocated while requests are in flight |
Parsing, serializing, transforming responses, rendering pages, compiling content, hashing, compression, and image generation can all increase Active CPU. Waiting on external I/O usually increases duration, not Active CPU.
Copy link to headingBefore you begin
Choose the scope you want to investigate:
- Team
- Project
- Environment
- Increase window
- Comparison window
- Recent deployment or release window, if known
Use the same scope throughout the investigation. Comparing different environments, routes, status codes, or time windows can make traffic changes appear to be CPU changes.
Copy link to heading1. Confirm the usage source
First, confirm which compute products contribute to the selected usage. Routing Middleware also uses Fluid compute, and Active CPU pricing, so disabling Fluid for regular Functions does not, by itself, remove every Active CPU source.
In the Vercel dashboard:
- Select the team.
- Open Usage.
- Choose the relevant time window.
- Filter to the affected project.
- Compare Active CPU with Function invocations and provisioned memory.
- Check whether usage is concentrated in a region, project, or compute source.
This confirms whether you are investigating the right project and product area before moving into route-level analysis.
Copy link to heading2. Find the routes driving Active CPU
After confirming the project-level increase, use route-level data.
- In the Vercel dashboard, Open Observability.
- Go to the Functions view.
- Select the same environment and time window.
- Use the route list to compare Active CPU and invocations.
- For each hot route, calculate Active CPU per invocation:
For example, a route with 22 seconds of Active CPU across 2200 invocations uses about 10 ms of Active CPU per invocation.
If you have Query enabled, you can inspect the same pattern more directly:
- Chart Function CPU Time with the
Sumaggregation. - Group by route.
- Filter to the same project, environment, and time window.
- Repeat with Function Invocations.
- Compare CPU per invocation across the current and previous windows.
Do not act on a project-wide chart alone. Rank routes by route-level usage, then compare like-for-like windows.
Copy link to heading3. Interpret the pattern
Use the route-level comparison to decide where to start.
| What changed | Likely cause | Start with |
|---|---|---|
| Active CPU and invocations both increased | More traffic or a changed request mix | Request amplification, bots, route mix, caching |
| Active CPU per invocation increased | More CPU work per request | Rendering, transforms, compilation, media work |
| Duration increased, but Active CPU did not | More waiting or streaming | Upstream APIs, databases, and long responses |
| Active CPU increased with errors or cold starts | Process errors or repeated initialization | Runtime Logs, startup code, uncaught exceptions |
| Active CPU stayed stable, but memory rose | Longer in-flight requests | Streaming, slow I/O, provisioned memory |
If CPU per invocation rose for a hot route, begin with repeated rendering, compilation, and per-request transformation. If total Active CPU rose while CPU per invocation stayed stable, begin with traffic growth, request amplification, and cache behavior.
Copy link to heading4. Common causes and fixes
Copy link to headingRequest amplification and traffic mix
If the total Active CPU increased while the CPU per invocation stayed stable, investigate request amplification before changing the hot-path code.
Check the following:
- Framework or deployment changes
- Prefetch behavior
- Route mix changes
- Automated traffic
- Bot traffic
- Cache misses on high-volume routes
The Edge Requests view can help show whether new request volume, rather than new CPU-heavy code, caused the increase. Caching can reduce Active CPU when responses are safe to cache. Requests served from the CDN cache do not invoke the function.
Copy link to headingRepeated rendering and compilation
If a route has high CPU per invocation and frequent cache misses, inspect rendering and compilation work. Check for:
- Dynamic rendering, where static or cached output would be safe
- Per-request MDX or markdown compilation
- Rebuilding the same page shell for every request
- Repeated data formatting or transformation
- Cache headers that prevent eligible responses from being cached
For Next.js App Router, identify the caching model before editing:
- If your app runs without Cache Components, request-time APIs such as
cookies(),headers(), the page'ssearchParamsprop, andconnection(), along withfetch(..., { cache: 'no-store' }), can make a route render dynamically. Use explicit fetch caching or revalidation only when freshness and privacy requirements allow it. - With Cache Components, use
use cachefor stable work that you can include in prerendered output, and put request-time work belowSuspenseso the surrounding shell can stay prerendered. For shared request-time reuse, follow Runtime Cache guidance; treat the default in-memory cache state as per-instance and ephemeral rather than shared storage.
If a hot route compiles stable MDX or markdown per request, compile it during the build. Otherwise, cache only when sharing, freshness, and privacy permit it.
Copy link to headingPer-request transforms and media work
Inspect hot handlers for large JSON parsing, transformation, and serialization pipelines. Because Active CPU counts code execution, selecting only the needed rows and fields before data reaches the function reduces work. Check hot handlers for:
- Large JSON parsing
- Expensive object transformations
- Unbounded loops over large result sets
- Repeated compression
- Per-request image generation
- Per-request Open Graph image generation
- Duplicate password hashing or cryptographic work
Reduce the amount of data that reaches the function by selecting only the needed rows and fields upstream. Avoid recompressing unchanged output and cache reusable compression results when safe.
For image or Open Graph generation, pregenerate invariant Open Graph images or cache eligible outputs. Do not weaken password-hashing parameters to reduce CPU; remove duplicate work around the security control instead.
Copy link to headingWaiting on background work
Use the preloading pattern to start independent I/O together. This can shorten wall time, but work between awaits still consumes Active CPU.
Next.js after() and Vercel waitUntil() can finish the response first, but work continues within the function lifecycle. CPU-intensive background work still consumes Active CPU.
Copy link to headingUncaught errors and process stops
Check Runtime Logs for process-level errors. Under Fluid compute error isolation, Vercel logs the error, lets current requests finish, and then stops the affected process.
After fixing the error, compare:
- Error rate
- Cold starts
- Invocations
- Active CPU per invocation
- Affected routes
A handled 5xx response does not by itself prove that the process stopped. Look for process-level errors and matching runtime signals.
Copy link to headingAdjust memory for CPU-bound functions
For CPU-bound functions, test the memory setting. More memory provides more CPU and can reduce Active CPU time, but it can also increase provisioned memory.
After changing the memory, compare both:
- Active CPU per invocation
- Provisioned memory
Low average CPU throttling can be normal. If high throttling coincides with latency or timeouts, test a larger memory configuration and verify the tradeoff.
Copy link to heading5. Investigate with an agent
If you want an agent to investigate, start with read-only access and require route-level evidence before approving changes. Provide the team scope, project, production environment, exact increase window, hot routes, deployment IDs, and recent releases.
To get started with your coding agent, copy and adapt this prompt:
Investigate why Fluid Active CPU increased for <project> in <team> during <window>. Start read-only. First, inspect the metrics schema for that team scope — it is the source of truth for available metrics: vercel metrics schema --scope <team> --format json Where available, query Function CPU Time and Invocations by route over the same team, project, environment, and window, then derive CPU per invocation from the matching totals: vercel metrics <cpu-metric-id> --scope <team> --project <project> --prod --since <start> --until <end> --aggregation sum --group-by route --order-by value --limit 50 --format json vercel metrics <invocation-metric-id> --scope <team> --project <project> --prod --since <start> --until <end> --aggregation sum --group-by route --order-by value --limit 50 --format json If grouped results truncate a route you care about, re-run with a --filter on that route. If Function metrics are unavailable (they require Observability Plus), use the dashboard's Functions view instead and say so in your findings. Corroborate with deployment metadata and runtime logs: vercel list <project> --scope <team> --environment production --status READY vercel inspect <deployment-id-or-url> --scope <team> vercel logs --scope <team> --project <project> --environment production --since <start> --until <end> --no-branch --json Note that `vercel inspect --logs` prints build output, not Active CPU evidence. Then inspect hot Route Handlers, Server Actions, layouts/pages, dynamic rendering, uncached fetches, loops, transformations, background work, and upstream latency. If cold starts or Node.js process stops rise, inspect the startup and module-scope initialization. Return route evidence, the trigger, and a baseline before recommending changes. Do not edit, deploy, change settings, purge caches, or mutate data without my explicit approval.
Copy link to headingVercel Plugin
The Vercel Plugin turns your AI coding agent (e.g., OpenAI Codex, Claude Code, or Cursor) into a Vercel expert. It adds skills, slash commands, and current knowledge of the tools this template uses, including Vercel Connect, Vercel Blob, and AI Gateway. The plugin is optional; it isn't required to follow this guide.
Copy link to heading6. Verify the fix
After deploying one change, compare the same route across comparable windows.
Check the following indicators:
- Function CPU Time divided by Function invocations
- Total Function invocations
- Error rate
- Cache status
- Duration
- Provisioned memory
Use the same route, environment, status, and time window shape. For example, compare the same weekday and traffic period before and after deployment.
Do not treat a lower total Active CPU as proof by itself. Traffic may have dropped, the route mix may have changed, or errors may have prevented work from completing. A strong fix should reduce Active CPU per invocation for the affected route without increasing errors or introducing unintended caching behavior.