# CloudFront Functions

> If you're on CloudFront, the small piece of JavaScript that does the redirects and rewrites a static host does for you. Not a place for logic.

- Verdict: Use when it fits
- Vendor: AWS
- Layer: [Storage and delivery](https://cloudlesslabs.com/stack/layers/storage/index.md). Job: Redirects and rewrites at the CloudFront edge
- Last reviewed: 26 October 2026, by Nicolas Dao (Cloudless Labs, Sydney)
- Web page: https://cloudlesslabs.com/stack/aws-cloudfront-functions/. The whole stack in one file: https://cloudlesslabs.com/stack/brief.md

It depends on where the site lives. If it's on CloudFront, use them: it's the only reasonable way to do what every static host does for you, and it costs next to nothing. If it can live on Cloudflare, you don't need them at all.

This site is the example. It runs on a private S3 bucket behind CloudFront, and about 40 lines of JavaScript run on every page request before CloudFront fetches the file:

| Request | What the function does | Why |
|---|---|---|
| `www.cloudlesslabs.com/...` | Redirects to `cloudlesslabs.com/...` | One domain for search engines |
| `ask.cloudlesslabs.com` | Serves `/llms.txt`; anything else there redirects to the main domain | The map for AI assistants has its own address |
| `/stack` | Redirects to `/stack/` | One URL per page |
| `/stack/` | Fetches `stack/index.html` | A private bucket has no index page: without this, every page but the home page fails |

That's the right size for them: string work on the URL and the headers, in well under a millisecond. They can't call anything, read the request body or load a library, and that's the point: they start in no time and scale with CloudFront.

What I don't do is put logic there. Security headers belong in a response headers policy and error pages in the distribution's settings, both of them configuration, not code. Anything that needs the network or real work goes to the origin, or to a [Cloudflare Worker](https://cloudlesslabs.com/stack/cloudflare-workers/index.md) in front.

## Use it when

- A site on S3 and CloudFront: a private bucket behind origin access control has no index page, so /about/ must be rewritten to /about/index.html, or every page but the home page fails.
- Redirects at the edge: www to the apex, /about to /about/, old URLs to new ones, one subdomain served from a file of the same site.
- Headers and cache keys: add or strip headers, normalise query strings so the cache hits more often.
- A cheap check before the origin: a signed token, a basic-auth password on a staging site, a country rule.

## Don't use it when

- Anything that needs the network, the request body, a library, or more than about a millisecond: it can't. Put the logic at the origin, in Lambda behind CloudFront, or in a Cloudflare Worker in front.
- A site you can host on Cloudflare: its static hosting does index pages, trailing slashes and redirect rules out of the box, with nothing to write.
- Settings that belong to the distribution: security headers go in a response headers policy, and error pages in custom error responses, not in code.

## Pricing

$0.10 per million invocations, with 2 million a month free. Included in every CloudFront flat-rate plan. KeyValueStore reads $0.03 per million (2 million free), on the Pro plan and above.

## Gotchas, with fixes

- **Gotcha:** The runtime is a restricted JavaScript: no network, no file system, no environment variables, no timers, no request body, and the code is capped at 10 KB with 2 MB of memory.
  **Fix:** Keep it to string work on the URL and headers. Values that change, such as a redirect table, go in KeyValueStore (runtime 2.0) rather than in the code.
- **Gotcha:** A function runs on every request of the behaviour it's attached to, assets included.
  **Fix:** Attach it to the default behaviour for pages only, and give /_next/static/* and other asset paths their own behaviours without it.
- **Gotcha:** A function has a DEVELOPMENT and a LIVE stage: saving new code in the console, or deploying it with publish set to false, leaves the distribution running the old LIVE version.
  **Fix:** Keep publish: true in code (the default), and test the new code with aws cloudfront test-function before it goes live.
- **Gotcha:** On a flat-rate plan, a function, and its KeyValueStore, can't be shared with another distribution.
  **Fix:** Create one function per distribution in code, from the same source.

## Provisioning

Official Pulumi package · Official Terraform provider

@pulumi/aws cloudfront.Function, with the code inline and publish: true, attached to a cache behaviour as a viewer-request function association.

## Instead, consider

- [Amazon CloudFront](https://cloudlesslabs.com/stack/aws-cloudfront/index.md): The distribution it runs on: headers policies, cache policies and error pages are settings there, not code.
- [Cloudflare static hosting](https://cloudlesslabs.com/stack/cloudflare-static-hosting/index.md): A site that can live anywhere: index pages, trailing slashes and redirects with nothing to write.
- [Cloudflare Workers](https://cloudlesslabs.com/stack/cloudflare-workers/index.md): Real logic at the edge: network calls, the request body, libraries.

## Decision guides

- [Cloudflare or S3 and CloudFront for a website?](https://cloudlesslabs.com/stack/guides/static-hosting/index.md): Where should a website, SPA or PWA live, Cloudflare static hosting or S3 behind CloudFront, and where do its heavy files go?

## Sources

- [CloudFront Functions or Lambda@Edge](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/edge-functions-choosing.html)
- [Restrictions on CloudFront Functions](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-function-restrictions.html)
- [CloudFront pay-as-you-go pricing](https://aws.amazon.com/cloudfront/pricing/pay-as-you-go/)
- [Flat-rate plans: features by tier](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/flat-rate-pricing-plan.html)

## Related

- [Storage and delivery](https://cloudlesslabs.com/stack/layers/storage/index.md): every tool in this layer, with its verdict
- [The whole stack in one file](https://cloudlesslabs.com/stack/brief.md): every use case and tool, for questions that span many
- [Map of every Markdown file on cloudlesslabs.com, with what each one answers](https://ask.cloudlesslabs.com)
