Een CDN haalt statische assets uit het hot path van je origin server en serveert ze vanaf een edge node dichtbij de bezoeker. Voor WordPress betekent dat: afbeeldingen in wp-content/uploads, theme-CSS, plugin-JavaScript en webfonts komen van een netwerk van points of presence in plaats van een halve wereld af te leggen naar je datacenter. De setup is kort en het effect is echt, maar het verkeerde type CDN kiezen breekt meer sites dan het er sneller op maakt. Voordat je een pull zone aanmaakt moet je eerst weten welk soort CDN je eigenlijk nodig hebt.
Wat een CDN doet voor de performance van WordPress
Een CDN is een geografisch verspreid netwerk van edge servers dat tussen je bezoekers en je origin in zit. Op het moment dat een bezoeker een statisch bestand opvraagt, beschrijft de uitleg van Google web.dev over content delivery networks drie mechanismen: het CDN maakt de TCP-verbinding dichtbij de bezoeker af (en voorkomt zo de kosten van een verbinding over lange afstand), het serveert het bestand vanuit de edge cache als die er is, en het houdt warmgehouden persistente verbindingen open naar de origin voor cache misses. Sommige CDN's routeren verkeer ook nog over hun eigen geoptimaliseerde backbone in plaats van publiek BGP, wat extra latency scheelt. Een cache hit ratio van 90% is waar je naartoe wilt. Moderne CDN's bieden Brotli-compressie, TLS 1.3 en HTTP/2 of HTTP/3 als features die je wilt zien staan.
Voor WordPress in het bijzonder zijn de statische assets de hoofdprijs. Afbeeldingen vormen ruwweg de helft van de byte payload van een gemiddelde webpagina en op een mediarijke WordPress-site ligt dat percentage nog hoger. Als je die bytes naar de edge verplaatst, kan je origin zich bezighouden met PHP en de database in plaats van JPEG's serveren.
Er is wel één belangrijke kanttekening waar elke nieuwe CDN-gebruiker tegenaan loopt. WordPress HTML is dynamisch, niet statisch. Een pagina-aanvraag draait PHP, doet MySQL-queries en bouwt het antwoord ter plekke op. Een gewone asset-CDN cachet die HTML niet. De bezoeker wacht nog steeds tot je origin de pagina rendert, en daarna laden afbeeldingen en CSS snel vanaf de edge. Als je TTFB de bottleneck is, lost een asset-CDN dat op zichzelf niet op. Daar heb je een aparte page-cachelaag voor nodig, óf op WordPress-niveau (een caching-plugin) óf op CDN-niveau (Cloudflare APO, full-page edge caching). Voor het bredere plaatje van waar TTFB-tijd op een WordPress-request naartoe gaat, lees wat TTFB is en waarom WordPress-sites er vaak een hoge hebben.
Full proxy CDN versus pull zone CDN voor statische assets
Dit is de keuze waar niemand je voor waarschuwt en die alle andere keuzes bepaalt.
Een pull zone CDN is het klassieke model. Je maakt een CDN-account aan (BunnyCDN, KeyCDN, CloudFront), maakt een pull zone aan die naar je origin URL wijst en het CDN geeft je een hostname zoals voorbeeld.b-cdn.net. Meestal zet je daar je eigen subdomein voor, bijvoorbeeld cdn.jouwsite.nl, via een CNAME. Een WordPress-plugin schrijft vervolgens elke asset URL op elke pagina om zodat die naar die CDN-hostname wijst in plaats van naar je origin. Alleen statische assets worden op de edge gecached, en ze leven op een ander domein dan je HTML. De pull zone haalt assets bij de eerste aanvraag op bij je origin en cachet ze daarna voor volgende aanvragen.
Een full proxy CDN zoals Cloudflare werkt heel anders. Op het moment dat je de oranje wolk van Cloudflare aanzet, gaat al het verkeer naar je domein (HTML én assets samen) via het edge-netwerk van Cloudflare. Je krijgt geen aparte cdn.jouwsite.nl hostname; je bestaande jouwsite.nl ís het CDN. Cloudflare cachet statische bestanden op het free plan automatisch op basis van bestandsextensie, en laat HTML standaard ongecached tenzij je Cloudflare APO aanzet ($5 per maand voor Free-gebruikers) of zelf Cache Rules schrijft.
Deze twee architecturen mengen niet zomaar. Als je al op Cloudflare zit met de oranje wolk aan, zet er dan niet ook nog een pull zone CDN met URL rewriting bij. Cloudflare cachet je statische assets al op de edge onder je eigen domein. Als je daar CDN Enabler met een cdn.jouwsite.nl hostname bovenop zet, worden assets herschreven naar een hostname die Cloudflare niet bezit, gaan ze buiten de Cloudflare cache om en is het hele punt weg. Kies één model, niet twee. Voor de stappen en valkuilen van het Cloudflare-pad specifiek, lees WordPress met Cloudflare: de juiste configuratie.
In de praktijk is de keuze vrij simpel. Zit je al op Cloudflare en is het free plan goed genoeg, dan heb je al een CDN en gaat de rest van dit artikel over het alternatief. Zit je niet op Cloudflare en wil je een aparte, pure asset CDN met usage-based facturatie en het vertrouwde pull zone model, lees dan vooral door.
Even kort over push zones, want die vraag komt soms langs: een push zone is een model waarbij je zelf bestanden upload naar een storage bucket en het CDN ze van daaruit distribueert. Dat past bij grote, weinig veranderende bestanden zoals video's en software downloads, maar het is onhandig in combinatie met WordPress media omdat uploads dynamisch zijn. Voor een normale WordPress-site is een pull zone gewoon de standaard en behandelt de rest van dit artikel alleen dat.
BunnyCDN als pull zone CDN opzetten
BunnyCDN is de populairste pull zone CDN onder WordPress-gebruikers. Pricing is per GB zonder maandelijks minimum voor pull zones, het dashboard is overzichtelijk en er is naast de generieke CDN Enabler ook een officiële WordPress-plugin.
De stappen, op volgorde:
- Maak een Bunny.net account aan en maak vanuit het dashboard een Pull Zone. De Bunny Pull Zone API documenteert het POST /pullzone endpoint voor programmatische creatie, maar via het dashboard gaat het de eerste keer veel makkelijker. Zet de Origin URL op je WordPress-site (
https://jouwsite.nl). Het Name veld wordt het subdomein opb-cdn.net. - Noteer de toegewezen CDN-hostname, die ziet er ongeveer zo uit:
jouwsite.b-cdn.net. Daar gaat de URL-rewriting naar wijzen als je hier stopt. - Voeg een eigen CNAME toe (optioneel maar aanbevolen). Maak in je DNS een record
cdn.jouwsite.nl CNAME jouwsite.b-cdn.net. Ga in het BunnyCDN dashboard naar je Pull Zone, Hostnames en voegcdn.jouwsite.nltoe. Wacht op DNS-propagatie en zet daarna het gratis Bunny SSL-certificaat aan voor je eigen hostname. Branding terzijde, de praktische reden is dat je zelf de DNS beheert: je kunt het assetverkeer later naar een ander CDN verplaatsen zonder elke URL op de site aan te passen. - Installeer URL-rewriting in WordPress. Gebruik óf de officiële "bunny.net" WordPress-plugin (zoek in de directory op "bunny.net") óf de generieke CDN Enabler plugin uit de volgende sectie. In beide gevallen is de configuratie hetzelfde: de CDN-hostname (
cdn.jouwsite.nl) invoeren en kiezen welke bestandstypen je wil herschrijven.
Controleer of het werkt. Laad een pagina op je site, bekijk de bron en bevestig dat de src-attributen van <img>-tags voor afbeeldingen in wp-content/uploads nu naar cdn.jouwsite.nl wijzen in plaats van naar jouwsite.nl. Vraag dezelfde asset twee keer op met curl -I https://cdn.jouwsite.nl/wp-content/uploads/..., en bij de tweede aanvraag moet er een header als CDN-Cache: HIT van de BunnyCDN edge nodes terugkomen die bevestigt dat het bestand uit de cache wordt geserveerd in plaats van bij je origin opgehaald. Je weet dat het werkt als de bandbreedte-grafiek in het BunnyCDN dashboard binnen een paar minuten begint te lopen bij normaal verkeer.
Er is geen verifieerbaar bewijs voor een breaking change in de BunnyCDN Pull Zone API in 2024 of 2025. De API-structuur en het dashboard-flow hierboven kloppen met de huidige documentatie.
KeyCDN opzetten
KeyCDN is de andere veelgebruikte pull zone CDN in de WordPress-wereld, en het bedrijf onderhoudt ook de CDN Enabler plugin die de meeste pull-zone setups gebruiken.
- Maak een KeyCDN account aan en maak vanuit het dashboard een nieuwe Pull Zone. Verplichte velden zijn Zone Name, Zone Status, Zone Type (zet die op "Pull") en Origin URL (zet die op
https://jouwsite.nl). - Noteer de toegewezen Zone URL, die er ongeveer zo uitziet:
jouwsite-abc123.kxcdn.com. - Voeg een Zone Alias (eigen hostname) toe als je die wilt. De officiële CDN Enabler integratiegids van KeyCDN loopt dit stap voor stap door. Maak een CNAME in je DNS (
cdn.jouwsite.nl CNAME jouwsite-abc123.kxcdn.com), voeg dezelfde hostname als Zone Alias toe in het KeyCDN dashboard en vraag daarna een gratis Let's Encrypt certificaat aan voor die alias in de SSL-sectie van KeyCDN. - Installeer CDN Enabler in WordPress en configureer hem met de CDN-hostname (zie de volgende sectie).
Controleer of het werkt. Zelfde aanpak als bij BunnyCDN: bekijk de bron, bevestig dat de asset URL's naar de CDN-hostname wijzen, vraag een asset twee keer op met curl en kijk in het KeyCDN dashboard naar de bandbreedte.
CDN Enabler, WP Rocket en W3 Total Cache: de URL-rewriting laag
Het CDN zelf herschrijft geen URL's in WordPress. WordPress schrijft asset URL's die naar je origin wijzen, en een WordPress-plugin herschrijft die naar de CDN-hostname voordat de pagina naar de bezoeker gaat. Er zijn drie veelgebruikte plugins die dit doen, en allemaal werken ze met elke pull zone CDN.
CDN Enabler (van KeyCDN) is de lichtste optie. Gratis, open source op GitHub en actief onderhouden (laatste forumactiviteit maart 2026). De configuratie staat onder Instellingen, CDN Enabler. Er zijn precies twee velden die ertoe doen: CDN Hostname (zet die op cdn.jouwsite.nl of welke je ook gekozen hebt) en Included File Extensions (de defaults bmp,bz2,css,gif,gz,... kloppen voor bijna elke site). De plugin onderschept de hele HTML response via een output buffer, doet een string replacement en herschrijft elke asset URL die hij tegenkomt. CDN-onafhankelijk by design, dus hij werkt met BunnyCDN, KeyCDN, CloudFront, R2 of wat dan ook dat je een hostname geeft.
De CDN-tab van WP Rocket doet hetzelfde werk binnen WP Rocket. CDN, Enable Content Delivery Network, voer dan je CNAME in onder "CDN CNAME(s)" en kies welke content-types je wilt laten herschrijven (afbeeldingen, JS, CSS). De documentatie van WP Rocket zelf loopt diezelfde flow door. RocketCDN, de optionele WP Rocket addon, is BunnyCDN white-labeled en kun je rechtstreeks vanuit dezelfde tab afnemen.
De CDN-tab van W3 Total Cache doet het ook. Performance, CDN, aanzetten, CDN type op "Generic Mirror" zetten (of de naam van je provider als die in de lijst staat) en de CDN-hostname invoeren. W3 Total Cache is van de drie het meest configureerbaar en het meest complex; het is overkill als URL rewriting de enige feature is die je ervan nodig hebt.
Kies één rewriter, nooit twee. Als WP Rocket URL's al herschrijft, zet er dan niet ook nog CDN Enabler bij. Dan proberen ze allebei dezelfde output buffer te bewerken en is het resultaat onvoorspelbaar, inclusief dubbel-herschreven URL's die naar cdn.jouwsite.nl/cdn.jouwsite.nl/wp-content/uploads/... wijzen en gewoon stoppen met laden.
De Cloudflare-uitzondering geldt hier ook. Draai je Cloudflare als reverse proxy, zet dan niet de CDN-tab van WP Rocket aan en installeer geen CDN Enabler. Cloudflare cachet je assets al op de edge onder je eigen domein. WP Rocket is juist Cloudflare-compatibel om die reden; de CDN-tab is voor een aparte CDN, niet voor Cloudflare proxy mode.
Voor het echt programmatische geval (geen plugin, alleen code) heeft WordPress twee filters waar CDN-plugins op haken:
// wp-content/mu-plugins/cdn-rewrite.php
// Schrijf media library URL's om naar de CDN-hostname.
add_filter( 'wp_get_attachment_url', function ( $url ) {
return str_replace( home_url(), 'https://cdn.jouwsite.nl', $url );
} );
// Schrijf entries in responsive image srcset om.
add_filter( 'wp_calculate_image_srcset', function ( $sources ) {
foreach ( $sources as &$source ) {
$source['url'] = str_replace(
home_url(),
'https://cdn.jouwsite.nl',
$source['url']
);
}
return $sources;
} );
Dit herschrijft attachment URL's en srcset entries voor responsive afbeeldingen, maar het raakt geen geënqueuede CSS of JS, geen background-images uit theme CSS en niets buiten de media library. Voor de meeste sites is de plugin-aanpak completer. De hooks zelf staan beschreven bij wp_get_attachment_url en wp_calculate_image_srcset.
Nog een opmerking over de UPLOADS constante in wp-config.php: als je oude artikelen hebt gelezen die define( 'UPLOADS', ... ) als CDN-stap presenteren, dan klopt dat niet. Die constante is een relatieve padoverride (altijd ten opzichte van ABSPATH, geen leading slash) voor waar WordPress geüploade bestanden lokaal wegschrijft. Hij staat gedocumenteerd in de wp-config.php reference van WordPress als een multisite-override en bestaat al langer dan zo'n beetje elke CDN-plugin. Hij regelt waar uploads lokaal staan, niet hoe die bestanden naar bezoekers worden geserveerd. Voor CDN-doeleinden kun je hem gewoon overslaan.
CloudFront: het AWS-pad
CloudFront is de juiste keuze als je al op AWS zit, als je liever flat-rate prijzen wil dan pay-as-you-go, of als je WAF en DDoS-bescherming bij je CDN ingebouwd wilt hebben. Het patroon is op WordPress-niveau hetzelfde als BunnyCDN en KeyCDN (maak een distribution, wijs hem naar je origin, configureer CDN Enabler met de distribution-hostname), maar de AWS-kant is meer configuratie dan het bunny.net dashboard.
Even kort iets over de pricing, want die verandert vaker dan de rest van CloudFront. Het traditionele pay-as-you-go model bestaat nog. In november 2025 voegde AWS flat-rate prijsplannen toe: Free ($0), Pro ($15/maand), Business ($200/maand) en Premium ($1.000/maand). De flat-rate plannen bundelen CDN met WAF, DDoS-bescherming, Route 53, CloudWatch, een ACM TLS-certificaat, edge compute en S3 storage credits. Of dat bundeltje goedkoper is dan een puur pull zone CDN als BunnyCDN hangt helemaal af van je verkeer en wat je sowieso al van AWS afneemt.
Cloudflare R2 voor het offloaden van WordPress media
Cloudflare R2 is het S3-compatibele object storage product van Cloudflare, en het is een populaire bestemming geworden voor WordPress media offload omdat R2 egress-bandbreedte gratis is. Storage kost $0,015 per GB per maand, punt. Er is geen per-GB transfer fee, dus een media library die veel afbeeldingsverkeer trekt kost ruwweg de opslag van de bestanden zelf en niets voor de bandbreedte.
Het setup-model is anders dan een pull zone CDN. In plaats van responses van je origin op een edge te cachen, migreer (offload) je je media library uit wp-content/uploads naar een R2 bucket. WordPress schrijft nieuwe uploads daarna direct naar R2 en herschrijft attachment URL's naar de custom domain van die bucket. Je origin server slaat helemaal geen media meer op.
Een aantal WordPress-plugins implementeert dit patroon:
- Codirun R2 Media & Static CDN
- Yctvn Media Offload for Cloudflare R2
- Media Cloud (voorheen ilab-media-tools)
- Next3 Offload
De grote lijn is: installeer een van deze plugins, maak in het Cloudflare dashboard een R2 bucket en een R2 API token aan, configureer de plugin met de bucketnaam en de credentials en laat hem op de achtergrond de bestaande media library migreren. Vanaf dat moment landen nieuwe uploads rechtstreeks in R2. Daarna hang je een custom domain aan de bucket (R2 ondersteunt custom domains native) zodat attachment URL's naar media.jouwsite.nl wijzen in plaats van naar de rauwe R2 URL. R2 buckets zitten automatisch achter het edge-netwerk van Cloudflare zodra je ze via een custom domain benadert, dus je krijgt edge caching gratis bovenop de offload.
Voor mediarijke sites met veel verkeer kan de rekensom heel aantrekkelijk zijn. Een community-gids over WordPress media offloaden naar R2 rapporteert TTFB op media-aanvragen die zakt van 180–400 ms op de origin naar 15–45 ms vanaf de edge na de migratie. De trade-off is dat je media nu in een ander systeem zit dan je WordPress-installatie, dus backups, restores en disaster recovery moeten met twee locaties rekening houden in plaats van met één.
Dynamische pagina's uit de cache houden
Een pull zone CDN met URL rewriting herschrijft alleen statische asset-URL's, geen WordPress HTML, dus het probleem van dynamische pagina's bestaat in het pull zone model grotendeels niet. WordPress genereert HTML op de origin elke keer opnieuw, ook voor pagina's als /checkout/, /cart/, /my-account/ en /wp-admin/. Het CDN ziet die HTML-responses nooit, want de URL-rewriting raakt alleen <img>-, <link href="...">- en <script src="...">-attributen voor bestanden in wp-content.
Toch is er één ding om over na te denken. Sommige asset-rewriters zijn iets te enthousiast en proberen ook admin-assets te herschrijven. Als je inlogt op wp-admin en je dashboard laadt een CSS-bestand vanaf cdn.jouwsite.nl/wp-admin/css/..., dan komt die admin CSS uit de CDN-cache en loop je het risico dat je na een WordPress core-update nog steeds de oude admin-styling te zien krijgt. De default include-lijst van CDN Enabler vermijdt dit omdat de rewriter de extensielijst respecteert en admin-paden gewoon doorvallen, maar als je de regels hebt aangepast is het wel even nakijken waard.
Draai je een full proxy CDN (Cloudflare met HTML-caching aan, of APO), dan is het verhaal voor dynamische pagina's compleet anders en moet je expliciet de cache bypassen voor /wp-admin/, /wp-login.php, /wp-json/, de wordpress_logged_in_*-cookies en alle WooCommerce session-cookies. Dat is het terrein van het Cloudflare-configuratie-artikel, niet van dit artikel.
CDN-aflevering testen vanaf de command line
Zodra de URL-rewriting staat en het CDN ervoor zit, test je het met curl in plaats van te vertrouwen op je browser, want de browser cache liegt over of het CDN nu echt iets doet of niet.
# 1) Bevestig dat de CDN-hostname resolved en het bestand serveert.
curl -I https://cdn.jouwsite.nl/wp-content/uploads/2026/04/voorbeeld.jpg
# Verwachte output (verkort):
# HTTP/2 200
# content-type: image/jpeg
# cdn-cache: MISS # eerste aanvraag na cache eviction
# server: BunnyCDN-...
# cache-control: public, max-age=...
# 2) Vraag hetzelfde bestand nog een keer op zodat het edge-gecached is.
curl -I https://cdn.jouwsite.nl/wp-content/uploads/2026/04/voorbeeld.jpg
# Verwachte output (verkort):
# cdn-cache: HIT # uit de edge cache, zonder origin-hit
De header die de cache hit bevestigt is provider-specifiek. BunnyCDN stuurt CDN-Cache: HIT, KeyCDN stuurt X-Cache: HIT, CloudFront stuurt X-Cache: Hit from cloudfront en Cloudflare (als die assets direct proxiet) stuurt cf-cache-status: HIT. Je weet dat het CDN werkt als de tweede aanvraag de HIT-header teruggeeft en de responstijd een orde van grootte sneller is dan de eerste.
Een tweede test, deze keer op de WordPress-pagina zelf, bevestigt dat de URL rewriting daadwerkelijk staat:
curl -s https://jouwsite.nl/ | grep -oE 'src="https://[^"]+"' | head -10
Als de rewriter zijn werk doet, wijzen de meeste asset URL's in de homepage HTML naar cdn.jouwsite.nl en niet meer naar jouwsite.nl. Wijzen ze nog naar jouwsite.nl, dan staat de rewrite-plugin niet aan of dekt zijn include-lijst niet de bestandstypen die je zoekt.
Wat er meestal misgaat en waar je het eerst kijkt
Drie failure modes zijn samen verantwoordelijk voor zo'n beetje elke "ik heb een CDN ingesteld en nu is mijn site stuk"-vraag die ik tegenkom.
Mixed content waarschuwingen op HTTPS-pagina's. De CDN-hostname is in de rewriter als HTTP geconfigureerd (http://cdn.jouwsite.nl) terwijl je WordPress-site HTTPS draait. Browsers blokkeren mixed content. Fix: zet de CDN-hostname in de rewriter-plugin op https://cdn.jouwsite.nl en zorg dat je via BunnyCDN, KeyCDN of welke provider dan ook een SSL-certificaat hebt uitgegeven voor die hostname.
Verouderde assets na een WordPress- of theme-update. Je hebt style.css in je theme aangepast en het CDN serveert nog steeds de oude versie. Of je purge de asset uit het CDN dashboard, of je vertrouwt op de cache-busting query string die WordPress aan geënqueuede assets hangt (?ver=6.8) om de cache automatisch te invalideren als de versie van het bestand verandert. CDN Enabler respecteert query strings standaard. Theme-developers die asset URL's hardcoden zonder wp_enqueue_style slaan die bescherming over en moeten handmatig purgen.
Cloudflare en een pull zone CDN herschrijven allebei URL's. Dit is de architectuurfout uit de eerste secties. Zit je op Cloudflare en zet je daar ook nog CDN Enabler met een cdn.jouwsite.nl-hostname bij aan, dan worden assets geserveerd vanaf een hostname die Cloudflare niet bezit, fragmenteert de cache en wordt de pagina trager in plaats van sneller. Kies er één. De fix is óf het pull-zone-deel uitzetten en het automatische statische cachen van Cloudflare zijn werk laten doen, óf de oranje wolk uitzetten op de asset-hostname (en zo gebruikt Cloudflare niet wat het wil zijn).
Hoe je controleert dat de hele setup zijn werk doet
Loop na alles hierboven nog deze laatste check door:
- Open de site in een privé-venster met DevTools open en het Network-tabblad gefilterd op afbeeldingen.
- Bevestig dat elke afbeeldingsaanvraag naar je CDN-hostname gaat en niet naar de origin.
- Bevestig dat de response headers op die afbeeldingen na de eerste aanvraag een cache HIT laten zien.
- Bevestig dat de TTFB van de pagina in DevTools (de "Waiting"-fase op het document-request) ongeveer hetzelfde is als voor de CDN-installatie, want je origin rendert nog steeds de HTML.
- Bevestig dat de totale page transfer size en de tijd-tot-volledig-geladen omlaag zijn, omdat afbeeldingen en assets nu vanaf de edge laden.
Klopt een van die vier niet, dan zit het CDN niet voor de assets waar jij denkt dat het voor zit. Loop nog een keer langs de configuratie van de URL-rewriting plugin, de include-lijst met bestandsextensies en de DNS- en SSL-setup van de CDN-hostname voordat je aanneemt dat het CDN zelf stuk is.