Purge the Cloudflare or CDN Cache After a Django Deploy
Decide what to purge from Cloudflare or another CDN after deploying Django: rely on hashed static file names, purge cached HTML by URL or tag, automate purges from CI with an API token, avoid purge-everything, and keep old assets available during rollouts.
Problem statement
After a deploy, some users still see the old design, a page references a JavaScript file that returns 404, or a fixed bug persists for hours. The CDN is serving cached copies. The reflex is to click "Purge Everything", which works but sends a wave of requests to your origin and still does not fix the underlying design. Most purges are unnecessary when static files are versioned, and the remaining ones can be targeted and automated.
- Use
ManifestStaticFilesStorage(or WhiteNoise's compressed manifest storage) so every changed static file gets a new name; no purge needed. - If the CDN caches HTML, purge the affected URLs (or tags with Cloudflare Enterprise and Fastly) after deploy.
- Automate purges from CI with a scoped API token, after the new release is healthy.
- Avoid purging everything except for emergencies; it spikes origin load.
- Keep previous releases' hashed files available so cached HTML from the old release still works.
Step-by-step solution
1. Version static files
STORAGES = {
"default": {"BACKEND": "django.core.files.storage.FileSystemStorage"},
"staticfiles": {"BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage"},
}
{% static "css/app.css" %} renders as /static/css/app.3f2a1c9b.css. When the file changes, the hash and URL change, so the CDN fetches the new file automatically. Cache hashed files for a year with immutable. Files referenced by fixed names outside Django's static system (a favicon.ico, robots.txt, files linked from emails) still need purging or versioned names.
2. Purge HTML deliberately
If you cache HTML at the edge (Cloudflare Cache Rules, page caching), changed templates do not reach users until the cached pages expire. Purge only what changed:
curl -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/purge_cache" \
-H "Authorization: Bearer $CF_API_TOKEN" -H "Content-Type: application/json" \
--data '{"files": ["https://shop.example.com/", "https://shop.example.com/pricing/"]}'
Cloudflare also supports purging by prefix, hostname, and cache tag on certain plans. With Fastly, purge by surrogate key.
3. Automate from CI
Create a Cloudflare API token limited to Zone.Cache Purge for the zone and store it as a CI secret. Run the purge after the deploy is verified healthy, not before, or the CDN may refetch old content from servers still running the previous release:
- name: Purge CDN HTML
if: success()
run: |
curl -fsS -X POST "https://api.cloudflare.com/client/v4/zones/${{ secrets.CF_ZONE_ID }}/purge_cache" \
-H "Authorization: Bearer ${{ secrets.CF_API_TOKEN }}" -H "Content-Type: application/json" \
--data @purge-urls.json
Generate purge-urls.json from the pages affected by the release, or a fixed list of high-traffic pages if HTML is cached.
4. Avoid purge-everything
Purging the whole zone makes every request a cache miss at once, so your origin receives full traffic until caches refill. With a heavily cached site, that can overload Django right after a deploy. If you need it, do it at a quiet time and make sure origin capacity can absorb the spike.
5. Keep old assets during rollouts
During a rolling deploy, some users receive HTML from the old release referencing old hashed files. If those files were deleted (collectstatic --clear, or a fresh volume without old files), they 404. Serve static files from the image (each release contains its own files) or keep old files in the bucket for a few days.
Explanation
A CDN caches by URL. If a URL's content changes while the URL stays the same, cached copies are stale until they expire or are purged. Content-hashed file names avoid the problem entirely for static assets, because new content gets a new URL and old URLs never change meaning. HTML pages keep stable URLs, so if they are cached at the edge they need explicit invalidation, ideally targeted and automated, timed after the new release is serving.
Edge cases / notes
- Browser caches. Purging the CDN does not clear users' browser caches; short
max-ageon HTML and hashed assets handle that. - Cloudflare tiered cache. Purges apply across tiers, but a refill wave still hits your origin.
- API limits. Purge APIs have rate and size limits per request; batch URL lists.
Next steps
- Configure HTML caching with Cache Django Pages With Cloudflare.
- Version assets with Django Static Files Cache Busting.
- If changes still do not appear, see Fix Django Code Changes Not Showing After Deploy.
FAQ
Do I need to purge Cloudflare after every Django deploy?
Not for hashed static files. Only for cached HTML or fixed-name files that changed.
Is Purge Everything safe?
It works but sends a burst of uncached traffic to your origin. Use targeted purges instead.
When should the purge run?
After the new release is deployed and healthy, so the CDN refetches new content.
Why do users get 404s for CSS after a deploy?
Old cached HTML references old hashed files that were deleted. Keep previous releases' files available.