---
title: "CloudFront cache warming: 600+ POPs, regional edge caches, and how to fill them — warmup.rocks"
description: "CloudFront caches per edge location, with regional edge caches as a second layer. What invalidations really cost, what Origin Shield does and doesn't do, and how to warm CloudFront properly."
canonical: https://warmup.rocks/blog/cloudfront-cache-warming
---

CloudFront

# CloudFront cache warming: 600+ POPs, regional edge caches, and how to fill them

July 2026 · 8 min read · [← All posts](https://warmup.rocks/blog/)

CloudFront is the largest CDN by location count — 600+ edge POPs feeding from 13 regional edge caches (RECs). That two-tier design is great news for warming: it means a warming strategy gets _leverage_. It's also the CDN where HTML caching is most often accidentally disabled, so let's start there.

## First: is your HTML cacheable at all?

CloudFront honors your origin's `Cache-Control`. The most common finding when we point the [cache checker](https://warmup.rocks/cache-checker) at a CloudFront site: `x-cache: Miss from cloudfront` on every request, forever — because the origin sends `no-cache`, `private`, or nothing at all while the distribution uses the `CachingDisabled` policy for dynamic behavior. Fix the policy first (use `CachingOptimized` or a custom cache policy with a real TTL for anonymous HTML), or warming has nothing to warm. The headers to read: `x-cache` (`Hit from cloudfront` / `Miss from cloudfront`) and `x-amz-cf-pop` (which POP answered, e.g. `FRA56-P5`).

## The two-tier cache: why warming CloudFront pays twice

When an edge POP misses, it doesn't go straight to your origin — it asks its **regional edge cache** first. RECs are bigger, fewer (13 worldwide) and hold objects longer than edge POPs. For warming this is a gift:

-   Warming one URL from _one_ location per region fills that region's REC.
-   Every other POP in the region that misses later gets a fast regional answer (tens of ms) instead of a full origin round trip (hundreds of ms).

So even a modest multi-region warming pass — one request per continent-region — upgrades the "worst case" for your whole audience from origin-latency to REC-latency. A denser pass (one request per country) then fills the actual edge POPs your visitors touch. That's the model [warmup.rocks](https://warmup.rocks/) uses: requests from 40+ countries land at the POPs real traffic lands at, and the RECs come along for free.

## Invalidations: the cold-cache generator

Every deploy that runs `aws cloudfront create-invalidation --paths "/*"` empties all 600+ POPs and all 13 RECs at once. Two things to know (details in [AWS's invalidation docs](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Invalidation.html)):

-   **Cost:** 1,000 invalidation paths per month are free, after that $0.005 per path — but `/*` counts as one path, which is why everybody uses it, which is why whole sites go globally cold on every release.
-   **Better:** use versioned asset filenames (cache forever, never invalidate) and invalidate only the HTML paths that changed. And whatever you invalidate — **re-warm it right after**. A post-deploy warming trigger (e.g. our [deploy hook / GitHub Action](https://warmup.rocks/docs/deploy-hooks)) closes the gap between "cache empty" and "first visitor" to a couple of minutes.

## Origin Shield: one more layer, same story

CloudFront's [**Origin Shield**](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/origin-shield.html) (an extra REC acting as the single funnel to your origin) further concentrates origin fetches — with shield enabled, a global warming pass typically costs your origin a single-digit number of requests per URL. If your origin is a slow CMS or a Lambda@Edge/SSR function, that's the difference between a warming pass being free and being a load test.

## Practical CloudFront warming setup

1.  **Cache policy:** real TTLs for anonymous HTML; exclude cookies/headers you don't vary on (every extra cache key dimension multiplies the objects to warm).
2.  **Versioned assets + targeted invalidations** instead of `/*` where possible.
3.  **Origin Shield on** if your origin is slow or expensive.
4.  **Scheduled multi-location warming** matched to your TTLs, plus a [deploy-hook triggered run](https://warmup.rocks/docs/deploy-hooks) after each invalidation.
5.  **Verify per location:** the [global TTFB test](https://warmup.rocks/ttfb-test) shows the REC effect directly — warm regions answer in <100 ms, cold ones show your full origin round trip.
