Workers cache overhead?

Hi, I am trying to figure out the best way to optimize response times for cached resources served from a worker. With worker + cache API, I am getting response times of about 200ms pretty consistently for an image. The same image, when served from cloudfront, is about 50-70ms. Both responses appear to be coming from IAD. Is the extra 150ms a result of worker overhead? Is there any way to improve this? (My application is an interactive medical imaging viewer, so load times are really important)
22 Replies
Chaika
Chaika2w ago
Sounds more like routing or missing cache. Workers are a few ms extra at best, they run on the same machine processing your request. Cache is ~5-15ms. If you're directly returning the result of cache match, it should have a cf-cache-status: hit response header as part of it
Jason Hostetter
Jason HostetterOP2w ago
Yes, the requests do have cf-cache-status: HIT - that's why i'm confused
Chaika
Chaika2w ago
What do you see in the cf-ray? IAD, and you're on the east coast near Ashburn?
Jason Hostetter
Jason HostetterOP2w ago
Cf-Ray is 96fb56bb29b03b8c-IAD, I'm in harrisonburg VA so yes about 2 hrs from DC by car The cloudfront responses are also being served from IAD
Chaika
Chaika2w ago
If it helps to have something to compare to, simple cache test: https://new-quick-cache-test.workers.chaika.me/, send a request or two and look for cf-cache-status: HIT to see pure cache latency, without cache, raw worker response w/o cache (should be faster): https://new-quick-cache-test.workers.chaika.me/?no-cache I'm guessing you can't share a repro url. If that's any better then your worker, I'd ask what your worker is doing/fetching from on cache misses. If you're doing logic before cache checks or have a really big bundle/lots of deps, worth checking cpu time & wall time on your metrics overview page of the worker
Jason Hostetter
Jason HostetterOP2w ago
I just checked a log for a request, total request time was 220ms, worker wall time 27, cpu time 4 seems like the worker is fast, not sure where the rest of the time is getting spent Your cache test page gives more like 50-100ms for both I am decrypting a jwt prior to the cache lookup, but given the reported wall time i don't think that's the issue You can try this url to try and reproduce:
https://litevna.app/dicomweb/studies/1613192914.63499384658207770811354947619272270175.11604791/series/1613192914.160303950947001819581703587693649150803/instances/1613192914.121911326266325401667365883536841953391/frames/1?token=eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0.._74ee-7xscDtM_hv.uQwxkVdqASJAwaDxuLTAw10uZ_t1-UDthr9jCE8rhPfBq89SZVcQr71GgrdmgghugUr-k7One86MWsI9w1aM4DYD0pVo-Ig8dZUN4QQMAZVh_s80RUt-4LHW2xP_w48--S9sRunqBcQguaXco8CgrFacp4drcYTgb51ZyAA090vDP4Q6TECdoDeRFqk35nyk6x3yDBcOjHKZ4hZz20skhSpxdTmjkYsRD3CNY7_JtA1W6Rxf2Fzme7IoIGUqMi-NR3pQobBJEusewm74Q5S_mxFmpOPdmxJiI1aGu3FQe9Vyj7egm-MvpkNvSX0y81odPS5o4Vgp79Q-lU2KTvponLO_nk5CjDVjaUoEbBRCdgNYVCk2J7sb-l41DR1AmpAd6Zp4r_PTuVVCqNMTGjWLu9k9biFTh4--IaBhEYU4p2gPJ9-cHMYc5f4PGs4cZxdckMQs6plxYmL5Xy85lzWC8cIF6f_AGh2Zm820if6w9pTP1poZSRGiHQwFzdDjV1tSw_Zc6IC72XpDZ2aDA1CS9ummS9ELM-YZSBuPGyIWJiuPzAs_64Z3BhPt5ATrBR02diSikDpc4TEoQ5dmOqlL3ci9vYFZLe75B7aeEDJLMhLpisrWsTrvtQ9r_JLVbAKR99tZ8Y7lpR0VM4YsipKHT2TxivP5j5KUr8x8SheJPk46rHE2ePiL53t2ptgiFs7N4bZQ-Zj1h47WDH-95dgoww.3x-cgxoBtc7lTGeSqpKQMQ
https://litevna.app/dicomweb/studies/1613192914.63499384658207770811354947619272270175.11604791/series/1613192914.160303950947001819581703587693649150803/instances/1613192914.121911326266325401667365883536841953391/frames/1?token=eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0.._74ee-7xscDtM_hv.uQwxkVdqASJAwaDxuLTAw10uZ_t1-UDthr9jCE8rhPfBq89SZVcQr71GgrdmgghugUr-k7One86MWsI9w1aM4DYD0pVo-Ig8dZUN4QQMAZVh_s80RUt-4LHW2xP_w48--S9sRunqBcQguaXco8CgrFacp4drcYTgb51ZyAA090vDP4Q6TECdoDeRFqk35nyk6x3yDBcOjHKZ4hZz20skhSpxdTmjkYsRD3CNY7_JtA1W6Rxf2Fzme7IoIGUqMi-NR3pQobBJEusewm74Q5S_mxFmpOPdmxJiI1aGu3FQe9Vyj7egm-MvpkNvSX0y81odPS5o4Vgp79Q-lU2KTvponLO_nk5CjDVjaUoEbBRCdgNYVCk2J7sb-l41DR1AmpAd6Zp4r_PTuVVCqNMTGjWLu9k9biFTh4--IaBhEYU4p2gPJ9-cHMYc5f4PGs4cZxdckMQs6plxYmL5Xy85lzWC8cIF6f_AGh2Zm820if6w9pTP1poZSRGiHQwFzdDjV1tSw_Zc6IC72XpDZ2aDA1CS9ummS9ELM-YZSBuPGyIWJiuPzAs_64Z3BhPt5ATrBR02diSikDpc4TEoQ5dmOqlL3ci9vYFZLe75B7aeEDJLMhLpisrWsTrvtQ9r_JLVbAKR99tZ8Y7lpR0VM4YsipKHT2TxivP5j5KUr8x8SheJPk46rHE2ePiL53t2ptgiFs7N4bZQ-Zj1h47WDH-95dgoww.3x-cgxoBtc7lTGeSqpKQMQ
I mean it's not like super slow, I'm getting 150-250ms for cache hits, but i feel like it should be faster
Chaika
Chaika2w ago
Cache hits should be basically your latency + 20-30ms. My latency to Cloudflare is ~25ms or so, I get some hits on the cache test link between ~47ms-60ms or so That link doesn'twork, just says invalid. Worth noting though that if you're serving big enough of a response your internet speed is going to start playing a role as well
Jason Hostetter
Jason HostetterOP2w ago
Whoops, wrong link format:
https://litevna.app/key_eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0.._74ee-7xscDtM_hv.uQwxkVdqASJAwaDxuLTAw10uZ_t1-UDthr9jCE8rhPfBq89SZVcQr71GgrdmgghugUr-k7One86MWsI9w1aM4DYD0pVo-Ig8dZUN4QQMAZVh_s80RUt-4LHW2xP_w48--S9sRunqBcQguaXco8CgrFacp4drcYTgb51ZyAA090vDP4Q6TECdoDeRFqk35nyk6x3yDBcOjHKZ4hZz20skhSpxdTmjkYsRD3CNY7_JtA1W6Rxf2Fzme7IoIGUqMi-NR3pQobBJEusewm74Q5S_mxFmpOPdmxJiI1aGu3FQe9Vyj7egm-MvpkNvSX0y81odPS5o4Vgp79Q-lU2KTvponLO_nk5CjDVjaUoEbBRCdgNYVCk2J7sb-l41DR1AmpAd6Zp4r_PTuVVCqNMTGjWLu9k9biFTh4--IaBhEYU4p2gPJ9-cHMYc5f4PGs4cZxdckMQs6plxYmL5Xy85lzWC8cIF6f_AGh2Zm820if6w9pTP1poZSRGiHQwFzdDjV1tSw_Zc6IC72XpDZ2aDA1CS9ummS9ELM-YZSBuPGyIWJiuPzAs_64Z3BhPt5ATrBR02diSikDpc4TEoQ5dmOqlL3ci9vYFZLe75B7aeEDJLMhLpisrWsTrvtQ9r_JLVbAKR99tZ8Y7lpR0VM4YsipKHT2TxivP5j5KUr8x8SheJPk46rHE2ePiL53t2ptgiFs7N4bZQ-Zj1h47WDH-95dgoww.3x-cgxoBtc7lTGeSqpKQMQ/dicomweb/studies/1613192914.63499384658207770811354947619272270175.11604791/series/1613192914.160303950947001819581703587693649150803/instances/1613192914.121911326266325401667365883536841953391/frames/1
https://litevna.app/key_eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0.._74ee-7xscDtM_hv.uQwxkVdqASJAwaDxuLTAw10uZ_t1-UDthr9jCE8rhPfBq89SZVcQr71GgrdmgghugUr-k7One86MWsI9w1aM4DYD0pVo-Ig8dZUN4QQMAZVh_s80RUt-4LHW2xP_w48--S9sRunqBcQguaXco8CgrFacp4drcYTgb51ZyAA090vDP4Q6TECdoDeRFqk35nyk6x3yDBcOjHKZ4hZz20skhSpxdTmjkYsRD3CNY7_JtA1W6Rxf2Fzme7IoIGUqMi-NR3pQobBJEusewm74Q5S_mxFmpOPdmxJiI1aGu3FQe9Vyj7egm-MvpkNvSX0y81odPS5o4Vgp79Q-lU2KTvponLO_nk5CjDVjaUoEbBRCdgNYVCk2J7sb-l41DR1AmpAd6Zp4r_PTuVVCqNMTGjWLu9k9biFTh4--IaBhEYU4p2gPJ9-cHMYc5f4PGs4cZxdckMQs6plxYmL5Xy85lzWC8cIF6f_AGh2Zm820if6w9pTP1poZSRGiHQwFzdDjV1tSw_Zc6IC72XpDZ2aDA1CS9ummS9ELM-YZSBuPGyIWJiuPzAs_64Z3BhPt5ATrBR02diSikDpc4TEoQ5dmOqlL3ci9vYFZLe75B7aeEDJLMhLpisrWsTrvtQ9r_JLVbAKR99tZ8Y7lpR0VM4YsipKHT2TxivP5j5KUr8x8SheJPk46rHE2ePiL53t2ptgiFs7N4bZQ-Zj1h47WDH-95dgoww.3x-cgxoBtc7lTGeSqpKQMQ/dicomweb/studies/1613192914.63499384658207770811354947619272270175.11604791/series/1613192914.160303950947001819581703587693649150803/instances/1613192914.121911326266325401667365883536841953391/frames/1
Actually, try this one, this just returns 3KB of json:
https://litevna.app/key_eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0.._74ee-7xscDtM_hv.uQwxkVdqASJAwaDxuLTAw10uZ_t1-UDthr9jCE8rhPfBq89SZVcQr71GgrdmgghugUr-k7One86MWsI9w1aM4DYD0pVo-Ig8dZUN4QQMAZVh_s80RUt-4LHW2xP_w48--S9sRunqBcQguaXco8CgrFacp4drcYTgb51ZyAA090vDP4Q6TECdoDeRFqk35nyk6x3yDBcOjHKZ4hZz20skhSpxdTmjkYsRD3CNY7_JtA1W6Rxf2Fzme7IoIGUqMi-NR3pQobBJEusewm74Q5S_mxFmpOPdmxJiI1aGu3FQe9Vyj7egm-MvpkNvSX0y81odPS5o4Vgp79Q-lU2KTvponLO_nk5CjDVjaUoEbBRCdgNYVCk2J7sb-l41DR1AmpAd6Zp4r_PTuVVCqNMTGjWLu9k9biFTh4--IaBhEYU4p2gPJ9-cHMYc5f4PGs4cZxdckMQs6plxYmL5Xy85lzWC8cIF6f_AGh2Zm820if6w9pTP1poZSRGiHQwFzdDjV1tSw_Zc6IC72XpDZ2aDA1CS9ummS9ELM-YZSBuPGyIWJiuPzAs_64Z3BhPt5ATrBR02diSikDpc4TEoQ5dmOqlL3ci9vYFZLe75B7aeEDJLMhLpisrWsTrvtQ9r_JLVbAKR99tZ8Y7lpR0VM4YsipKHT2TxivP5j5KUr8x8SheJPk46rHE2ePiL53t2ptgiFs7N4bZQ-Zj1h47WDH-95dgoww.3x-cgxoBtc7lTGeSqpKQMQ/dicomweb/studies
https://litevna.app/key_eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0.._74ee-7xscDtM_hv.uQwxkVdqASJAwaDxuLTAw10uZ_t1-UDthr9jCE8rhPfBq89SZVcQr71GgrdmgghugUr-k7One86MWsI9w1aM4DYD0pVo-Ig8dZUN4QQMAZVh_s80RUt-4LHW2xP_w48--S9sRunqBcQguaXco8CgrFacp4drcYTgb51ZyAA090vDP4Q6TECdoDeRFqk35nyk6x3yDBcOjHKZ4hZz20skhSpxdTmjkYsRD3CNY7_JtA1W6Rxf2Fzme7IoIGUqMi-NR3pQobBJEusewm74Q5S_mxFmpOPdmxJiI1aGu3FQe9Vyj7egm-MvpkNvSX0y81odPS5o4Vgp79Q-lU2KTvponLO_nk5CjDVjaUoEbBRCdgNYVCk2J7sb-l41DR1AmpAd6Zp4r_PTuVVCqNMTGjWLu9k9biFTh4--IaBhEYU4p2gPJ9-cHMYc5f4PGs4cZxdckMQs6plxYmL5Xy85lzWC8cIF6f_AGh2Zm820if6w9pTP1poZSRGiHQwFzdDjV1tSw_Zc6IC72XpDZ2aDA1CS9ummS9ELM-YZSBuPGyIWJiuPzAs_64Z3BhPt5ATrBR02diSikDpc4TEoQ5dmOqlL3ci9vYFZLe75B7aeEDJLMhLpisrWsTrvtQ9r_JLVbAKR99tZ8Y7lpR0VM4YsipKHT2TxivP5j5KUr8x8SheJPk46rHE2ePiL53t2ptgiFs7N4bZQ-Zj1h47WDH-95dgoww.3x-cgxoBtc7lTGeSqpKQMQ/dicomweb/studies
I just noticed that even with the same payload, compared to cloudfront it was a pretty sizeable difference.
Chaika
Chaika2w ago
~40-50ms for me when cache hit, ~80ms or so on first without cf-cache-status header If you just ping litevna.app, what's your avg latency?
No description
Jason Hostetter
Jason HostetterOP2w ago
Super fast: round-trip min/avg/max/stddev = 10.738/14.979/20.725/2.494 ms wth
Chaika
Chaika2w ago
What are your response headers on a slower (150ms+) response? Do you have anything like cf-placement?
Jason Hostetter
Jason HostetterOP2w ago
No:
Access-Control-Allow-Headers
*, *
Access-Control-Allow-Methods
GET, POST, PUT, DELETE, OPTIONS, GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin
*, *
Access-Control-Expose-Headers
Content-Range, Content-Length, Content-Encoding, X-Decode-Level, Content-Range, Content-Length, Content-Encoding, X-Decode-Level
Age
11
Alt-Svc
h3=":443"; ma=86400
Cache-Control
max-age=14400
Cf-Cache-Status
HIT
Cf-Ray
96fba3febbd22f24-IAD
Connection
close
Content-Length
2525
Content-Type
application/json
Date
Fri, 15 Aug 2025 21:03:47 GMT
Expires
Fri, 15 Aug 2025 21:04:05 GMT
Last-Modified
Fri, 15 Aug 2025 21:03:35 GMT
Nel
{"success_fraction":0,"report_to":"cf-nel","max_age":604800}
Report-To
{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=e6fq8V8p4iR1KeRNSKhzkmtTRfLEnG36YcnhSzxM8u%2BVPJhVXS8nnEVSirVSuujkwUNRyYvzr0O5kr7XXIpMjvsoFOwfSHcGNBDeidcQLTTnb%2BR784BnLy3AUEwm5w%3D%3D"}],"group":"cf-nel","max_age":604800}
Server
cloudflare
Server-Timing
cfL4;desc="?proto=TCP&rtt=11244&min_rtt=10781&rtt_var=4970&sent=3&recv=5&lost=0&retrans=0&sent_bytes=203&recv_bytes=1547&delivery_rate=99917&cwnd=250&unsent_bytes=0&cid=ebf23b71b84ab597&ts=142&x=0"
Timing-Allow-Origin
Access-Control-Allow-Headers
*, *
Access-Control-Allow-Methods
GET, POST, PUT, DELETE, OPTIONS, GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin
*, *
Access-Control-Expose-Headers
Content-Range, Content-Length, Content-Encoding, X-Decode-Level, Content-Range, Content-Length, Content-Encoding, X-Decode-Level
Age
11
Alt-Svc
h3=":443"; ma=86400
Cache-Control
max-age=14400
Cf-Cache-Status
HIT
Cf-Ray
96fba3febbd22f24-IAD
Connection
close
Content-Length
2525
Content-Type
application/json
Date
Fri, 15 Aug 2025 21:03:47 GMT
Expires
Fri, 15 Aug 2025 21:04:05 GMT
Last-Modified
Fri, 15 Aug 2025 21:03:35 GMT
Nel
{"success_fraction":0,"report_to":"cf-nel","max_age":604800}
Report-To
{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=e6fq8V8p4iR1KeRNSKhzkmtTRfLEnG36YcnhSzxM8u%2BVPJhVXS8nnEVSirVSuujkwUNRyYvzr0O5kr7XXIpMjvsoFOwfSHcGNBDeidcQLTTnb%2BR784BnLy3AUEwm5w%3D%3D"}],"group":"cf-nel","max_age":604800}
Server
cloudflare
Server-Timing
cfL4;desc="?proto=TCP&rtt=11244&min_rtt=10781&rtt_var=4970&sent=3&recv=5&lost=0&retrans=0&sent_bytes=203&recv_bytes=1547&delivery_rate=99917&cwnd=250&unsent_bytes=0&cid=ebf23b71b84ab597&ts=142&x=0"
Timing-Allow-Origin
sorry that formatting is horrendous I'm getting some responses in the 50ms range, but most 150.
Chaika
Chaika2w ago
The connection close bit you have on there is curious, what are you testing from?
Jason Hostetter
Jason HostetterOP2w ago
That particular one i think was from HTTPie macos client but most testing in chrome/arc I see the same header in chrome as well
Chaika
Chaika2w ago
ah ok, yea browsers or curl are usually best to test in, rest clients/etc aren't quite meant to be performance benchmarks, that one looked like it was closing the connection each time It looks like your cache ttl is really low, like 30s or so, if possible I would bump it up a fair bit more so there's more chance for hits and less surprise cold hits
Jason Hostetter
Jason HostetterOP2w ago
I guess if you’re getting 50 ms that’s good news, as long as my users get fast loads
Chaika
Chaika2w ago
With a warmed up connection and hitting cache, it's possible to get low enough latency on that url even from IAD IAD (CF IAD) 38.29ms 200 Cf-Cache-Status -> HIT IAD (CF IAD) 41.55ms 200 Cf-Cache-Status -> HIT
Jason Hostetter
Jason HostetterOP2w ago
That particular path is a query path where data is more likely to change. That larger payload link (the first one) is longer with unchanging data What are you getting on that first link (the one that returns binary data)? Still fast?
Chaika
Chaika2w ago
From my device on a residental connection ~45ms From a server in IAD ~1ms away from Cloudflare IAD (CF IAD) 24.02ms 200 Cf-Cache-Status -> HIT IAD (CF IAD) 22.1ms 200 Cf-Cache-Status -> HIT Not bad
Jason Hostetter
Jason HostetterOP2w ago
Dang not bad at all. Must be something weird with my setup/connection Maybe my ISP? Idk. Thanks for your help!
Walshy
Walshy2w ago
Whenever perf testing always do what a browser would, so many people spin up new connections for every request, use http1.1, etc. There's a lot that browsers/servers do these days to ensure things are super fast
Jason Hostetter
Jason HostetterOP5d ago
That makes sense. I also directly bound two workers in the request chain instead of using fetch, and reworked the request pattern to avoid a server hit (which was used to get around a cors preflight) and now I’m seeing lower latency as well. Very much appreciate the help!

Did you find this page helpful?