Why are image resizing 18x more expensive if used in a worker?

Sure, it’s a little bit more convenient, but it’s an arbitrary pricing hike and really prevents businesses from using the service. It would make more sense for them to spend an hour implementing the default CF images API to convert the images…

Not only that, but the only way to upload in image is via multi-part form data, which means that downloading an image in a worker and passing it to the form-data won’t even work, because the worker won’t accept at stream for that input type.

How are you measuring that 18x price rate?

CF images are 1$ per 100K images served and conversions themselves are free. Using it in a worker is 9$ per 50K images served. 9x2 = 18$. 18$ / 1$ = 18x and also requires a Pro account (20$/mo) to work

Oh, I knew about the new images service but I never tried it personally. We’ve always just done the image encoding/resizing ourselves in Workers. 1 image = 1 worker request; with some larger images it maybe 1 image = 3 worker requests.

If just implementing your own code (under 50ms) then you can do 10 million images for $5, not counting the cost of KV.

The problem is images larger than 2MB, the worker will run out of CPU-time.

Nah, we regularly handle images from peoples smart phones which as JPG are about 4-6MB.

Like I said, you can split the workload across multiple workers so 1 big image might be 3 requests but most of the time 1 worker request is enough CPU time. Remember that when Cloudflare say “CPU Time” they mean it; GCP and AWS misrepresent “CPU Time” as “Wall Time”. 50ms CPU Time is a lot.

Converting between an ArrayBuffer and multi-part form-data would waste a lot of CPU Time.

4-6 might be possible if it’s only infrequent (Workers allow startup leeway of up to 200ms), we have sustained load so it won’t work and we have images up to 50MB.

That’s why it doesn’t work, if it could be streamed as standard file upload it would work perfectly.

How do you split file conversion workload across workers? Didn’t expect that to be possible for binary conversion. Doesn’t it need the “full picture”? (pun intended)

I’m aware of that but I was speaking in terms of sustained load averages. We put all the image encoding/resizing logic into a seperate Worker Route because Javascript is used for the main application. It might be possible to do it in Javascript too but probably harder and slower.

50MB images however! That’ll be a pain to deal with in Workers

Multi-thread encoding is fairly trivial these days; you can have a look at the existing libraries out there for ideas in your preferred language

Sounds like you already solved that, something you’re able to share?

EDIT: Ah, it’s not for workers, yeah there are many native solutions.

No. And you don’t even need to have each chunk the same size. There are algorithms to help you chop-down an image into chunks based on their complexity to that roughly each chunk will use approximately the same CPU-Time and therefore all chunks will be delivered back to the main thread at the same time. If one chunk takes longer then the main thread will be idle waiting for that one to finish, thats inefficient.

Sounds way too time-consuming, we’d need a wasm to convert the chunks and it would need image context, since png and jpeg are not the same.

It’s not wholly mine to distribute freely. I worked on it so I can give you pointers into the right direction to building your own solution. All the information is out there you just need to put it together into a Worker runtime environment. Look at ffmepg, mozJPEG, and oxiPNG.

It’ll take a dev about a month if they know what they’re doing. Question would be if it worth their time vs the cost of just using an existing service. We only built one because AWS didn’t work well in China, the existing image services were awful, Cloudflare Images service didn’t exist yet and Workers was only just coming out to Beta.

1 Like

Is this the reality of your final billing amount too, or is this figures you quoted only from the price-list? What I’m trying to say is that maybe the documentation/price-list is out-of-date which is often the case with Cloudflare. It seems strange to have two different prices depending how you’re uploading the images into their service.

Can you link some documentation about this? It seems so strange to use multi-part formdata uploading images into their service. Like it’s not even a general purpose system, its specifically designed for images so it’s really strange they’d do it this way!

Have you tried uploading as “Content-Type: image/png” for example?

It’s due to the CF images being new and the Workers are using the other (old) solution, so yeah that is the pricing that applies.

Any other upload type with just fail with {"result":null,"success":false,"errors":[{"code":"101","message":"content-type is not supported"}],"messages":[]}

According to the ticket I just got a reply on, that’s just how it is.