---
title: Troubleshoot and optimize Function Invocations on Vercel
description: Diagnose which routes drive Function Invocations and learn to optimize them. Separate necessary dynamic traffic from divertible requests, fix common invocation patterns, and verify the change after shipping.
url: /kb/guide/optimize-function-invocations
canonical_url: "https://vercel.com/kb/guide/optimize-function-invocations"
published: 2026-09-08
last_updated: 2026-09-08
authors: Mike Darlington
related:
  - /docs/functions/usage-and-pricing
  - /kb/guide/understand-cost-impact-of-function-invocations
  - /docs/caching/cache-status
  - /docs/vercel-firewall
  - /docs/bot-management
  - /docs/vercel-blob/client-upload
  - /docs/agent-resources/vercel-plugin
  - /docs/observability/insights
  - /docs/query/reference
  - /docs/caching
  - /kb/guide/optimize-active-cpu-on-fluid-compute
install_vercel_plugin: npx plugins add vercel/vercel-plugin
---

This guide investigates rising Function Invocations from a billing and usage perspective. If your invoice or the Usage page shows the number climbing, common causes include a route that opted into dynamic rendering unexpectedly, prefetch or bot traffic you didn't intend to serve, a client polling an API more often than the product needs, or uploads routed through a Function.

Under [Fluid compute](https://vercel.com/docs/functions/usage-and-pricing), a request that reaches a Function is an invocation, and you're billed per invocation, whether the Function succeeds or fails. A page built at deploy time is served from the CDN, so its requests never reach a Function and create zero invocations. That asymmetry is the playbook. First, find which routes requests are reaching. Second, divert the requests that don't need a Function. Serve them from the CDN cache, stop prefetch and bot traffic you don't want, quiet chatty clients, and move payloads out of the Function path.

In this guide, you’ll learn how to:

- Confirm the rising metric is Function Invocations, not Middleware invocations or CDN Requests
  
- Find the routes driving Function Invocations
  
- Decide how each route should serve
  
- Fix the most common invocation-heavy patterns
  
- Run a safe, read-only agent investigation
  
- Verify a change after shipping
  

## Before 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, or time windows can make traffic changes look like billing changes.

## 1\. Confirm the usage source

In the dashboard, select the team and open the [Usage page](https://vercel.com/d?to=%2F%5Bteam%5D%2F%7E%2Fusage&title=Open+Usage). Navigate to **Functions** → **Function Invocations**. The **Count** view shows the total amount of invocations across your projects.

Confirm you’re looking at the right metric before going route-level: Middleware invocation counts appear in a separate **Middleware** observability tab rather than the **Vercel Functions** tab, and if you suspect automated traffic, the **CDN Requests** observability surface has bot and bot-category breakdowns.

## 2\. Find the routes driving invocations

For project-level investigation, go to **Observability** → **Vercel Functions**. This view allows you to rank routes by invocations and drill into a specific route’s count and latency distribution. Follow the [Observability route drill-down guide](https://vercel.com/kb/guide/understand-cost-impact-of-function-invocations) to identify which routes are driving your usage.

Open **Observability** → **New Query** and navigate to **Visualize** → **Function Invocations** to analyze usage with more precision. Query supports **Count**, **Count per Second**, and **Percentages** for this metric. You can group or filter by route, request path, cache result, request method, referrer URL, client IP, and client user agent. Full Query access requires Observability Plus, available on Enterprise and Pro plans. With free observability you can open a query, but modifying filters or creating new queries needs the subscription. Without it, the Vercel Functions view above covers route-level ranking.

For example, suppose the Usage page shows 20.9K invocations this week, and Query grouped by route attributes 9.1K of them, about 43.5%, to `/api/factory`, almost all with a cache result of **MISS**. Cache status is returned on every response in the x-vercel-cache header and appears as the cache result dimension in Query. That one route is your optimization target: an API endpoint polled by every open tab is a caller problem, and a dynamic page that could tolerate sixty seconds of staleness is a caching problem. The next step separates the two.

## 3\. Interpret the pattern

For each high-volume route, ask how its response varies, then pick the serving model that matches:

| How the response varies                                                    | Serve it via                              | Effect on invocations                                                                                                                                                                                                                                                                                                                                         |
| -------------------------------------------------------------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Same for everyone                                                          | Static site generation                    | Zero: no Function runs per request                                                                                                                                                                                                                                                                                                                            |
| Changes on a schedule or when your data changes, tolerates brief staleness | ISR, time-based or on-demand revalidation | Cached responses serve without invoking; revalidations still run the Function                                                                                                                                                                                                                                                                                 |
| Dynamic, but briefly cacheable                                             | `Cache-Control` headers on the response   | Repeat requests become CDN **HIT**s and don’t invoke                                                                                                                                                                                                                                                                                                          |
| Genuinely per-user or per-request                                          | Stays dynamic                             | Reduce the requests themselves. See [prefetch](https://vercel.com/kb/guide/optimize-function-invocations#request-amplification-and-rsc-traffic), [bots](https://vercel.com/kb/guide/optimize-function-invocations#automated-traffic-and-bots), [chatty clients](https://vercel.com/kb/guide/optimize-function-invocations#chatty-application-endpoints) below |

## 4\. Common causes and fixes

### Caching and dynamic rendering

The [cache-status values](https://vercel.com/docs/caching/cache-status) tell you what each request did:

- **HIT** serves the response without invoking a Function, and an ISR cache hit behaves the same way.
  
- **STALE** serves the cached response immediately while a Function is re-invoked in the background.
  
- **BYPASS**, such as one triggered by Draft Mode or a bypass token, skips the cached prerender and invokes a Function for a fresh response.
  
- **MISS** can generate a response from a Function or from an origin, so a MISS alone does not prove which one ran.
  

ISR reduces invocations by serving cached content, but the Function still runs during background or on-demand revalidation. For simultaneous requests to the same uncached ISR path, Vercel collapses the misses into one Function invocation per region.

For Next.js App Router, identify your rendering model to avoid unexpected dynamic execution:

- **Classic model (pre-Cache Components):** Using `cookies()`, `headers()`, or the page `searchParams` prop opts the entire route into dynamic rendering. Uncached `fetch` calls or `revalidate: 0` also make the route dynamic.
  
- **Cache Components (Next.js 16):** These APIs do not automatically opt the whole route into dynamic rendering. You can place request-time work behind `Suspense` to preserve a prerendered shell. Applying `use cache` to both the layout and page can prerender the entire route. Cache Components and `use cache` were unified under the stable `cacheComponents` model in Next.js 16.0.
  

**Upgrade Note:** In Next.js 14, `GET` Route Handlers were cached by default. Starting in Next.js 15, the default changed to dynamic, review `GET` handlers that relied on the old static default.

**Note on Data Cache:** In current Next.js, the Data Cache and Vercel Runtime Cache store data fetched during Function execution, and are distinct from the full-response CDN cache.

### Request amplification and RSC traffic

Traffic volume can rise unexpectedly due to framework prefetching and React Server Component (RSC) requests: navigations and prefetches fetch server-rendered payloads for the destination route, so they show up in Query as additional requests against that route’s path, distinct from full page loads. Requests served from the CDN cache do not reach the Function.

On the App Router, prefetch behavior depends on the route and its rendering mode, and setting `prefetch={false}` on a `<Link>` disables viewport and hover prefetching. Where traced prefetch traffic is unnecessary, disable or narrow prefetching. Prefetching exists to make navigation feel instant, so narrowing it trades some navigation speed for fewer requests. Because the volume depends on the route and its rendering mode, measure it on your own routes rather than estimating it.

### Automated traffic and bots

Automated clients can concentrate requests on dynamic routes. Vercel documents bot and bot-category breakdowns in the **CDN Requests** observability surface. That breakdown is not scoped to traffic that reached a Function, so attribute Function traffic by route, method and user agent in Query instead. For information on blocking unwanted traffic, see the [Vercel Firewall](https://vercel.com/docs/vercel-firewall) and [Bot Management](https://vercel.com/docs/bot-management) documentation.

### Chatty application endpoints

Internal API, auth, or session routes may receive more calls than required by product behavior. Redundant polling or refresh calls drive up costs because every one of them reaches the Function. Use Query to group invocations by route and client user agent to identify chatty callers, then remove or consolidate only the calls the application does not need. Use platform redirects to handle URL changes at the CDN layer, avoiding a Function invocation.

### Function-proxied uploads

Large client payloads that traverse a Function only to reach storage add unnecessary execution. [Vercel Blob client uploads](https://vercel.com/docs/vercel-blob/client-upload) use a token exchange and an `onUploadCompleted` callback, so the browser sends the payload directly to storage. This removes the payload from the Function path. The token and callback steps remain part of the workflow.

## 5\. 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 name, production environment, the specific window where invocations increased, and any recent framework upgrades or deployment changes. Have the agent tie each finding to one of the causes above and propose the matching fix from that section.

### Agent prompt

To get started with your coding agent, copy and adapt this prompt:

```plaintext
Investigate why Function Invocations 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 Invocations by route over the same team, project,
environment, and window:

  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 Vercel 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

Identify whether the increase is driven by unexpected dynamic rendering, prefetch
traffic, automated bots, or chatty clients. Inspect Route Handlers, Server Actions,
and layouts for dynamic API usage. Group results by cache result where available and
distinguish CDN HITs from background revalidations — treat only a plain HIT as a
result that did not invoke a Function. Return route evidence and a baseline before
recommending changes. Do not edit, deploy, change settings, purge caches, or mutate
data without my explicit approval.
```

### Vercel Plugin

The [Vercel Plugin](https://vercel.com/docs/agent-resources/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 Vercel tools. The plugin is optional; it isn’t required to follow this guide.

```bash
npx plugins add vercel/vercel-plugin
```

## 6\. Verify the fix

After deploying your changes, compare the same route and selected time range in **Vercel Functions** observability before and after the change.

Check the following indicators:

- Total Function invocations for the route
  
- Cache result distribution, where a response-cache change should show the intended traffic producing plain **HIT** responses
  
- Error rate
  
- Traffic sources by user agent, if you changed prefetch or bot handling
  

Do not treat a lower total as proof by itself. Traffic may have dropped, or the route mix may have changed. A strong fix should reduce invocations for the affected route across comparable windows, such as the same weekday and traffic period, without increasing errors.

## Related resources

- [Fluid compute usage and pricing](https://vercel.com/docs/functions/usage-and-pricing)
  
- [Vercel Functions observability](https://vercel.com/docs/observability/insights#vercel-functions)
  
- [Vercel Query reference](https://vercel.com/docs/query/reference)
  
- [Vercel caching](https://vercel.com/docs/caching)
  
- [Active CPU usage on Fluid compute](https://vercel.com/kb/guide/optimize-active-cpu-on-fluid-compute)