Building a Video Hosting System on Backblaze B2 + Cloudflare CDN (Cheaper Than AWS)
6 min read
Hosting video content on AWS S3 and CloudFront can result in massive egress bill shock. Learn how to build a production-ready video hosting system using Backblaze B2 and Cloudflare CDN with $0 egress fees.
If you have ever built an e-learning platform, a SaaS product, or a video-heavy website, you know that video files consume massive amounts of storage and bandwidth. When you host these videos on traditional cloud services like Amazon Web Services (AWS), the pricing structure can feel like a trap.
AWS S3 storage is reasonably priced, but the moment you distribute those videos to users via the internet, you get hit with AWS's data transfer (egress) fees. These fees can reach up to $0.08 to $0.09 per GB. If you have 1,000 students streaming a 1 GB video, you are looking at $80 just in egress bandwidth fees. Scale that to tens of thousands of views, and your AWS bill will skyrocket.
Fortunately, there is a production-grade alternative that offers high performance, global delivery, and near-zero egress fees. By combining Backblaze B2 (object storage) and Cloudflare CDN, you can leverage the Bandwidth Alliance to serve videos with $0 egress bandwidth fees.
What is the Bandwidth Alliance?
The Bandwidth Alliance is an agreement between major cloud hosting and infrastructure providers to discount or completely waive data transfer fees between their networks. Because Backblaze and Cloudflare are key members of this alliance, data transferred from a Backblaze B2 storage bucket to a Cloudflare CDN edge node is completely free of charge.
This means your pricing model changes dramatically:
- Storage: Backblaze B2 costs $0.006 per GB/month (about 1/4th the cost of AWS S3).
- Egress (Data Transfer): $0.00 per GB for all traffic routed through Cloudflare.
- Delivery: Cloudflare caches and delivers your video files globally, minimizing latency and buffering.
Step 1: Set Up Your Backblaze B2 Bucket
First, create a Backblaze account and set up a bucket to store your video assets:
- Go to the Backblaze admin panel and click 'Create a Bucket'.
- Set your Bucket Name (must be globally unique, e.g., 'company-videos-cdn').
- Set files to 'Public' so Cloudflare can read them.
- Enable CORS (Cross-Origin Resource Sharing) under 'Bucket Settings' so video players on your domain can fetch files from the CDN. Set CORS to allow GET and HEAD requests from your website's origin.
Once created, note down your bucket's Friendly URL. It will look something like this: `f000.backblazeb2.com/file/company-videos-cdn/`.
Step 2: Point Your Subdomain to Backblaze in Cloudflare
To serve your videos under a clean, custom branded URL (e.g., `videos.yourcompany.com`) rather than a default Backblaze URL, we configure Cloudflare's DNS:
- Log in to your Cloudflare dashboard and go to your domain's DNS settings.
- Add a new CNAME record.
- Set the Name to your desired subdomain (e.g., `videos`).
- Set the Target to the endpoint of your Backblaze bucket (e.g., `f000.backblazeb2.com`).
- Make sure the Proxy Status is set to 'Proxied' (orange cloud icon). This routes all incoming traffic through Cloudflare, enabling caching and invoking the Bandwidth Alliance.
Step 3: Mask the Backblaze Path with Rewrite Rules
By default, accessing a file requires appending the bucket path: `videos.yourcompany.com/file/company-videos-cdn/sample.mp4`. To clean this up and make URLs look like `videos.yourcompany.com/sample.mp4`, we add a Cloudflare URL Rewrite Rule:
- In Cloudflare, go to Rules > Transform Rules.
- Click 'Create Transform Rule' and select 'Rewrite URL'.
- Set the matching condition to apply to all incoming requests on your subdomain: `(http.host eq "videos.yourcompany.com")`.
- Set the Path Rewrite to: Rewrite to > Dynamic > `concat("/file/company-videos-cdn", http.request.uri.path)`.
- Save the rule.
Now, any request sent to `videos.yourcompany.com/sample.mp4` will be dynamically mapped to the correct Backblaze B2 path behind the scenes.
Step 4: Optimize Cache Settings for Video Streaming
By default, CDN networks might not cache large video files efficiently. We need to tell Cloudflare to cache files aggressively:
- Go to Rules > Page Rules (or Cache Rules).
- Create a rule matching: `videos.yourcompany.com/*`.
- Under settings, select 'Cache Level' and set it to 'Cache Everything'.
- Set 'Edge Cache TTL' to a long duration, such as '1 Month', because static video files rarely change.
- Under Backblaze B2, ensure that you configure HTTP response headers (specifically `Cache-Control`) to permit public caching. Set it to `public, max-age=2592000`.
Step 5: Deliver and Stream Content
For progressive MP4 playback, you can now embed video tags pointing directly to your subdomain: `<video src="https://videos.yourcompany.com/lecture1.mp4" controls></video>`. For larger platforms, segmenting videos using HLS (HTTP Live Streaming) and storing the `.m3u8` playlists and `.ts` fragments in Backblaze B2 is highly recommended. It allows users to start playing videos instantly, dynamic quality switching (e.g., 1080p to 480p), and fast seeking.
With this architecture, you get the storage reliability of Backblaze B2, the lightning-fast edge delivery of Cloudflare, and a complete waiver of the data transfer fees that make AWS so prohibitive.
Frequently Asked Questions
Why is egress bandwidth free between Backblaze B2 and Cloudflare?
Both Backblaze and Cloudflare are founding members of the Bandwidth Alliance. Because of this partnership, Backblaze does not charge any egress (data transfer) fees for traffic routed from B2 to Cloudflare's network, making the delivery of assets completely free of egress fees.
Do I need a paid Cloudflare plan to set this up?
No, the free tier of Cloudflare is completely sufficient. You will only pay Backblaze for storage ($0.006 per GB/month) and any direct egress outside Cloudflare (which is negligible if your setup is configured correctly).
How do you handle video seeking (Range Requests) in Cloudflare?
Cloudflare supports HTTP Range Requests out of the box. However, you must ensure that your caching rules do not break range requests. By default, Cloudflare caches the entire file or large chunks. For video streaming, it is recommended to use HTTP/2 or HTTP/3 and ensure standard caching configurations are in place.
Is this setup suitable for private or paid videos?
Yes, but you will need to add an authorization layer such as Cloudflare Workers to check and validate Signed URLs or access tokens before serving files from the cache. We cover Signed URL architecture in a separate guide.