Servire asset statici da Cloudflare R2 invece che da S3: vantaggi, regole e limiti
Quando spostare asset e directory statiche su Cloudflare R2 invece che su S3: costi, SSG, domini personalizzati, regole di cache e architettura di produzione.
Gli asset statici sembrano banali finché non diventano una voce grande e poco prevedibile della fattura. Screenshot di prodotto, PDF, video, font, export di documentazione, report generati e build scaricabili spesso iniziano nello stesso bucket. Quando il traffico cresce, il problema non è più solo lo storage. È la distribuzione.
Cloudflare R2 cambia il modello: object storage compatibile con S3, nessun costo di egress da R2 verso Internet e un percorso semplice per servire il bucket dietro un dominio gestito da Cloudflare. Ma R2 non sostituisce ogni forma di hosting statico. La scelta dipende da cosa stai servendo: un’applicazione web o oggetti.
Il problema reale non è salvare file
Un sistema pubblico di asset deve fare quattro cose:
- Conservare oggetti in modo durevole.
- Esporre URL sotto un hostname controllato.
- Mettere in cache aggressivamente i file più richiesti.
- Invalidare o versionare i cambiamenti in modo prevedibile.
S3 lo fa spesso con CloudFront davanti. R2 lo fa con un dominio personalizzato Cloudflare, Cache Rules, WAF, Access e Workers quando serve logica. La differenza pratica non è solo l’API del bucket. È dove vive lo strato edge e quanto costano i byte serviti agli utenti.
Quando R2 è la scelta giusta
R2 funziona molto bene per file pubblici, letti molte volte e relativamente stabili:
- asset con hash come
app.4f3a1c.cssovendor.91bc2.js - immagini, video, font e media Open Graph
- PDF, whitepaper, report e download pubblici
- release, dataset, file di modello e archivi grandi
- directory statiche in cui l’URL deve mappare a una chiave oggetto
Il vantaggio è sia economico sia operativo. R2 non addebita egress da R2 a Internet, supporta molti strumenti compatibili con S3 e permette di gestire cache, sicurezza e regole di delivery nello stesso control plane Cloudflare.
SSG o delivery diretto da R2?
La prima domanda è: stai servendo pagine o file?
Usa SSG per HTML e route. Astro, Cloudflare Pages, Workers Static Assets, Netlify o Vercel capiscono route come /pricing, fallback SPA, redirect, header per route, pagine 404 e deploy atomici. È quello che serve per siti marketing, documentazione, blog e applicazioni dove contano SEO, canonical, structured data e status code.
Usa R2 diretto quando il path identifica un file:
https://assets.example.com/brand/logo.svg
https://downloads.example.com/reports/audit-2026.pdf
https://releases.example.com/app/1.8.4/linux-amd64.tar.gz
R2 non deduce automaticamente che /docs/ debba servire /docs/index.html o che /app/settings debba cadere su /app/index.html. Puoi aggiungere un Worker davanti a R2, ma a quel punto stai costruendo un piccolo static host. Può essere corretto, ma deve essere una scelta esplicita.
Pattern di produzione consigliati
Il pattern più sicuro è mantenere il sito su una piattaforma SSG e spostare i file pesanti su R2:
www.example.com -> sito o applicazione
assets.example.com -> bucket R2 pubblico
downloads.example.com -> bucket R2 pubblico
Così mantieni route HTML, preview, redirect e segnali SEO nella piattaforma del sito, mentre immagini, PDF e release vengono serviti da R2 con la cache Cloudflare.
Per archivi pubblici versionati, R2 può servire direttamente un albero di oggetti. Non usare il listing del bucket come navigazione. Pubblica una pagina indice dal sito principale o carica un index.html esplicito se gli utenti devono esplorare i file.
Se servono autenticazione, token, normalizzazione dei path o header dinamici, metti un Worker davanti a R2. Il Worker può validare la richiesta, risolvere la chiave oggetto, impostare Cache-Control e restituire il file.
Dominio personalizzato, cache e sicurezza
In produzione usa un dominio personalizzato come assets.example.com. L’endpoint r2.dev è comodo per testare, ma non dovrebbe essere la superficie pubblica principale. Un dominio personalizzato consente Cache Rules, WAF, Access, regole bot e Workers.
Le regole di cache dovrebbero essere esplicite:
- Asset con hash:
Cache-Control: public, max-age=31536000, immutable. - File mutabili come
latest.zip,catalog.jsonoindex.html: TTL breve e purge durante il deploy. - Download privati o firmati: bypass cache o cache key progettata correttamente.
Cache Everything: solo sull’hostname del bucket, non globalmente sull’applicazione.
Anche la pipeline di upload conta. Ogni oggetto deve avere il Content-Type corretto e metadata di cache coerenti. JavaScript servito come application/octet-stream o SVG con tipo errato può rompere browser, preview e policy di sicurezza.
R2 vs S3: regola pratica
S3 resta sensato per aziende fortemente AWS-native, con CloudFront, IAM, signed URLs, logging e governance già pronti. R2 diventa interessante quando l’egress pesa sui costi, gli asset sono pubblici o semi-pubblici e Cloudflare è già lo strato edge.
Regola operativa:
- Pagine HTML e route applicative: SSG, Pages o Workers Static Assets.
- File pubblici grandi e asset immutabili: R2 dietro un dominio personalizzato.
- Alberi pubblici semplici: R2 diretto.
- Alberi con auth o routing: Worker davanti a R2.
- Workflow privati profondamente integrati con AWS: S3 può restare la scelta migliore.
L’architettura migliore raramente è “R2 per tutto”. È più precisa: lascia le pagine allo strumento pensato per le pagine, sposta i byte pubblici ad alto volume su R2 e applica cache e sicurezza nel punto reale di ingresso del traffico.