Vercel FastAPI Cuts Function Use for Static Files

Vercel now serves eligible FastAPI assets from its CDN. See which requests stop using Functions and which protected paths still need them.

Sunday, September 13, 2026Omid Saffari
Tools
Vercel FastAPI Cuts Function Use for Static Files

Vercel changed one cost line for FastAPI apps on September 10, 2026. Eligible frontend and static-file requests now go from Vercel's CDN straight to the visitor, so they stop creating Function invocations and compute usage. CDN requests and transfer still exist, which is why this cuts Function use instead of making static delivery free.

The request skips the Function now

A static file is something the server can send as-is, such as an HTML file, stylesheet, JavaScript bundle, font, or image. A Vercel Function is the running FastAPI process that handles dynamic requests. The CDN is the delivery layer close to the visitor.

Before this change, a file mounted through FastAPI could still take the Function path. The request reached Vercel's network, invoked the FastAPI Function, and let Python return the file.

Now Vercel finds eligible files behind app.frontend() and FastAPI's StaticFiles during the build. It promotes those files to the CDN, and matching requests are served without invoking the Function.

That changes the path from this:

visitor → CDN → FastAPI Function → file → visitor

to this:

visitor → CDN file → visitor

The dynamic API does not become static. Only matching files move. Files in the project-level public/ directory were already served from the CDN, so apps that put every public asset there do not get a new saving from this release.

Promoted directories also stay inside the Function bundle by default. Setting tool.vercel.fastapi.static.exclude = true removes that duplicate copy, but it is a separate bundle decision. You do not need it for the CDN request path to work.

An architectural section showing public FastAPI assets taking a short path from a visitor through the CDN while protected assets pass through the Function and its guard
Public assets can stop at the CDN. Protected assets still need the Function when FastAPI must check the request.

The bill loses compute, not delivery

Vercel meters a request in layers. Function Invocations count requests that reach your code. Active CPU and Provisioned Memory measure the work and runtime resources behind those invocations. Fast Origin Transfer measures traffic between the CDN and the Function.

The outer delivery meters are different. CDN Requests, shown as Edge Requests in the dashboard, apply to both static assets and Function traffic. Fast Data Transfer measures the bytes sent between the CDN and the visitor.

Here is the clean ledger for one million otherwise identical asset requests that reached the Function before deployment and qualify for promotion after deployment:

MeterBefore promotionAfter promotion
Function Invocations1 million0
Active CPU for those requestsMeasured0
Provisioned Memory for those requestsMeasured0
Fast Origin Transfer for those responsesMeasured0
CDN Requests or Edge Requests1 million1 million
Fast Data Transfer to visitorsMeasured bytesMeasured bytes

The published Pro rate is $0.60 per one million Function invocations. So one million file requests that previously reached the Function remove $0.60 of gross invocation usage before the monthly credit, plus whatever Active CPU, Provisioned Memory, and Fast Origin Transfer those requests actually consumed.

That last part must come from your Usage data. A file response that barely touched Python has little CPU to remove. A large response can have more origin transfer to remove. The release gives you a new route, not a universal savings percentage.

CDN usage remains on the other side of the ledger. Vercel's current CDN pricing page lists the first 10 million Edge Requests and first 1 TB of Fast Data Transfer as included on Pro under on-demand billing, followed by region-based usage rates. Teams using Flat Rate CDN consume that plan's request and transfer capacity instead. The Flat Rate CDN explainer covers that separate budget decision.

For Hobby, the benefit can be headroom instead of a smaller cash bill. Hobby includes one million Function invocations, four Active CPU hours, and 360 GB-hours of Provisioned Memory. Public file traffic that no longer reaches the Function stops eating those allowances, while its CDN delivery still counts where applicable.

Eligibility follows your route and security rules

Vercel preserves FastAPI's declaration order for StaticFiles. A route declared before a static mount wins at the same path and reaches the Function. A route declared after the mount loses to the CDN file.

app.frontend() is slightly different. API routes always take priority over frontend files, regardless of declaration order. That keeps a frontend mounted at / from swallowing a real API endpoint.

Security changes the default too. A CDN file never enters Python, so FastAPI middleware and Depends() checks cannot run on it. Vercel therefore keeps these paths on the Function by default:

  • All static mounts and frontends when the app has top-level middleware.
  • A sub-app's static mounts when that sub-app has middleware.
  • A frontend guarded by FastAPI dependencies.

Setting cdn = false makes the opposite trade. It disables promotion and keeps every matching request on the Function. That is a valid choice when application code must inspect each request.

There is one smaller edge case: the bare root of a StaticFiles mount still reaches the Function so FastAPI can redirect it to the trailing-slash form. Do not expect a literal zero in Function usage if clients keep requesting that bare path.

Where this changes the work

A solo SaaS founder with one FastAPI repo

A founder serving a bundled web app through app.frontend() can leave the API dynamic and move the public HTML, CSS, and JavaScript traffic off the Function path. The payoff is a cleaner compute baseline. Product traffic can grow without every browser asset fetch looking like backend work.

An agency engineer with public and client-only files

An agency engineer can place the public shell on the CDN while declaring a sensitive route before the static mount. The payoff is not just lower Function use. It is a route map that says which client files require Python to make an access decision and which do not.

A backend lead working with finance

A backend lead can give finance two separate forecasts: dynamic FastAPI traffic for the Function line, and all visitor traffic for the CDN line. The payoff is that a fall in Function Invocations is no longer mistaken for a matching fall in Edge Requests or transfer.

A team with global middleware

A team using top-level logging, tenant resolution, or authentication middleware should expect static mounts to stay on the Function by default. The useful move is to decide whether a clearly public asset area can bypass that middleware. If the answer is no, there is no safe saving to budget from this change.

Audit one deployment

Start from a real route inventory, not the assumption that every file with an extension is public.

  1. Mark public and protected paths

    List every app.frontend() directory and StaticFiles mount. Mark the files that can be returned to any visitor. Separately mark anything whose response depends on a user, tenant, role, cookie, or request-time middleware result.

  2. Check declaration order

    Keep a Function route before a StaticFiles mount when that route must win. This is Vercel's documented pattern:

    Python
    from fastapi import FastAPI
    from fastapi.staticfiles import StaticFiles
    
    app = FastAPI()
    
    # Declared before the mount, so this route wins over any CDN file at this path.
    @app.get("/static/protected.json")
    def protected():
        return {"access": "denied"}
    
    app.mount("/static", StaticFiles(directory="static"))
  3. Leave guarded paths on the Function

    Check top-level middleware, sub-app middleware, and frontend dependencies before changing configuration. Do not set cdn = true to make a chart fall unless every affected file is genuinely public. Use cdn = false when all matching traffic must run through FastAPI.

  4. Choose whether to trim the bundle

    If the running app never reads the promoted files, you can exclude their source directories from the Function bundle with the documented setting:

    TOML
    [tool.vercel.fastapi.static]
    exclude = true

    Leave the default in place if runtime code still needs those files.

  5. Deploy and verify the split

    Run vc deploy. Exercise one public file, one protected file, and one API route. Confirm the protected response still behaves correctly, then compare the project's Function Invocations, Active CPU, Provisioned Memory, Fast Origin Transfer, Edge Requests, and Fast Data Transfer in Usage. The public sample should leave the Function path without disappearing from the CDN totals.

The honest limit on the saving

The direct invocation price is only $0.60 per million on Pro. For a small app, the cash saving may be pennies or absorbed by the monthly usage credit. The larger benefit can be removing asset noise from Function usage and preserving compute headroom for real API work.

The saving grows when public asset traffic is large, the old Function path held memory long enough to matter, or responses created meaningful Fast Origin Transfer. It stays small when the files already lived in public/, traffic is low, or security rules correctly keep the paths on the Function.

This also does not replace asset optimization. The same large JavaScript bundle, image, or font still has to cross the CDN to the visitor. Shrinking those files remains the move that cuts Fast Data Transfer.

Your Monday move

Act this week if app.frontend() or StaticFiles serves public files and those requests show up in Function usage. Wait if the files are protected and you have not separated their access rules. You are unaffected if the relevant files already come from public/ or another CDN-backed path.

On Monday, inventory public versus protected asset paths, preserve every route and guard that must run, then verify one deployment with one request from each class. Budget the measured drop in Function usage. Keep CDN requests and transfer on the sheet.

If you want more plain-English breakdowns of platform changes that alter the operating bill, join the newsletter.

Last Updated
Sep 13, 2026
Category
Explained

Prefer this site in Google

Add omidsaffari.com as a preferred source in Google Search

Mark omidsaffari.com as preferred and Google lifts it in Top Stories, AI Overviews and AI Mode for you.

OpenAI API Key Expiry Needs a Rotation Plan

OpenAI API Key Expiry Needs a Rotation Plan

OpenAI now lets teams expire project API keys. Plan replacement and verification before scheduled agents lose access.Sep 13, 2026Explained
Vercel Connect Gives Shared Credentials a Clear Owner

Vercel Connect Gives Shared Credentials a Clear Owner

Vercel Connect lets Pro and Enterprise teams restrict connector management. See how to assign owners and keep agent setup moving.Sep 13, 2026Explained
Cloudflare AI Search Can Index R2 Files Without Renaming

Cloudflare AI Search Can Index R2 Files Without Renaming

Cloudflare AI Search now indexes extensionless R2 files with valid Content-Type metadata. See which ingestion steps you can remove.Sep 12, 2026Explained
Vercel Sandbox Gives Larger Agent Jobs More Disk Room

Vercel Sandbox Gives Larger Agent Jobs More Disk Room

See which repository, build, and data jobs fit Vercel Sandbox’s larger disk, plus what to measure before retrying a storage-heavy agent run.Sep 12, 2026Explained
Cloudflare Workflows: Budget for Shorter Run History

Cloudflare Workflows: Budget for Shorter Run History

New Paid Workflows keep completed and errored state for seven days by default. Set retention before old failures disappear.Sep 11, 2026Explained
ChatGPT Data Can Cut Weekly Reporting Handoffs

ChatGPT Data Can Cut Weekly Reporting Handoffs

ChatGPT Data turns connected business data into recurring reports. Price Work usage, warehouse queries, review, and Site sharing before rollout.Sep 11, 2026Explained
Cursor Projects Moves Coding Teams to Review Queues

Cursor Projects Moves Coding Teams to Review Queues

Cursor Projects adds shared context and recurring agents. See the setup, review workload, and budget checks before moving a team onto it.Sep 11, 2026Explained
ChatGPT Deep Research Now Shares Your Work Budget

ChatGPT Deep Research Now Shares Your Work Budget

Deep Research in ChatGPT Work uses the same Work/Codex allowance or credits. Learn what it costs and how to check each delivered report.Sep 10, 2026Explained
Newsletter

One letter, every Sunday.Working systems, not hot takes.

Weekly. No spam. Unsubscribe anytime.