Cloudflare R2 vs Supabase Storage: quando aggiungere R2 nel 2026
Sei già su Supabase. L'egress dello Storage costa da $0.03 a $0.09 per GB, R2 non addebita nulla. Ecco il punto in cui aggiungere R2 conviene davvero nel 2026.
L'object storage è un namespace piatto di file serviti via HTTP, fatturato in due modi: per i gigabyte che tieni e per i gigabyte che muovi. Se hai un SaaS su Supabase, l'object storage ce l'hai già. Quindi la domanda vera nel 2026 non è quasi mai quale provider scegliere da zero. È se lo storage incluso in Supabase basta, oppure se aggiungere Cloudflare R2 per i media pesanti. La risposta dipende quasi solo da un numero: l'egress.
In breve. Tieni i file su Supabase Storage quando sono privati, legati a un utente loggato e serviti a basso volume. L'integrazione con la row-level security e i transform delle immagini inclusi valgono più dell'egress che risparmieresti. Aggiungi Cloudflare R2 quando servi media pubblici su larga scala: l'egress a costo zero trasforma una bolletta che sale con il successo del prodotto in una che sale solo con quanto archivi. Molti team finiscono per usarli entrambi, divisi lungo la linea pubblico/privato.
Quanto costano nel 2026
I due servizi prezzano lo storage a meno di un terzo di distanza. Prezzano l'uscita dei byte a un ordine di grandezza di distanza. È in quel divario che si decide tutto.
- Storage per GB al mese. R2 costa $0.015 sul tier Standard e $0.01 su Infrequent Access. Supabase Storage include 100 GB nel piano Pro da $25, poi $0.021 per GB. Sui soli byte archiviati R2 costa meno, ma lo storage è raramente la voce che fa male.
- Egress verso internet. R2 non addebita nulla, tramite l'API S3, l'API Workers, il dominio r2.dev o un dominio custom. Supabase fattura l'egress a $0.09 per GB non in cache e $0.03 per GB servito dalla sua CDN, con 250 GB inclusi nel piano Pro. È questa la differenza che si accumula.
- Operazioni. R2 fattura $4.50 per milione di operazioni Class A (scritture, list) e $0.36 per milione di Class B (letture). Supabase conteggia le richieste allo storage nel suo normale conteggio delle richieste, invece di fatturare per operazione sull'oggetto.
- Quota gratuita. R2 dà 10 GB di storage, 1 milione di operazioni Class A e 10 milioni di Class B ogni mese. Il piano Free di Supabase include 1 GB di file storage e 5 GB di egress, condivisi su tutto il progetto.
Sono prezzi di listino in dollari, prima di qualsiasi sconto a volume. Le cifre arrivano direttamente dalla pagina prezzi di R2 e dalla documentazione prezzi di Supabase Storage. Verificale contro il tuo traffico reale prima di decidere.
Il calcolo dell'egress, quello che nessuno fa prima della bolletta
Due fatti sull'egress di Supabase decidono gran parte di questo confronto, e sono entrambi facili da non vedere.
Primo, l'egress incluso è condiviso. I 250 GB del piano Pro non sono una quota per lo storage. Sono un unico pool consumato insieme dalle query al database, dalle chiamate ad Auth, dai canali Realtime, dalle Edge Functions e dai download dallo storage. Una dashboard con tante query può consumare gran parte di quella quota prima ancora che venga servita una sola immagine. Il titolo "250 GB inclusi" è il tetto per tutto il backend, non per i media.
Secondo, egress in cache ed egress non in cache costano cifre diverse. I byte serviti dalla cache CDN di Supabase costano $0.03 per GB. I byte che mancano la cache e arrivano all'origine costano $0.09 per GB, come il vecchio S3. Un asset pubblico ben messo in cache costa un terzo a servirlo rispetto a uno non in cache, ed è per questo che il tasso di cache hit, non il traffico grezzo, è il dato che muove la bolletta dello storage su Supabase. Supabase ha triplicato lo sconto sulla cache e raddoppiato la quota inclusa in un aggiornamento prezzi del 2025, quindi i confronti vecchi che citano un $0.09 fisso sono superati.
Mettiamoci dei numeri. Un video di prodotto da 50 MB scaricato 20.000 volte in un mese sono circa 1 TB di egress. Su Supabase Pro, oltre il pool incluso, quel singolo asset costa circa $30 se ogni byte è in cache e circa $90 se nessuno lo è. Su R2 lo stesso terabyte non costa nulla in egress, più qualche centesimo di letture Class B. Un solo file popolare basta a giustificare un secondo bucket.
Dove vince Supabase Storage
Il motivo per tenere i file su Supabase non è il prezzo. È che lo storage è già collegato al resto dello stack.
L'autorizzazione arriva dal database. Un oggetto dello storage è governato dalle stesse policy di row-level security delle tue tabelle. Un utente loggato legge solo i file del proprio tenant, grazie a una policy che fa il join con la riga che referenzia il file. Nessun secondo modello IAM, nessuna rotazione di chiavi separata, nessuna gestione di signed URL. Per i file privati legati all'utente è questa la cosa che conta, e R2 non ha un equivalente.
I transform delle immagini sono inclusi. Supabase ridimensiona e riconverte le immagini al volo tramite la sua API di trasformazione a $5 per 1.000 immagini di origine, le prime 100 gratis, e converte in WebP in automatico per i browser che lo supportano. R2 non ha alcun transform nativo: aggiungeresti Cloudflare Images come prodotto a parte o useresti un Worker di trasformazione. Se servi avatar, thumbnail o set di immagini responsive, quella pipeline inclusa è un motivo concreto per tenere le immagini su Supabase.
Un servizio, un solo SDK. Upload, download e policy di accesso usano lo stesso client Supabase che già chiami per le query. Lo Storage parla anche il protocollo S3 e supporta upload ripristinabili fino a 50 GB per file sul piano Pro, così file grandi e tooling S3 standard funzionano senza uscire dalla piattaforma.
Dove vince Cloudflare R2
R2 inizia a convenire nel momento in cui i byte escono dai tuoi server in quantità.
Egress zero, a qualsiasi scala. È il titolo, e tiene. Servire 5 TB o 50 TB di media pubblici costa lo stesso in egress: nulla. Una bolletta che su Supabase o S3 salirebbe a ogni condivisione, ogni embed e ogni picco di attenzione resta invece piatta e segue solo quanto archivi. Per video, asset scaricabili o immagini servite in modo ampio via CDN, non c'è confronto.
Storage più economico e un tier freddo. Lo storage Standard costa $0.015 per GB, e Infrequent Access lo porta a $0.01 per i dati che leggi di rado, con $0.01 per GB di recupero e una durata minima di 30 giorni. Per upload utente a coda lunga, backup o log che restano intoccati per mesi, il tier freddo sta sotto il $0.021 fisso di Supabase.
È cresciuto oltre il semplice object storage. R2 ora offre le event notification che inviano a una coda e attivano un Worker a ogni modifica, e R2 Data Catalog, uno strato gestito Apache Iceberg per interrogare gli oggetti come tabelle. Supabase ha risposto lo stesso anno con gli Analytics Buckets, anche loro basati su Iceberg. I due convergono verso lo stesso futuro analitico partendo da punti opposti, segno che la scelta dello storage in sé si sta restringendo a egress e integrazione.
Il punto di pareggio: quando aggiungere davvero R2
Il fattore scatenante non sono i byte archiviati. Il divario tra $0.015 e $0.021 per GB è reale ma piccolo, e dovresti archiviare terabyte perché conti da solo. Il fattore scatenante è l'egress.
La linea onesta: finché l'egress dei tuoi media pubblici sta dentro l'egress che il piano già include, dopo il traffico di database e API che condividono il pool, Supabase Storage è di fatto gratis con l'abbonamento, e aggiungere R2 è complessità prematura. Quando i download dei media diventano la voce principale della bolletta Supabase, da centinaia di gigabyte a terabyte al mese, l'egress zero di R2 vince in modo netto, anche mettendo in conto la gestione di un secondo servizio.
Il segnale più chiaro è un piccolo gruppo di asset che genera traffico sproporzionato: un video di lancio, un download popolare, un'immagine pubblica incorporata su mezzo web. Il giorno in cui l'egress di quel file diventa una cifra vera in fattura, sposta i media pubblici su R2 e lascia il resto dov'è.
L'assetto ibrido su cui finiscono molti SaaS
La divisione che funziona corre lungo la linea pubblico/privato, e combacia anche con la linea dell'egress.
I file privati e legati all'auth restano su Supabase Storage: dati di profilo, documenti per tenant, CSV caricati, tutto ciò in cui il join della RLS fa vera autorizzazione e il traffico è modesto. I media pubblici e serviti in modo ampio passano su R2 dietro una CDN Cloudflare: immagini marketing, foto prodotto, video, risorse scaricabili, tutto ciò il cui pubblico è chiunque e il cui costo è l'egress.
Spostare un file fuori da Supabase ti costa due cose, e ognuna la sostituisci in modo consapevole. Perdi l'autorizzazione RLS, quindi i media pubblici su R2 li servi in chiaro, dietro un Worker che verifica una sessione prima di servire l'oggetto, oppure con signed URL a tempo. Perdi i transform delle immagini inclusi, quindi pre-generi le varianti, aggiungi Cloudflare Images o usi un Worker di trasformazione. Per asset davvero pubblici nessuna delle due perdite morde: non c'è un utente da autorizzare, e le varianti si generano una volta sola.
Migrare i media pubblici da Supabase a R2
La migrazione è più noiosa che difficile, e la copia dei byte è la parte facile. Super Slurper di Cloudflare tira da S3 e Google Cloud Storage, non da Supabase, quindi qui non c'è un import con un clic. Punti invece rclone sull'endpoint S3-compatibile di Supabase come sorgente e R2 come destinazione, e lo lasci trasferire gli oggetti. Uno spostamento una tantum di qualche centinaio di gigabyte gira in un pomeriggio.
Il lavoro vero è il livello di accesso, e lo fai prima di copiare qualsiasi cosa. Ogni code path che prendeva un file tramite il client Supabase, appoggiandosi alla RLS per l'autorizzazione, va riscritto per prenderlo da R2 con il suo nuovo modello: pubblico per gli asset aperti, un signed URL o un controllo via Worker per ciò che va ancora protetto. Mappa prima quei percorsi. Poi tieni i due store in parallelo per almeno un ciclo di fatturazione: scrivi i nuovi upload su entrambi, leggi prima da R2 con Supabase come fallback, e smetti di scrivere su Supabase solo quando il percorso di lettura da R2 risulta pulito nei log. Sposta le letture prima delle scritture, e le scritture per ultime.
Cosa scegliamo di default nel 2026
Per un SaaS nuovo in cui Supabase è già database e livello di auth, il nostro default è partire con il solo Supabase Storage. È un servizio in meno, l'autorizzazione è gratis, e la maggior parte dei prodotti non spinge mai abbastanza egress pubblico da aver bisogno d'altro. Aggiungiamo R2 solo quando la forma del traffico lo richiede: un prodotto ricco di contenuti, una libreria di media, un download pubblico che cresce con il marketing più che con il numero di utenti.
Quando R2 entra, entra per un compito solo, i media pubblici dietro una CDN, mentre Supabase tiene tutto ciò che è legato a un utente. La trappola è puntare su R2 dal primo giorno perché il titolo dell'egress zero è attraente. Un secondo servizio di storage che non ti serve ancora è complessità che paghi in ogni percorso di upload, ogni controllo di accesso e ogni migrazione, molto prima che ti faccia risparmiare un centesimo. Lo storage è una tubatura. Aggiungi il secondo tubo quando il primo è davvero sotto pressione, non prima.
Se la tua decisione deve pesare anche Amazon S3, per un'infrastruttura AWS esistente o una certificazione di compliance specifica, trattiamo il confronto a tre in Cloudflare R2 vs S3 vs Supabase Storage.
Domande frequenti
- Does Supabase Storage run on Amazon S3 under the hood?
- No. Supabase Storage is its own service, fronted by Postgres and governed by row-level security, that happens to speak the S3 protocol so standard S3 clients and tools work against it. It does not inherit S3's pricing, its storage classes, or its egress model. The practical consequence is that you can point an AWS SDK or rclone at a Supabase bucket, but you are billed by Supabase's rules ($0.021 per GB stored, $0.03 to $0.09 per GB egress), not Amazon's.
- How do I protect private files on R2 without Supabase's RLS?
- R2 has no row-level security, so you replace it at the application edge. The two common patterns are time-limited signed URLs, where your backend mints a short-lived URL after checking the user's session, and a Cloudflare Worker in front of the bucket that validates a session or JWT before streaming the object. Both work, but both are code you write and maintain. This is exactly why private, user-scoped files are usually better left on Supabase Storage, where the database policy does the same job for free.
- Will moving images to R2 break my resizing and WebP conversion?
- Yes, if you rely on Supabase's built-in transforms. Supabase resizes and converts images to WebP on the fly; R2 does nothing of the kind. When you move images to R2 you pick one of three replacements: pre-generate the variants you need at upload time and store each one, add Cloudflare Images as a separate transform layer in front of R2, or run a Worker that resizes on request and caches the result. For a fixed set of sizes (a thumbnail, a card image, a full view) pre-generating is the simplest and cheapest. For arbitrary on-the-fly sizes, Cloudflare Images or a Worker is the closer match to what Supabase gave you.
- When does Supabase Storage egress actually get expensive?
- When public downloads start eating the shared egress pool. The 250 GB included in Supabase Pro is not reserved for storage: your database, Auth, Realtime, and Edge Functions all draw from it. Once your media downloads push the project past that pool, every extra gigabyte costs $0.03 cached or $0.09 uncached. A practical threshold: if a handful of public assets generate hundreds of gigabytes a month, you are paying real money for traffic that R2 would serve for free. Private, low-traffic files almost never reach that point and are fine where they are.
Studio
Inizia un progetto.
Un partner unico per il prodotto digitale che devi costruire. Produzione più veloce, tecnologie moderne, costi ridotti. Un team, una fattura.