Show HN: A WordPress plugin that rewrites image URLs for near-zero-cost delivery
wordpress.orgHi HN,
I built a WordPress plugin called Bandwidth Saver. It takes the images your site already has and serves them through Cloudflare R2 and Workers, which means zero egress fees and extremely low storage cost. The goal is to make image delivery fast and cheap without adding any of the complexity of traditional optimization plugins.
The idea is simple. WordPress keeps generating images normally. The plugin rewrites the URLs on the frontend so images are served from a Cloudflare Worker. On the first request, the Worker fetches the original image and stores it in R2. After that, Cloudflare’s edge serves the image from its global cache with no egress charges. There’s no need to preload or sync anything, and if something fails, the original image loads. That’s the entire system.
I built this because most image CDN plugins try to do everything: compression, resizing, AI transforms, asset management, custom dashboards, and monthly fees. That’s useful for some users, but it’s unnecessary for most sites that just want their existing media to load faster without breaking the bank. Bandwidth Saver focuses only on delivery, not transformations. It’s intentionally minimal.
There are two ways to use it. The plugin is completely free if you want to run your own Cloudflare Worker. I included the Worker code and the steps needed to deploy it. If you don’t want to deal with any Cloudflare setup, there’s a managed option for $2.99 per month that uses my Worker and my R2 bucket. I’m trying to keep it accessible while also covering operational costs.
The plugin works with any theme or builder and doesn’t modify the database. It only rewrites URLs on output. WordPress remains the system of record for all media. R2 simply becomes a cheap, durable cache layer backed by Cloudflare’s edge.
I’m especially interested in feedback about the approach. Does the fetch-on-first-request model make sense? Is the pricing fair for a plugin of this scope? Should I prioritize allowing users to connect their own R2 buckets or the managed service? And for those with experience in edge compute or CDNs, I would love thoughts on how to improve the Worker or the rewrite strategy.
Thanks for reading, happy to answer any questions.
You might want to put a cap on the $2.99/m plan, otherwise one huge site could wipe you out. If you do, I'd express that in terms that most small Wordpress sites will understand (like unique viewers, page hits, etc).
I think some here will say "why not just use Cloudflare directly", but I disagree, I think this plugin makes sense. Cloudflare is relatively straightforward for technical users, but many Wordpress users are non-technical. $2.99 is a very small amount for reliable fast images, while also packing a pretty nice margin for you for most users who will need a tiny fraction of that.
Yes, this plugin is aimed at the long tail and I need to be clear on a fair use policy. The idea behind the self host worker is that I can provide white glove migration if any site becomes burdensome without disrupting the service altogether.
And I agree, if a site is behind Cloudflare DNS this plugin does not make much sense, but it's a solution for many non-technical users, as you mentioned.
Do the long tail websites really have a problem with cost for their delivery? I don't think so.
I'm sorry to say that with this plugin, you're just adding to the pervasive tracking enabled by widespread use of Cloudflare.
Do they? I honestly do not know yet. That is what I am trying to learn.
Yeah, raise your base price too imho. At least $5
Will do, had to make it interesting for launch :)
Thanks for all the comments so far. I wanted to share what I am taking from the discussion and also open the door if anyone wants to keep pushing on any of these points. There is a lot of useful input here.
About the $2.99 plan. Several people pointed out that the pricing feels too low or too open ended. That is fair. I priced it that way for launch, but I am going to adjust it with a clearer fair use limit and a slightly higher base price. If anyone has strong opinions on what feels reasonable for small sites while still being safe for me, I would love to hear it.
Who the plugin is actually for. A few replies assumed this is mainly for people who already use Cloudflare DNS. The real target is the group that cannot or do not want to move their nameservers, but still want Cloudflare-level delivery. If anyone here has seen this pattern with clients or non-technical users, I am curious how common that is in your experience.
Privacy wording. Some comments pointed out that my privacy section could be clearer about what Cloudflare logs. I agree. The plugin itself does not track anything, but Cloudflare obviously logs what any CDN logs. I will rewrite that part. If there is better wording that avoids confusion, I am open to suggestions.
Why use a Worker at all. This is not an offloader, although that's a good plug in on itself. I saw a few questions about why not rely entirely on Cloudflare’s built in caching. The Worker is mainly there to keep all Cloudflare setup outside of WordPress and avoid credential handling inside the plugin. If anyone sees a simpler pattern that avoids that overhead, I would like to hear it.
Content and responsibility. The point about hosting other peoples images under my own domain is valid. I am adding more safeguards and encouraging bigger sites to self host their Worker. If you have experience dealing with this at scale, any advice is welcome.
Overall this thread has been helpful. There are still a few open questions and I am happy to keep the conversation going if anyone wants to dig deeper into pricing, edge behavior, privacy, or Cloudflare alternatives.
This is awesome, I've used offload media for years, but they've been getting more and more annoying about their plugin trying to convert to using their cdns and upgrading to their premium plugin.
I've wanted to explore R2 (I use S3/Cloudfront today) and this looks like a great way to do so!
Lucas, let me know if I can help with anything.
inbox [at] cris [dot] mx
> Privacy
> Bandwidth Saver respects your privacy and your visitors’ privacy: Does not track visitors...Does not collect analytics
Wouldn't this cause a site's visitors to send traffic to cloudflare in situations where they wouldn't otherwise, allowing cloudflare to log their IP, timestamp, and the image requested, along with any other data in the request header? If this plugin wasn't used on the site cloudflare wouldn't get/log/track any of that. I'm not sure that handing all that data over to a third party (especially one as large and centralized as cloudflare) is compatible with respecting visitor's privacy. At the very least, site owners should be made aware of the fact that this is data will end up being shared.
This is true, I still try to be clear about that:
"External Services
This plugin connects to external services to deliver images:
Cloudflare R2 & Workers
Purpose: Stores and serves cached images from 300+ global locations Provider: Cloudflare, Inc. Terms: cloudflare.com/terms Privacy: cloudflare.com/privacypolicy"
My impression was that this would be used by sites already proxied by cloudflare, so this already happens.
But perhaps it is a separate thing that can be used regardless of your dns?
Right. The target user is not using Cloudflare nameservers.
I came here to say this. I find the following to be quite misleading:
Bandwidth Saver respects your privacy and your visitors’ privacy:
Because all that tracking and data collection will be done by Cloudflare (a company subject to the CLOUD act) instead.
Noted. I agree the current wording is not clear enough about what Cloudflare logs. I am going to rewrite that section so it is more explicit.
Cloudflare has their own image optimization and caching service, would be a good alternative: https://developers.cloudflare.com/images/transform-images/
I wrote a basic plugin for Jekyll to automatically prefix my images with this. Pretty much just set it and forget it: https://github.com/catskull/catskull.github.io/blob/master/_...
Am I missing something or is this way harder to do in Wordpress?
The idea here is that WordPress will still host and transform the images (could have many stacked plugins as a pipeline) but the plugin will rewrite the final image's URL to be served by Cloudflare. So you can benefit of whatever pipeline you have in the server, and let the plugin use cloudflare at the edge.
so i could. say.
have a squid proxy on a $5 unmetered vps, referring to WP as a content-origin and then just use this to rewrite the image URL without using cloudflare at all?
(also possible with an apache directive but , doing it in WP could be useful)
and could you not .. just do the same for your $2.99 customers so you dont get a surprise $2000 bill or find yourself told by cloudflare that its time to pay up?
although if youre allowing uploads youre not in control of youd really need something like sightengine (or to roll your own) sooner or later to make sure no CSAM uploads and then theyll just get you in fees that way.
otherwise one person who does that might get your account canned and take every single blog using this service out
thats why id be a proponent of steering them to sign up and use their own CF R2 bucket , or self hosted minio (s3), or other s3 provider… or the squid thing for technical users who dont like cloudflare and its ilk. then theyre responsible for what they upload and host.
most wordpress static site plugins will configure the s3 hosting.
i just am not familiar with any that would easily let me plug in my own base URL for images. they probably exist… and if not then good job for tackling it. at the moment im going about this a different way and it works? but i wouldnt know how to go about packaging and shipping this up in a way thats accessible for everyone.
maybe a crude squid.conf generator you put your real wp url and your new cdn url into. but then youll want https on it too
i do know a lot of people would love to have “cdn” features without taxing the i/o and bandwidth on wordpress but who ALSO dont want to get cloudflare into their hosting for one reason or another. (im not there yet but i get it.)
the hug of death on stock wordpress is real which is why im already doing this in practice. with extra steps. (specifically a cloudflare rewrite rule for /wp-uploads/* to the alternate base URL which could also be done in vhost directives)
imo WP needs a third option under site URL and admin URL , for the base image URL.
Thanks for the detailed reply. Let me try to clear up a few things, because I think we are talking about slightly different use cases.
The plugin is not trying to replace Cloudflare, Squid, Minio, or any other origin setup. It also is not an offloader. WordPress still stores the files and keeps whatever transformation pipeline you already use. The plugin only rewrites the final image URL so the request hits a Worker that fetches the file on demand and caches it in R2. That is the entire idea.
You could absolutely build something similar with Squid or Minio or a reverse proxy. There are many valid ways to do this if you are comfortable managing the infra yourself. The plugin exists for the large group of WordPress users who are not going to set up their own proxy, or Minio, or custom rewrite rules. They just want their existing images to load faster without touching their hosting stack.
On the managed plan, you are right that I need good safeguards. I agree that self hosted R2 or self hosted S3 makes the most sense for larger or more active sites. My plan is to encourage that path when usage grows so the shared bucket does not become a liability for anyone.
The idea of WordPress having a separate “base image URL” setting would actually solve a lot of problems. Until that exists, this plugin is basically trying to fill that gap for non technical users.
If you have suggestions on how to simplify the worker pattern further, or how you would package your Squid setup so it is accessible to others, I am definitely interested in hearing more.
[delayed]
That is what Cloudflare already does by caching images
Right. The target user is not using Cloudflare nameservers.
Great idea and definitely love the aspec of bringing your own worker.
But technically would it be better to have the plugin to any transformation and then have just cloudflare in front of the website raking care of all caching ? (I thought they even provide a WordPress plugin for that).
Also careful with hosting other people content under your domain/service under your name especially with CSAM stuff and other illegal material that your domain becomes the face of.
Hi, yes. Jetpack has a plugin for CDN but it's very limited I actually had the experience of having to turn off that plugin because the shared URL was reported as a malicious website, and without notice raked up a bill of over $9k for AWS bandwidth costs.
The idea here is to make it actually work at a level of service that Jetpack can't or won't. Yes, in the managed service I'll have to take that into account.
Nice work! I wish more WordPress plugins took a Unix like approach of just doing one thing well. Wat too common for good plugins to grow into a bloated mess over time.
Thanks! I hope to keep it simple for a long time, and ideally profitable.
doesn't cloudflare already offer this if you proxy?
Yes! It’s amazing. This is an option for non-technical users or anyone who can’t or won’t move their domain to Cloudflare’s DNS.
How many WordPress sites even need this? I have several running and none of them use anywhere close to enough bandwidth that I have to worry about it.
That’s the main question for me now: is there a subset of users who can’t or won’t switch their nameservers to Cloudflare, yet still need a lot of bandwidth?
It’s possible that group doesn’t exist.
Agreed. I think it should be called "storage saver" and focus on deleting the images from your server and storing in r2, though there's plenty of plugins already that do this "media offloading"
That could work as a separate plugin. This one is intentionally not an offloader. WordPress keeps storage and transformations, I only rewrite the final URL.
Why use a cf worker rather than use wp hooks to upload to r2 when an image is uploaded?
Where does the url rewrite happen - wp hook or in cf worker?
As another comment said, 2.99 unlimited is a TERRIBLE idea
The purpose of the worker is to offload all Cloudflare configuration to a single endpoint that fetches and caches each image on demand. This removes the need for any configuration at the WordPress level and keeps credentials out of WordPress entirely.
The URL rewrite happens in a WordPress hook. And yes, the $2.99 plan could technically cover around 200 GB in R2, but there is real liability attached to that.
What price would feel fair and still interesting to you?
I don't see the benefit of keeping things out of WordPress.
It also seems like you're recreating or even bypassing existing mechanisms
* why do the processing in wordpress first rather than just offload it completely to cloudflare's image optimization service? I don't think you even need the worker for that - it can be done automatically in various ways.
* are you deleting the files from the server after offloading? That's largely the point of such wp offload media plugins, some of which support r2.
My point about pricing was don't offer flat fee.
Thanks for the follow up. I think the main difference is that I am not trying to build another offloader or a full image optimization service. WordPress stays in control of storage and transformations. The plugin only rewrites the final URL so the request goes through a Worker and then Cloudflare’s edge cache. That is the entire scope.
I am not deleting anything from the server and I am not replacing the media library with R2. If someone needs real offloading, there are already plugins built for that and they make sense for bigger or more storage heavy sites.
Using Cloudflare’s native image service is also an option, but it requires Cloudflare setup inside WordPress and user credentials. The Worker avoids that and keeps the whole Cloudflare side in one place. For technical users your approach works fine. The plugin exists for people who want CDN level delivery without touching any of that.
And yes, I am moving away from the flat fee idea. I appreciate you pointing it out. If you have thoughts on what kind of limits feel reasonable for small to medium sites, I am open to it.
What's the advantage of this vs just setting the site up on a free cloudflare plan and use a caching rule?
Easier for non-technical wordpress users who would struggle setting it up themselves.
Cool so the value you provide is much of the benefit of CF but without messing with nameservers etc. (scary). If you don't understand all the techie bits you're going to read 'CDN plugin' and be filed in that basket so I'd work on how to differentiate and market yourself in that space.
Thanks, that is exactly the angle I am leaning into. The whole point is to give users most of the benefits of Cloudflare without having to move nameservers or deal with caching rules or the dashboard. For people who already use Cloudflare directly, this might not be needed. For everyone else, it removes a lot of the steps that usually cause support tickets or confusion.
I agree about the positioning. I am updating the wording so it is clear that this is not trying to compete with Cloudflare’s full feature set or with full image optimization plugins. It is more of a simple “use Cloudflare as your image CDN” switch for the long tail of WordPress sites that will never touch DNS settings.
If you have thoughts on how to phrase that more clearly, I am open to ideas.
We serve over 100 WordPress websites, some with relatively high traffic. I've never encountered a Cloudflare issue with image caching. I am a little confused about what this is all about.
We also have our own CDN-ish DigitalOcean droplets with Terabytes of data transfer available (stacked droplets increase the TB limit under the same account, too). This is a $10-$15 solution for 100+ WordPress sites.
Small droplets (DigitalOcean, Vultr, or managed like CloudWays) offer multi-TB bandwidth for data transfers. With the WebP format, even the highest-resolution image is under 100 KB. We try to keep everything under 50 KB for mobile optimization as well. I don't see sites using 50 GB per month and always below the limits. Why would anyone need an extra layer of complication?
Thanks for the detailed perspective. Your setup makes sense for agencies or teams that can manage their own caching, droplets, image formats, and traffic patterns. In that environment a plugin like this is not really needed.
The plugin is aimed at a different group. A lot of WordPress users are not on Cloudflare, do not want to touch DNS, and are not comfortable running their own CDN proxy or tuning image formats. They just want their existing media to load faster without changing their hosting stack.
If you are already keeping everything optimized and have a CDN pattern you like, then you are already covered. This is more for the long tail of smaller sites that will never set up their own caching rules or droplets. It is just a simpler path for them.
I loved the FAQ question "What happens if cloudflare is down?"... Well, the short answer is it takes down 75% of the internet with it; you mean like 3 days ago for the whole day? well, there is always going outside and going bowling with your friends for a few hours until it comes back online, then the internet resumes function at that time.
True true, maybe I should update it to “go outside and touch some grass.”
I wouldn't use this, because it seems odd to use a Cloudflare Worker for something inherently static, but I thought about what I might use, and bunny.net came to mind. Now I have a question, which is why on the Bunny.net pricing page doesn't it mention Cloudflare? https://bunny.net/pricing/ It mentions CDN77, BytePlus, CacheFly, CloudFront, and Fastly. Is what Cloudflare provides in a different market segment?
> It mentions CDN77, BytePlus, CacheFly, CloudFront, and Fastly. Is what Cloudflare provides in a different market segment?
Cloudflare's pricing is "free until you get a message from the sales team that it's time to pay up". That's impossible to compare to anything else, so yes effectively a different market segment.
Yup, been there. I was serving more than 45 TB of data a month on one site, and they tried to push me into a $4,000/mo product.
I’ll stick with my $20 subscription, thanks.
Yes, the worker handles the fetch and cache. In normal use the URLs would point straight to the R2 public endpoint. Cloudflare might end up cheaper than Bunny.net. Five terabytes on Cloudflare would be about $75, but you avoid egress fees entirely and gain access to more than 300 edge locations.
my feedback... a lot of my clients just use cloudflare and its basically free.
This is true. Honest question: how technical are your clients? I’m trying to get a sense of whether there’s a market where paying $2.99 a month is a better choice than moving the domain to Cloudflare.
You don't need to "move the domain to Cloudflare"
If someone can get Cloudflare caching working without changing nameservers, then yes, this plugin does not offer anything new for that case.
Yet another nail in the coffin of the self-hosted web. Why should we pipeline the last free content through a company, that already controls most of the web traffic?
Mine is a tiny nail. Please buy my plugin.
[flagged]
I'm listening.
https://github.com/Qbix/Platform
Having said that, I am a big fan of CDNs. Your origin server can generate pages and that’s a lot better than static sites.
If you want a decentralized Internet, don’t use the Web. Use something like Pears / Holepunch / Hypercore / Dat (same thing hehe)