Workers: event.waitUntil does not allow fetch to trigger

Hi everyone,

I have a workers app that listens to a fetch event (addEventListener syntax) and returns a 302 HTTP response.

Before returning the response I use event.waitUntil to wait for 2 things

  • a fetch request to “log” my performance (I’m trying to measure KV read performance)
  • a KV write to store the result and not block the response

The KV write is executed without problem, however the fetch request is never even sent. I’ve tried running it “in context” and everything works as expected (example below), however creating the fetch request and passing it to event.waitUntil does not trigger it. I’m guessing Workers Runtime “queues” fetch requests until it needs to trigger them.

Examples (simplified for readability):

Does not trigger fetch:

const perf_promise = fetch('performance.tracker', { method: 'POST' });
event.waitUntil(perf_promise);
event.waitUntil(KV_DB.)
return new Response(null, { status: 302 });

Triggers fetch request:

return fetch('performance.tracker', { method: 'POST' }).then(() => {
     return new Response(null, { status: 302 });
});

Where is the fetch in the waitUntil posting to? Is it another worker?

Hi @anon9246926 !
It is indeed, via custom domain.
I have another worker performing http request to various endpoints (2 of which are workers) and have no issues though

If you are calling one worker from another you should use service bindings

Hi @anon9246926! Thanks a lot for your answer!
I’ve seen service bindings in the documentation. But I haven’t seen any mention of there being limitations of fetch request from worker to worker. Although the phrasing of your first question leads me to believe there is. Could you provide more context on this or some documentation please?
The only piece of docs I could find that remotely addresses this is:

A Service binding allows you to send HTTP requests to another Worker without those requests going over the Internet.

Which leads me to believe that worker-to-worker fetch requests should work over the internet, just slower than service bindings (obviously).

Although Service Bindings are an amazing option, the fact that this http request is “worker-to-worker” is more of a coincidence than anything, it could have been a lambda function or a serverless instance somewhere, even a Raspberry Pi at home. However now that you mention it, I haven’t tried fetching something else than a worker. I’ll give it a try and let you know.

There is quite a limitation on fetching workers from workers indeed, they cannot be the same “zone” (zones being essentially domains, everything listed under Websites in your CF Dash is a zone), as in, if your worker runs on a custom domain or route (worker1.example.com), it cannot fetch worker2.example.com. Same for the default workers.dev domain, worker1.yourworkersdev.workers.dev can’t fetch worker2.yourworkersdev.workers.dev but you can call a worker from a worker on a different zone (worker.dev → custom, etc).

1 Like

Hi @Chaika , thanks a lot! Do you know why this limitation exists?
I’m quite surprised since I have a Scheduled Worker that seems to be performing fetch requests without problem. But this might be because they have no “DNS zone attached” (ie no domain)?

I guess I’ll have to go the Service Binding route then and let you know.
If you have any docs on why this limitation exists I’ll be marking that as the “Solution” for the thread, since I believe that would lead other people to understand the reason better. Would that be ok with you both?

Perhaps this post might answer some questions for you @jsmrcaga

2 Likes

Amazing find! Thanks a lot!

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.