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.

What to purge after deployHashed staticnever purgeCached HTMLpurge by URL or tagFixed-name filespurge or renameAutomate in CIAPI tokenVersioned asset names make most purges unnecessary.
  1. Use ManifestStaticFilesStorage (or WhiteNoise's compressed manifest storage) so every changed static file gets a new name; no purge needed.
  2. If the CDN caches HTML, purge the affected URLs (or tags with Cloudflare Enterprise and Fastly) after deploy.
  3. Automate purges from CI with a scoped API token, after the new release is healthy.
  4. Avoid purging everything except for emergencies; it spikes origin load.
  5. 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.

does this file need a purge?How is the file named and cached?hashed static fileNo purgenew name per changecached HTML pagePurge URLs or tagsafter deployfixed-name assetPurge or renamefavicon, robotsVersioned names handle most assets; purge only what keeps its URLdjango-deployment.com
Purge everything only in emergencies, such as leaked private content.

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.

in the deploy pipeline1Deploy new releasehashed assets included2Health checks passall instances3Purge changed HTMLURLs or tags4Purge fixed-name filesif they changed5Watch origin loadcache refillPurge after the new release is live, never beforedjango-deployment.com
Static assets do not appear in this list because their URLs change.

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-age on 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

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.

Keep going