A CDN is like opening branch stores near your customers instead of shipping every order from one warehouse. Your Drupal server stays the single source of truth, but a network of edge servers scattered around the world hold cached copies of your CSS, JS, and images — so a visitor in Tokyo downloads those assets from a server in Tokyo, not from wherever your Drupal site actually lives.
What you'll learn in this lesson
- What a CDN actually does, and why it matters most for static assets
- The two real integration approaches: origin-pull CDNs and Drupal's own CDN module
- How to point your public files path at a CDN in settings.php
- The cache-invalidation gotcha that catches almost everyone the first time
Why static assets specifically
A CDN is a poor fit for dynamic, per-user HTML — that content genuinely has to come from your application server. But CSS, JS, and images are usually identical for every visitor and rarely change, which makes them ideal candidates: cache them once at every edge location, and every subsequent visitor near that edge gets a near-instant response instead of a round trip to your origin server.
Approach 1: origin-pull, no module needed
Most modern CDNs (Cloudflare, CloudFront, Fastly) work as a transparent reverse proxy in front of your whole site — you point your domain's DNS at the CDN, and it caches whatever your origin server returns, using the response's own Cache-Control headers to decide how long to keep it. This requires zero Drupal-side configuration beyond making sure your static assets are served with sensible cache headers (Drupal's own .htaccess/nginx config already sets long expiry on /sites/default/files/ and aggregated CSS/JS by default).
Approach 2: explicitly rewriting asset URLs
If you'd rather serve assets from a dedicated asset subdomain (cdn.example.com) instead of proxying your whole site, you rewrite the base URL Drupal uses when generating asset paths:
// In settings.php
$settings['file_public_base_url'] = 'https://cdn.example.com/sites/default/files';
This changes where Drupal points uploaded files (images, PDFs) — for CSS/JS aggregation specifically, the contributed CDN module is the standard tool: it lets you map file extensions or specific paths to CDN URLs through the admin UI (/admin/config/development/cdn) without touching settings.php at all, and it correctly handles fallback if the CDN is unreachable.
A quick way to verify it's actually working
Open your browser's Network tab, reload a page, and check the "Initiator" and response headers on a CSS/JS/image request. A CDN response typically includes a header like cf-cache-status: HIT (Cloudflare) or x-cache: Hit from cloudfront — if you only ever see MISS, either the asset isn't cacheable (check its Cache-Control header) or the CDN isn't actually in the request path yet.
Quick check: you update a background image referenced directly in a custom CSS file (not run through Drupal's own aggregation), but visitors keep seeing the old version for hours after deploy. What's the most likely cause? If you said the CDN is still serving a cached copy under the unchanged filename, you've got it — without a version/hash in the path, nothing tells the CDN the underlying file changed.
Key takeaways
- CDNs are for static, visitor-independent assets — CSS, JS, images — not for dynamic per-user page HTML.
- Origin-pull CDNs (Cloudflare, CloudFront) need no Drupal-side config beyond correct
Cache-Controlheaders, which Drupal already sets sensibly by default. - The contributed CDN module is the standard way to explicitly route specific asset types to a CDN subdomain through the admin UI.
$settings['file_public_base_url']in settings.php redirects uploaded-file URLs specifically, not aggregated CSS/JS.- Always include a content hash or version string in the path of anything you want a CDN to invalidate automatically on change.
Coming up next
You've now covered library efficiency, conditional attaching, dependency management, compression, and CDN delivery — the complete asset-management toolkit. Next, we turn to a different rendering layer entirely: how Views, one of Drupal's most powerful but most performance-sensitive systems, can be tuned to stay fast as your dataset grows.