---
title: "Build a CDN With Nginx: Caching Setup, Config and Limits"
description: "How to use Nginx as a CDN caching layer: proxy_cache config, cache keys, purging, TLS and when a DIY Nginx CDN stops being worth it."
image: https://blog.blazingcdn.com/hubfs/Gemini-Blog/image-Nov-01-2026-05-25-12-3531-PM.jpeg
---

[![BlazingCDN](https://blog.blazingcdn.com/hubfs/Logo/blog-logo-w.png)](https://blog.blazingcdn.com?hsLang=en-us)

[📘Learn ▾](https://blog.blazingcdn.com/cdn-learn?hsLang=en-us)

[CDN Fundamentals](https://blog.blazingcdn.com/cdn-fundamentals?hsLang=en-us) [By Content Type](https://blog.blazingcdn.com/by-content-type?hsLang=en-us) [Advanced Concepts](https://blog.blazingcdn.com/advanced-concepts?hsLang=en-us) [Glossary](https://blog.blazingcdn.com/glossary?hsLang=en-us)

[⚡ Web Performance](https://blog.blazingcdn.com/web-performance?hsLang=en-us)

[🎬Video & Streaming ▾](https://blog.blazingcdn.com/video-streaming-cdn?hsLang=en-us)

[🔴 Live Streaming](https://blog.blazingcdn.com/live-streaming?hsLang=en-us) [📺 VOD & OTT](https://blog.blazingcdn.com/vod-ott?hsLang=en-us) [💰 Bandwidth & Costs](https://blog.blazingcdn.com/bandwidth-costs?hsLang=en-us)

[🏭 Other Industries ▾](https://blog.blazingcdn.com/cdn-industry-insights?hsLang=en-us)

[📺 Media & Broadcasting](https://blog.blazingcdn.com/media-broadcasting?hsLang=en-us) [💾 Software & SaaS](https://blog.blazingcdn.com/software-saas?hsLang=en-us) [🏗️ DevOps & Cloud Infra](https://blog.blazingcdn.com/devops-cloud-infra?hsLang=en-us) [📚 AdTech & Advertising](https://blog.blazingcdn.com/adtech-advertising?hsLang=en-us) [🎮 Gaming & Esports](https://blog.blazingcdn.com/gaming-esports?hsLang=en-us) [📱 Mobile Apps & Developers](https://blog.blazingcdn.com/mobile-apps-developers?hsLang=en-us) [🤖 AI & Machine Learning](https://blog.blazingcdn.com/ai-machine-learning?hsLang=en-us) [🏛️ Enterprise & Corporate](https://blog.blazingcdn.com/enterprise-corporate?hsLang=en-us) [📚 E-Learning & EdTech](https://blog.blazingcdn.com/e-learning-edtech?hsLang=en-us) [🏟️ Sports & Live Events](https://blog.blazingcdn.com/sports-live-events?hsLang=en-us)

[💰 Pricing & Costs ▾](https://blog.blazingcdn.com/cdn-pricing-and-cdn-costs?hsLang=en-us)

[Provider Pricing](https://blog.blazingcdn.com/provider-pricing?hsLang=en-us) [Cost Optimization](https://blog.blazingcdn.com/cost-optimization?hsLang=en-us) [Decision Support](https://blog.blazingcdn.com/decision-support?hsLang=en-us)

[⚡Compare ▾](https://blog.blazingcdn.com/cdn-comparison?hsLang=en-us)

[Provider Comparisons](https://blog.blazingcdn.com/provider-comparisons?hsLang=en-us) [Strategy Comparisons](https://blog.blazingcdn.com/strategy-comparisons?hsLang=en-us) [Ratings & Benchmarks](https://blog.blazingcdn.com/cdn-ratings-and-benchmarks?hsLang=en-us)

[📊 Benchmarks](https://blog.blazingcdn.com/cdn-ratings-and-benchmarks?hsLang=en-us)

[🔒 Security ▾](https://blog.blazingcdn.com/cdn-security?hsLang=en-us)

[Attack Protection](https://blog.blazingcdn.com/attack-protection?hsLang=en-us) [Encryption & Access](https://blog.blazingcdn.com/encryption-access?hsLang=en-us) [Video & DRM Security](https://blog.blazingcdn.com/video-drm-security?hsLang=en-us)

[📁 Case Studies](https://blog.blazingcdn.com/case-studies?hsLang=en-us) [🔌 Integrations](https://blog.blazingcdn.com/integrations?hsLang=en-us) [🛠️ Tools](https://blog.blazingcdn.com/cdn-tools?hsLang=en-us)

[Get Started](https://blazingcdn.com/sign-up-contact-form/)

[Learn](https://blog.blazingcdn.com/en-us/tag/learn) [Learn - CDN Fundamentals](https://blog.blazingcdn.com/en-us/tag/learn-cdn-fundamentals) [DevOps & Cloud Infra](https://blog.blazingcdn.com/en-us/tag/devops-cloud-infra)

# Build a CDN With Nginx: Caching Setup, Config and Limits

 Vadym Borovskyi  Nov 1, 2026, 6:27:28 PM

![](https://blog.blazingcdn.com/hubfs/Gemini-Blog/image-Nov-01-2026-05-25-12-3531-PM.jpeg)

One megabyte of Nginx shared memory indexes about 8,000 cache keys, a figure from the Nginx documentation that still holds in 2026, and it is the first sizing decision in any nginx cdn. A CDN built on Nginx consists of proxy\_cache on NVMe edge nodes, a shield tier that collapses misses, and Anycast or GeoDNS routing in front. This playbook covers a working proxy\_cache configuration, cache key and purge options, multi-node rules, a failure table, and a worked cost model that shows where DIY stops paying off.

As of 2026, an Nginx CDN is a fleet of Nginx reverse proxies running proxy\_cache on NVMe storage. Each megabyte of keys\_zone indexes roughly 8,000 objects, and proxy\_cache\_lock limits each node to one origin request per uncached object. Nginx supplies only the data plane. Routing, certificate automation, purging and monitoring are the parts you build around it.

Budget about two hours for one working edge node and several weeks for a multi-region fleet with failover, purge fan-out and alerting.

## **What an Nginx CDN needs beyond the Nginx binary**

The cache directives are the easy part. A production deployment has four layers, and most outages come from the three that are not Nginx:

- **Edge nodes:** Nginx with proxy\_cache, TLS termination and an NVMe cache volume. Two or more per region for redundancy.
- **Origin shield:** a small Nginx tier between the edges and origin. It consolidates misses from every region, so a cold object costs one origin fetch, not one per edge.
- **Origin:** the source of truth. It must send accurate Cache-Control headers, because Nginx honors them ahead of your proxy\_cache\_valid defaults.
- **Routing:** Anycast (your own ASN, a provider-independent prefix, BGP sessions in every location) drains a failed node in seconds. GeoDNS is cheaper to run, but resolvers cache answers for the full TTL and beyond, so draining takes minutes.

Prerequisites for the steps below: Nginx 1.25.1 or newer (for the standalone http2 directive), a dedicated NVMe mount for cache data, an origin reachable over HTTPS, and an ACME client for certificates.

## **Can you use Nginx as a CDN?**

Yes. Nginx as a CDN works well for cacheable static content: images, scripts, software packages, video segments and large downloads. The proxy\_cache module handles storage, request collapsing and stale serving. What Nginx does not provide is global traffic steering, fleet-wide purge, certificate distribution or health-based failover, so those must be built or bought separately.

The fit gets worse as content gets less cacheable. Personalized HTML, authenticated APIs and WebSocket traffic gain little from an edge cache and add a hop you have to operate.

## **How to configure Nginx proxy cache on an edge node**

The configuration is described directive by directive so it can be adapted to your layout. Substitute EDGE\_ZONE with a zone name, ORIGIN\_HOST with your origin hostname, and NVME\_PATH with your cache mount.

1. **Define the cache store.** In the http context, add proxy\_cache\_path NVME\_PATH with levels=1:2, keys\_zone=EDGE\_ZONE:200m, max\_size set to about 90% of the volume, inactive=7d and use\_temp\_path=off. Why: 200 MB of zone indexes about 1.6 million keys, inactive controls eviction of cold objects regardless of TTL, and use\_temp\_path=off writes directly into the cache directory instead of copying across file systems.
2. **Normalize the cache key.** Set proxy\_cache\_key to "$scheme$host$uri$arg\_v", where v is your versioning parameter. Why: the default key includes the full query string, so utm\_source, fbclid and session parameters fragment one object into thousands of entries. Whitelisting the parameters that change the response is safer than blacklisting trackers.
3. **Set TTL defaults.** Use proxy\_cache\_valid 200 206 301 1d, and proxy\_cache\_valid 404 1m. Turn on proxy\_cache\_revalidate so expired objects are refreshed with conditional requests (If-Modified-Since, If-None-Match) instead of full refetches. Why: a 304 costs the origin a few hundred bytes instead of the whole object.
4. **Collapse concurrent misses.** Enable proxy\_cache\_lock with proxy\_cache\_lock\_timeout 5s. Why: when a popular object expires, hundreds of simultaneous requests otherwise all go to origin. With the lock, one request fills the cache and the rest wait.
5. **Serve stale during trouble.** Add proxy\_cache\_use\_stale with error, timeout, updating, http\_500, http\_502, http\_503 and http\_504, plus proxy\_cache\_background\_update on. Why: clients keep getting the cached copy while origin is failing, and refreshes happen in the background, so nobody waits on a slow origin.
6. **Slice large files.** For objects above roughly 100 MB, enable slice 1m, append $slice\_range to the cache key, forward it with proxy\_set\_header Range $slice\_range, and include 206 in proxy\_cache\_valid. Why: a range request for the last megabyte of a 4 GB installer no longer forces Nginx to pull and store the entire file first.
7. **Expose cache status.** Add a response header X-Cache-Status carrying $upstream\_cache\_status, and put $upstream\_cache\_status, $request\_time and $upstream\_response\_time in your log format. Why: without per-request cache status you cannot tell a routing problem from a cache problem.
8. **Terminate TLS.** Set ssl\_protocols to TLSv1.2 and TLSv1.3, ssl\_session\_cache shared:SSL:20m, and http2 on. Either disable session tickets or rotate the ticket keys in sync across every node behind the same Anycast address. Why: unsynchronized ticket keys break session resumption whenever routing shifts a client to another node.

Two defaults catch most first deployments. Nginx will not cache a response that carries Set-Cookie, and it will not cache a response with Vary set to an asterisk. Strip cookies at origin for static paths, or use proxy\_ignore\_headers with Set-Cookie only on routes where you are certain the response is not personalized.

### Validate the edge node

Request the same object twice with any HTTP client. Expect X-Cache-Status MISS on the first response and HIT on the second, with an Age header that increases on later requests. Then stop origin and request the object again: you should see STALE or HIT, not a 502.

## **Cache keys and purging options in open-source Nginx**

Open-source Nginx has no built-in purge directive. The proxy\_cache\_purge directive belongs to the commercial NGINX Plus, so a self-built CDN picks one of four approaches:

- **Versioned URLs:** change the v parameter or the file path on every deploy. This approach is the most reliable because nothing has to be deleted, and it pairs naturally with the whitelisted cache key from step 2.
- **Third-party purge module:** the community ngx\_cache\_purge module adds a purge location. You have to compile it against every Nginx upgrade.
- **Bypass refresh:** set proxy\_cache\_bypass to a secret request header. A request carrying that header skips the cache lookup, fetches from origin and overwrites the stored copy.
- **File deletion:** each cache file is named with the MD5 hash of its key, placed in directories derived from the levels setting. Scripts can compute the path and remove the file.

Every option except versioned URLs has to fan out to every edge and shield node, and a purge is only complete when all nodes confirm it. Purge specific keys or prefixes. A global purge on a busy fleet turns into an origin stampede within seconds.

## **Running Nginx proxy cache across multiple nodes**

Each Nginx node has an independent cache. Ten edges mean up to ten misses for every new object, which is why the shield tier matters more as the fleet grows.

On the edges, point the upstream at the shield pool using hash $request\_uri consistent. Consistent hashing sends each URL to the same shield node, so the shield tier behaves like one large cache instead of several small duplicated ones. When a shield node leaves the pool, only its share of keys moves. Keep configuration in version control and deploy the same release to every node: drift between edges is a common cause of hit ratios that differ by region for no visible reason.

For static and media workloads, a well-keyed fleet typically reaches 90–98% edge hit ratio (an estimate that depends heavily on library size and TTLs). A sustained rate below 80% usually points to fragmented keys, undersized storage or a keys\_zone that fills before the disk does.

## **Diagnostics and rollback for an Nginx CDN**

| Symptom | Likely cause | Fix |
| --- | --- | --- |
| Every request shows MISS | Set-Cookie or private Cache-Control from origin | Fix origin headers for static paths |
| Hit ratio falls while disk has free space | keys\_zone full, forcing early eviction | Size the zone at 1 MB per 8,000 objects plus headroom |
| Origin spikes on deploy | Global purge or lock disabled | Versioned URLs, proxy\_cache\_lock on |
| Slow first byte on large files | Whole-file fill on range requests | Enable the slice module |

Most Nginx CDN incidents trace back to origin headers or key design, not to Nginx capacity.

When a node misbehaves, work through it in this order:

1. Compare cache-status mix and error rates with a healthy edge to decide whether the fault is caching, routing or origin.
2. Drain the node by withdrawing its Anycast route or setting its GeoDNS weight to zero.
3. Roll back configuration by validating with nginx -t, then switching an atomic symlink to the previous release and reloading.
4. Reintroduce the node gradually while watching its hit ratio and the origin request rate.

## **When a DIY Nginx CDN stops being worth it**

Bandwidth is rarely what breaks the DIY business case. Engineering time is. Here is a worked model for 100 TB a month, with every input labeled as this blog's estimate:

- 100 TB a month averages about 309 Mbps (100 TB × 8 bits ÷ 2.59 million seconds). At a 3× peak-to-average ratio, that is roughly 1 Gbps at peak.
- Three regions with two edges each, plus two shield nodes, gives 8 servers. Estimate $100–$300 per month each with unmetered ports, so $800–$2,400 a month in total.
- On-call, purge tooling, certificates and upgrades take about 0.25 of an engineer. At an estimated $180,000 loaded annual cost, that adds $3,750 a month.
- Estimated total: $4,550–$6,150 a month, before Anycast IP space and transit.

| Situation | Better fit |
| --- | --- |
| Servers and bandwidth already paid for, team already on call | DIY Nginx |
| On-premises or data-residency rules forbid third-party edges | DIY Nginx |
| Need for custom request logic that no managed CDN exposes | DIY Nginx |
| Multi-region static or video traffic with no spare engineering time | Managed CDN |

Unless the hardware and the people are already sunk costs, the engineering line alone usually exceeds managed delivery fees at 100 TB a month.

As of November 2026, BlazingCDN charges from $5 per TB down to $2.50 per TB at volume, so 100 TB a month costs $415, with one rate for the US, Europe and Asia and no request fees. Current rates are listed on the [**BlazingCDN CDN pricing page**](https://blazingcdn.com/pricing/).

BlazingCDN includes origin shield, request coalescing, API purge and Prometheus metrics, which covers the parts of the build that take the most engineering time. The limits are real, though. It does not support HTTP/3 and does not sell a WAF, so a self-built Nginx edge remains the better choice when those must live on the same layer.

## **FAQ: building an Nginx CDN**

### How many cache keys fit in an Nginx keys\_zone?

One megabyte of Nginx keys\_zone stores about 8,000 cache keys, according to the Nginx documentation. A 200 MB zone therefore indexes about 1.6 million objects. Size the zone from your expected object count rather than from disk capacity, because a full zone evicts entries early even when the NVMe volume still has free space.

### Does open-source Nginx support cache purging for a CDN?

Not natively. In Nginx, the proxy\_cache\_purge directive is part of the commercial NGINX Plus. Open-source deployments use versioned URLs, the third-party ngx\_cache\_purge module, a secret-header proxy\_cache\_bypass refresh, or scripted deletion of the MD5-named cache files. Any method other than versioning must fan out to every edge and shield node.

### Is Nginx as a CDN good for video or large file delivery?

Yes, provided the slice module is enabled for large objects. Nginx as a CDN serves HLS and DASH segments and multi-gigabyte downloads efficiently from NVMe. Slicing in 1 MB ranges prevents whole-file fills on range requests, and proxy\_cache\_lock stops a new release or popular episode from triggering a burst of simultaneous requests to the origin.

### How many nodes do you need to build a CDN with Nginx?

A minimum viable build is two edge nodes per region plus a two-node shield tier, so eight servers for three regions. Two edges per region let you drain one for maintenance without losing that region. The shield, reached through consistent hashing on the request URI, keeps origin load roughly flat as you add edges.

### What cache hit ratio should an Nginx CDN reach?

For static and media traffic, an Nginx CDN typically reaches 90–98% after cache key normalization and sensible TTLs, though this is an estimate that varies with library size. A sustained ratio below 80% usually signals query-string fragmentation, Set-Cookie on static responses, or a keys\_zone that is too small for the object count.

## **Measure your Nginx cache before you scale it**

This week, log $upstream\_cache\_status on every node for seven days. Break the HIT, MISS, EXPIRED and STALE counts down by content type and region. If cacheable traffic misses more than 20% of the time, fix the cache key and origin headers before you buy more servers. Then put your real egress volume, server count and on-call hours into the cost model above, so the build-or-buy decision rests on your own numbers rather than on a rule of thumb.

If the model shows engineering time outweighing bandwidth, the [**BlazingCDN cost calculator**](https://blazingcdn.com/cdn-cost-calculator/) prices the same monthly volume on progressive tiers, starting at $5 per TB.

Share: [f](https://www.facebook.com/sharer/sharer.php?u=https://blog.blazingcdn.com/en-us/go-global-with-nginx-build-your-own-cdn-for-supercharged-caching) [in](https://www.linkedin.com/sharing/share-offsite/?url=https://blog.blazingcdn.com/en-us/go-global-with-nginx-build-your-own-cdn-for-supercharged-caching) [𝕏](https://twitter.com/intent/tweet?url=https://blog.blazingcdn.com/en-us/go-global-with-nginx-build-your-own-cdn-for-supercharged-caching&text=) [✉](mailto:?subject=%3Cspan%20id="hs_cos_wrapper_name"%20class="hs_cos_wrapper%20hs_cos_wrapper_meta_field%20hs_cos_wrapper_type_text"%20style=""%20data-hs-cos-general-type="meta_field"%20data-hs-cos-type="text"%20%3EBuild%20a%20CDN%20With%20Nginx:%20Caching%20Setup,%20Config%20and%20Limits%3C/span%3E&body=https://blog.blazingcdn.com/en-us/go-global-with-nginx-build-your-own-cdn-for-supercharged-caching)

![BlazingCDN](https://blog.blazingcdn.com/hs-fs/hubfs/Logo/blog-logo-w.png?height=24&name=blog-logo-w.png)

*Heavy traffic.*  
Light bill.

The CDN for video and large traffic

Their monthly bill vs ours

- 20 TBFastly $2,087**$92.50**
- 50 TBCDN77 $990**$215**
- 200 TBCloudFront $11,965**$765**

Published list prices, Aug 2026

[Calculate your cost](https://blazingcdn.com/cdn-cost-calculator/?utm_source=blog&utm_medium=sidebar&utm_campaign=blog_sidebar&utm_content=compare_calc)

## Related posts

[![](https://blog.blazingcdn.com/hubfs/Gemini-Blog/image-Nov-01-2026-05-20-39-5216-PM.jpeg)](https://blog.blazingcdn.com/en-us/what-is-a-reverse-proxy-reverse-vs-forward-proxy?hsLang=en-us)

Learn

### [What Is a Reverse Proxy? Reverse vs Forward Proxy](https://blog.blazingcdn.com/en-us/what-is-a-reverse-proxy-reverse-vs-forward-proxy?hsLang=en-us)

A reverse proxy is a server that sits in front of one or more origin servers, accepts client connections on their ...

Nov 1, 2026, 6:22:17 PM [Read more](https://blog.blazingcdn.com/en-us/what-is-a-reverse-proxy-reverse-vs-forward-proxy?hsLang=en-us)

[![](https://blog.blazingcdn.com/hubfs/Gemini-Blog/image-Nov-01-2026-04-55-14-9690-PM.jpeg)](https://blog.blazingcdn.com/en-us/amazon-cloudfront-cdn-walkthrough-cache-invalidation-waf-rules?hsLang=en-us)

Learn

### [CloudFront Cache Invalidation: Paths, Wildcards and Costs](https://blog.blazingcdn.com/en-us/amazon-cloudfront-cdn-walkthrough-cache-invalidation-waf-rules?hsLang=en-us)

A CloudFront invalidation removes cached objects from every Amazon CloudFront cache layer before their TTL expires. As ...

Nov 1, 2026, 5:58:23 PM [Read more](https://blog.blazingcdn.com/en-us/amazon-cloudfront-cdn-walkthrough-cache-invalidation-waf-rules?hsLang=en-us)

[![BlazingCDN](https://blog.blazingcdn.com/hubfs/Logo/blog-logo-w.png)](https://blog.blazingcdn.com?hsLang=en-us)

[📘 Learn](https://blog.blazingcdn.com/cdn-learn?hsLang=en-us) [📊 Benchmarks](https://blog.blazingcdn.com/cdn-ratings-and-benchmarks?hsLang=en-us) [🎬 Video & Streaming](https://blog.blazingcdn.com/video-streaming-cdn?hsLang=en-us) [🏭 Industries](https://blog.blazingcdn.com/cdn-industry-insights?hsLang=en-us) [💰 Pricing & Costs](https://blog.blazingcdn.com/cdn-pricing-and-cdn-costs?hsLang=en-us) [⚡ Compare](https://blog.blazingcdn.com/cdn-comparison?hsLang=en-us) [🔒 Security](https://blog.blazingcdn.com/cdn-security?hsLang=en-us) [🛠️ Tools](https://blog.blazingcdn.com/cdn-tools?hsLang=en-us) [✍️ Publish with us](https://blog.blazingcdn.com/publish-with-us?hsLang=en-us)

in f 𝕏 ✉

 Copyright © BlazingCDN |. All rights reserved.

```json
{
  "@context" : "https://schema.org",
  "@id" : "https://blazingcdn.com/#organization",
  "@type" : "Organization",
  "description" : "High-volume CDN for video, live streaming, OTT/IPTV, software, games, SaaS and large-file delivery.",
  "logo" : {
    "@id" : "https://blazingcdn.com/#logo",
    "@type" : "ImageObject",
    "height" : 560,
    "url" : "https://blazingcdn.com/wp-content/uploads/2024/08/logo-560-560.png",
    "width" : 560
  },
  "name" : "BlazingCDN",
  "sameAs" : [ "https://www.linkedin.com/company/blazingcdn", "https://x.com/BlazingCdn", "https://www.reddit.com/r/BlazingCDN/", "https://www.wikidata.org/wiki/Q141711074" ],
  "url" : "https://blazingcdn.com/"
}
```

```json
{
  "@context" : "https://schema.org",
  "@id" : "https://blog.blazingcdn.com/#website",
  "@type" : "WebSite",
  "inLanguage" : "en-US",
  "name" : "BlazingCDN Blog",
  "publisher" : {
    "@id" : "https://blazingcdn.com/#organization"
  },
  "url" : "https://blog.blazingcdn.com/"
}
```

```json
{
  "@context" : "https://schema.org",
  "@id" : "https://blog.blazingcdn.com/en-us/go-global-with-nginx-build-your-own-cdn-for-supercharged-caching#article",
  "@type" : "BlogPosting",
  "author" : {
    "@id" : "https://blog.blazingcdn.com/en-us/author/blazingcdn#person",
    "@type" : "Person",
    "description" : "Vadym Borovskyi is Chief Product and Marketing Officer at BlazingCDN, where he has led product strategy and growth since 2021. He has more than 11 years of experience in IT product management and B2B marketing. On this blog he writes about CDN pricing and egress costs, video and software delivery, cache configuration, and how teams evaluate and switch CDN providers. He is based in Warsaw, Poland.",
    "image" : "https://143144902.fs1.hubspotusercontent-eu1.net/hubfs/143144902/vadym-borovskyi.jpg",
    "jobTitle" : "Chief Product and Marketing Officer",
    "knowsAbout" : [ "Content Delivery Networks (CDN)", "CDN pricing", "Video streaming delivery", "Software and game distribution", "Cache optimization", "Product Management", "B2B Marketing", "Digital Marketing", "Pay Per Click Marketing (PPC)", "Google Ads", "Search Engine Marketing (SEM)", "Marketing Strategy", "Artificial Intelligence (AI)", "Cloud Management", "SaaS Development", "IT Consulting", "Computer Networking", "Project Management", "Startups" ],
    "name" : "Vadym Borovskyi",
    "sameAs" : [ "https://www.linkedin.com/in/axelt/" ],
    "url" : "https://blog.blazingcdn.com/en-us/author/blazingcdn",
    "worksFor" : {
      "@id" : "https://blazingcdn.com/#organization"
    }
  },
  "dateModified" : "2026-11-01T17:27:28Z",
  "datePublished" : "2026-11-01T17:27:28Z",
  "description" : "How to use Nginx as a CDN caching layer: proxy_cache config, cache keys, purging, TLS and when a DIY Nginx CDN stops being worth it.",
  "headline" : "Build a CDN With Nginx: Caching Setup, Config and Limits",
  "image" : "https://143144902.fs1.hubspotusercontent-eu1.net/hubfs/143144902/Gemini-Blog/image-Nov-01-2026-05-25-12-3531-PM.jpeg",
  "inLanguage" : "en-us",
  "isPartOf" : {
    "@id" : "https://blog.blazingcdn.com/#website"
  },
  "mainEntityOfPage" : {
    "@id" : "https://blog.blazingcdn.com/en-us/go-global-with-nginx-build-your-own-cdn-for-supercharged-caching",
    "@type" : "WebPage"
  },
  "publisher" : {
    "@id" : "https://blazingcdn.com/#organization"
  },
  "wordCount" : 2288
}
```

```json
{
  "@context" : "https://schema.org",
  "@id" : "https://blog.blazingcdn.com/en-us/go-global-with-nginx-build-your-own-cdn-for-supercharged-caching#breadcrumb",
  "@type" : "BreadcrumbList",
  "itemListElement" : [ {
    "@type" : "ListItem",
    "item" : "https://blog.blazingcdn.com/en-us",
    "name" : "Blog",
    "position" : 1
  }, {
    "@type" : "ListItem",
    "item" : "https://blog.blazingcdn.com/en-us/go-global-with-nginx-build-your-own-cdn-for-supercharged-caching",
    "name" : "Build a CDN With Nginx: Caching Setup, Config and Limits",
    "position" : 2
  } ]
}
```

```json
{
  "@context" : "https://schema.org",
  "@id" : "https://blog.blazingcdn.com/en-us/go-global-with-nginx-build-your-own-cdn-for-supercharged-caching#faq",
  "@type" : "FAQPage",
  "mainEntity" : [ {
    "@type" : "Question",
    "acceptedAnswer" : {
      "@type" : "Answer",
      "text" : "One megabyte of Nginx keys_zone stores about 8,000 cache keys, according to the Nginx documentation. A 200 MB zone therefore indexes about 1.6 million objects. Size the zone from your expected object count rather than from disk capacity, because a full zone evicts entries early even when the NVMe volume still has free space."
    },
    "name" : "How many cache keys fit in an Nginx keys_zone?"
  }, {
    "@type" : "Question",
    "acceptedAnswer" : {
      "@type" : "Answer",
      "text" : "Not natively. In Nginx, the proxy_cache_purge directive is part of the commercial NGINX Plus. Open-source deployments use versioned URLs, the third-party ngx_cache_purge module, a secret-header proxy_cache_bypass refresh, or scripted deletion of the MD5-named cache files. Any method other than versioning must fan out to every edge and shield node."
    },
    "name" : "Does open-source Nginx support cache purging for a CDN?"
  }, {
    "@type" : "Question",
    "acceptedAnswer" : {
      "@type" : "Answer",
      "text" : "Yes, provided the slice module is enabled for large objects. Nginx as a CDN serves HLS and DASH segments and multi-gigabyte downloads efficiently from NVMe. Slicing in 1 MB ranges prevents whole-file fills on range requests, and proxy_cache_lock stops a new release or popular episode from triggering a burst of simultaneous requests to the origin."
    },
    "name" : "Is Nginx as a CDN good for video or large file delivery?"
  }, {
    "@type" : "Question",
    "acceptedAnswer" : {
      "@type" : "Answer",
      "text" : "A minimum viable build is two edge nodes per region plus a two-node shield tier, so eight servers for three regions. Two edges per region let you drain one for maintenance without losing that region. The shield, reached through consistent hashing on the request URI, keeps origin load roughly flat as you add edges."
    },
    "name" : "How many nodes do you need to build a CDN with Nginx?"
  }, {
    "@type" : "Question",
    "acceptedAnswer" : {
      "@type" : "Answer",
      "text" : "For static and media traffic, an Nginx CDN typically reaches 90–98% after cache key normalization and sensible TTLs, though this is an estimate that varies with library size. A sustained ratio below 80% usually signals query-string fragmentation, Set-Cookie on static responses, or a keys_zone that is too small for the object count."
    },
    "name" : "What cache hit ratio should an Nginx CDN reach?"
  } ]
}
```