Cache keys and immutability
Every CDN URL is a contract:Accept + Save-Data + Client Hints when used. That means:
- Changing
w,format, or any transform param creates a new cache entry (by design). - Reusing the same URL always hits the same bytes — ideal for
Cache-Control: immutablesemantics. - Do not overwrite files in place if you need instant updates; upload a new
fileIdor purge.
Prefer new file IDs over in-place overwrites
| Pattern | Cache behaviour |
|---|---|
| Upload v2 as new file, update HTML | Old URL keeps serving v1; new URL is fresh |
| Overwrite bytes at same file ID | Edge may serve stale bytes until TTL or purge |
Purge asset:{fileId} tag | Invalidates all transform variants for that file |
Format negotiation
Useformat=auto (SDK default) so modern browsers get AVIF/WebP and legacy clients get JPEG from one URL string. Convertly sets Vary: Accept — at most two encoded variants per transform URL.
See Format & delivery.
Responsive delivery
- Most sites:
<ConvertlyImage>orsrcset+sizes— see Responsive images. - Fluid layouts:
ch=Width,Dpr— see Client Hints guide. - Art direction:
<picture>with differentw/h/gravityper breakpoint.
dpr=2 with a fixed w — see Device pixel ratio).
Presets reduce mistakes
Named presets (hero, thumb, og-card) keep param sets consistent across teams and reduce accidental cache fragmentation from typos.
Purge strategy
| Scenario | Recommendation |
|---|---|
| Single known URL changed | Purge by URL |
| File replaced in storage, many widths live | Purge by tag asset:{fileId} |
| Redeployed entire origin folder | origin:{slug} tag purge |
| Routine content updates | New file ID — skip purge |
Origin deliverability
Convertly fetches origin-backed URLs (/o/{slug}/…) over public HTTPS or private bucket credentials. If transforms fail or return errors, check the following.
Public HTTPS origins
| Check | Why it matters |
|---|---|
| URL returns 200 in a private browser tab | CDN must fetch without cookies |
| HTTPS with valid certificate | HTTP and self-signed are rejected |
Not localhost / 127.0.0.1 / RFC1918 IPs | Public CDN cannot reach your laptop |
Correct Content-Type (image/jpeg, etc.) | Wrong MIME can break encode pipeline |
| No hotlink blocking that blocks Convertly’s fetcher | Some WAF rules block unknown user agents |
| Response under size limits | Very large originals slow first transform |
localPassthrough or point the origin at a preview deploy or HTTPS tunnel — see Image CDN setup and Operations → Local development.
Private bucket origins (S3, R2, GCS, Azure)
| Check | Why it matters |
|---|---|
| Read credentials are valid and not expired | Convertly decrypts stored creds server-side only |
| Bucket + path prefix match the object key | pathPrefix is prepended to every fetch |
| IAM / policy allows GetObject on the prefix | Write access is not required |
| Region / endpoint matches provider | R2 and custom S3 endpoints need explicit endpoint |
Common error patterns
| Symptom | Likely cause |
|---|---|
| 403 on CDN URL, JSON body about signed URL | Namespace is signed/private — add ?s= via signing API |
| 502 / upstream fetch failed | Origin URL 404, timeout, or credentials rejected |
| Image never updates after deploy | Browser + CDN cache; bump file id or purge |
| Works in prod, not locally | Expected — use passthrough or public preview origin |
Smart crop cost
gravity=smart and gravity=face run analysis on cache miss only. Popular URLs pay once, then serve from edge indefinitely. For zero per-request analysis, persist focal points from POST /api/images/analyze and render with fp=x,y.
Security vs performance
publicnamespaces: fastest path — embed URLs directly in HTML.signed/privatenamespaces: every URL needs server-side signing — plan for sign API latency at render time, not per browser request if you cache signed URLs untilexp.
Related docs
- Operations — purge, origins, security
- URL structure — namespaces, slugs, custom domains