DEV Community

Magevanta
Magevanta

Posted on • Originally published at magevanta.com

Magento 2 CDN Configuration: Faster Assets, Global Performance

A CDN (Content Delivery Network) is one of the highest-leverage performance improvements you can make to a Magento 2 store. Instead of every visitor downloading images, CSS, and JavaScript from your origin server, those assets are served from an edge node geographically close to them. The result: dramatically lower latency, reduced origin load, and better Core Web Vitals scores.

This guide walks through the full CDN setup for Magento 2 — from choosing a provider to configuring static content URLs, media, and cache invalidation.

Why Magento 2 Needs a CDN

A typical Magento 2 page request involves dozens of static asset fetches:

  • CSS bundles (merged or per-module)
  • JavaScript files (RequireJS modules, bundles)
  • Product images and banners
  • Fonts, icons, and SVGs

Without a CDN, every one of those requests hits your origin server. For a store with international customers, a visitor in Sydney hitting a server in Frankfurt adds 200–300 ms of network latency per asset. Multiply that by 40–60 assets and you're looking at seconds of avoidable delay.

A CDN solves this by caching assets at edge nodes around the world after the first request. Subsequent requests from nearby visitors are served at local network speeds.

Choosing a CDN Provider

Magento 2 works with any CDN that supports:

  • Custom origin pull (fetches from your server on cache miss)
  • Custom hostname / CNAME support
  • Cache-Control header respect

Popular choices:

Provider Notes
Cloudflare Free tier, excellent DDoS protection, easy setup
Fastly Used by Adobe Commerce Cloud, very fast purge API
AWS CloudFront Great if already on AWS, flexible but more complex
BunnyCDN Cheap, fast, straightforward pricing
KeyCDN Pay-as-you-go, simple configuration

For most self-hosted stores, Cloudflare or BunnyCDN offer the best price/performance ratio.

Step 1 — Set Up a CDN Subdomain

Create a dedicated subdomain that points to your CDN, for example:

cdn.yourdomain.com
Enter fullscreen mode Exit fullscreen mode

In your CDN provider, configure this hostname as a "pull zone" or "distribution" with your Magento origin as the source:

Origin: https://yourdomain.com
CDN hostname: cdn.yourdomain.com
Enter fullscreen mode Exit fullscreen mode

The CDN will pull files from your origin on the first request and cache them at the edge for subsequent requests.

Step 2 — Configure Magento 2 to Use the CDN URL

In the Magento Admin, navigate to:

Stores → Configuration → General → Web

Under Base URLs, set:

  • Base URL for Static View Files: https://cdn.yourdomain.com/
  • Base URL for User Media Files: https://cdn.yourdomain.com/

Save the config and flush the Magento cache:

bin/magento cache:flush
Enter fullscreen mode Exit fullscreen mode

You can also set this via CLI, which is useful for automated deployments:

bin/magento config:set web/unsecure/base_static_url https://cdn.yourdomain.com/
bin/magento config:set web/unsecure/base_media_url https://cdn.yourdomain.com/
bin/magento config:set web/secure/base_static_url https://cdn.yourdomain.com/
bin/magento config:set web/secure/base_media_url https://cdn.yourdomain.com/
Enter fullscreen mode Exit fullscreen mode

After this change, all references to static and media files in Magento's HTML output will point to your CDN URL instead of the origin.

Step 3 — Verify Static Content Deployment

Before pushing to production, make sure your static content is deployed and accessible:

bin/magento setup:static-content:deploy -f
Enter fullscreen mode Exit fullscreen mode

Then visit a frontend page and inspect the asset URLs in your browser's network tab. You should see requests going to cdn.yourdomain.com for CSS, JS, and images.

Step 4 — Configure Cache Headers on the Origin

For the CDN to cache assets effectively, your origin server needs to send proper Cache-Control headers. Magento's static assets are versioned by hash, so they can be cached aggressively.

In Nginx, add this to your server block:

location ~* \.(jpg|jpeg|png|gif|ico|webp|svg|css|js|woff|woff2|ttf|eot)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
    add_header Vary "Accept-Encoding";
}
Enter fullscreen mode Exit fullscreen mode

For media files (product images), a shorter TTL is safer since they can change:

location /media/ {
    expires 7d;
    add_header Cache-Control "public";
}
Enter fullscreen mode Exit fullscreen mode

Step 5 — CDN Cache Invalidation

When you deploy new static content (new theme, module update), the CDN needs to serve fresh files. There are two approaches:

Option A — Version-based URLs (Recommended)

Magento uses content hashes in static asset URLs by default (e.g., version1234567890/). When you redeploy static content, the hash changes, so the CDN automatically fetches the new files. No manual invalidation needed.

Make sure this is enabled:

bin/magento config:set dev/static/sign 1
Enter fullscreen mode Exit fullscreen mode

Option B — Manual CDN Purge

If you need to force a purge (e.g., after updating media images), most CDN providers offer an API or CLI:

Cloudflare:

curl -X POST "https://api.cloudflare.com/client/v4/zones/{zone_id}/purge_cache" \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  --data '{"purge_everything":true}'
Enter fullscreen mode Exit fullscreen mode

BunnyCDN:

curl -X POST "https://api.bunny.net/pullzone/{zone_id}/purgeCache" \
  -H "AccessKey: {api_key}"
Enter fullscreen mode Exit fullscreen mode

For Fastly (used in Adobe Commerce Cloud pipelines), Magento has built-in Fastly integration with automatic purge on cache flush.

Step 6 — Handle Secure vs Non-Secure URLs

If your store runs on HTTPS (it should), make sure your CDN subdomain also has a valid TLS certificate. Most CDN providers issue free certificates automatically for custom domains.

Also ensure both secure and non-secure base URLs are set in Magento (even if you redirect all HTTP to HTTPS):

bin/magento config:set web/unsecure/base_static_url https://cdn.yourdomain.com/
bin/magento config:set web/secure/base_static_url https://cdn.yourdomain.com/
Enter fullscreen mode Exit fullscreen mode

Step 7 — Exclude Dynamic Requests from the CDN

Your CDN should only cache static assets, not Magento's dynamic pages (cart, checkout, customer account). Configure your CDN to not cache requests matching:

  • Paths containing session cookies (PHPSESSID, mage-cache-sessid)
  • /checkout/
  • /customer/
  • /sales/
  • Any request with a Set-Cookie response header

In Cloudflare, use a Page Rule:

URL: yourdomain.com/checkout/*
Cache Level: Bypass
Enter fullscreen mode Exit fullscreen mode

For Fastly/VCL, configure pass for these paths in the vcl_recv subroutine.

Performance Impact — What to Expect

After a proper CDN setup, typical improvements:

Metric Before CDN After CDN
TTFB for static assets 80–300 ms 5–30 ms
LCP (Largest Contentful Paint) 3.5–6s 1.5–2.5s
Origin bandwidth usage Baseline −60–80%
Server load during traffic spikes High Significantly reduced

The bandwidth reduction alone can meaningfully lower hosting costs, especially for image-heavy catalogs.

Common Pitfalls

Mixed content warnings: If your CDN URL uses HTTPS but Magento generates some HTTP URLs, browsers will block the mixed content. Always use HTTPS for both origin and CDN.

Wrong path structure: The CDN pull zone must serve Magento's full path structure, including /pub/ if your webroot is configured to use it. Test a few asset URLs manually before going live.

Forgot to flush config cache: After changing base URLs in the admin, always run bin/magento cache:flush — stale config cache will cause the old URLs to persist.

CDN caching HTML: If you accidentally route your main domain through the CDN without bypassing dynamic requests, customers will see cached versions of each other's carts. Always double-check your bypass rules.

Putting It All Together

A CDN is one of the few Magento performance improvements with near-zero downside. Setup takes an hour, the cache miss penalty is invisible to users, and the gains are immediate and measurable.

The recommended flow for a new store:

  1. Pick a CDN provider (Cloudflare for simplicity, BunnyCDN for cost efficiency)
  2. Create a cdn.yourdomain.com pull zone pointing to your origin
  3. Set the Magento base static/media URLs
  4. Configure aggressive cache headers in Nginx
  5. Enable signed static URLs for automatic versioning
  6. Test asset URLs on staging first, then deploy to production

Once it's running, you'll wonder why you didn't set it up on day one.

Top comments (1)

Collapse
 
buildbasekit profile image
buildbasekit

This is a clean setup guide. The latency breakdown really puts things into perspective.

I’ve been testing how systems behave under load recently, and one thing that stands out is how small delays (like per-asset latency) compound fast and show up as early signals before bigger failures.

Interesting how CDN shifts that pressure away from origin. Curious, have you seen cases where origin bottlenecks still show up even after aggressive caching?