Patterns from this design

Global image delivery with CloudFront and edge-side transformation

caching

Cache-key allowlist and normalization

When
Any CDN where clients shape responses via query params (size, format, locale) and junk params (utm, session) would otherwise mint infinite cache objects.
AWS
CloudFront cache policy allowlisting only the params that change the bytes, plus a CloudFront Function on viewer-request that sorts, lowercases, and clamps them to a fixed breakpoint set in ~1 ms.
Trade-off
You quantize the request space - arbitrary widths snap to the nearest breakpoint - giving up pixel-exact requests for a bounded, high-hit-ratio cache.
caching

Conditional same-key request coalescing

When
Same-key cold spikes (a hot hero image) cause thundering-herd misses AND the per-miss origin work is expensive (transform, re-encode). Not worth it for cheap static origins, and it does nothing for launches of many distinct keys.
AWS
CloudFront Origin Shield, one per CRR region, as the regional collapse point so concurrent edge misses for one key become one origin fetch; each POP routes to its nearest Shield.
Trade-off
Adds a cache hop and per-request fee; splits the coalescing cache across regions; and is not HA - when a Shield degrades CloudFront bypasses it and floods origin, so pre-compute, not Shield, is the launch-shock and SPOF protection.
media-cdn

Two-tier edge compute split

When
Edge logic mixes cheap per-request string work (key rewrite, auth check) with expensive per-miss byte work (image transform).
AWS
CloudFront Functions (1 ms, no cold start) on viewer-request for normalization and signed-URL validation; Lambda at edge on origin-request for the transform, running on misses only.
Trade-off
Two runtimes to test and deploy, with Lambda at edge replication lag on every change - in exchange for a roughly 7x cheaper viewer layer.
caching

Versioned URLs over invalidation

When
Content changes you control (re-uploads, catalogue refreshes) need fresh bytes without racing the cache or burning CloudFront's 3000-path / 15-wildcard-per-sec quota.
AWS
Embed a version in the path (img/v3/id.jpg) backed by a DynamoDB version map; bump the version to mint a guaranteed-fresh key. Reserve wildcard invalidation plus short TTL for legal takedowns only.
Trade-off
URL generators must know the current version (a lookup), coupling the app to a version table instead of treating URLs as static.
media-cdn

Pre-compute as the primary path

When
Derivatives are small and predictable and re-requested over a lifetime, so V x P_render is less than F_avg x P_transform - making pre-compute cheaper than on-the-fly and keeping Lambda off the critical path (concurrency, failover, SWR cold-miss gaps).
AWS
S3 upload event triggers Step Functions to validate (magic bytes, dimension caps, Rekognition moderation), render all standard variants to S3, and warm-prefetch them through CloudFront before go-live; on-the-fly Lambda at edge transform is the long-tail fallback only.
Trade-off
You store variants that may never be requested and re-render on a schema or transform-version change - only wins when the variant set is small and the crossover inequality holds (fails for high-cardinality, rarely-requested UGC).
media-cdn

Three-layer per-tenant isolation

When
Multi-tenant delivery where a valid signature must not be enough to read another tenant's content - isolation has to bind signing, path, and IAM, not just trust a key.
AWS
CloudFront Trusted Key Groups per tenant validated in the viewer Function, which also scopes the signed Resource to the tenant prefix, asserts the requested prefix matches the validating key group, and rejects path traversal; the transform role assumes a session tagged with the authenticated tenant ID so an s3:prefix IAM condition bounds its read per request; S3 keys derived server-side to eliminate SSRF.
Trade-off
Config and CMKs grow with tenant count against the behaviors-per-distribution cap, forcing sharding (dedicated behaviors/distributions for large tenants, shared prefix-routed behavior for the long tail) - and sharding fixes signing isolation only, so the session-tag prefix condition is the separate control for origin/IAM isolation.