diff --git a/utils/jsffi/prelude.mjs b/utils/jsffi/prelude.mjs
index b32a843ce27e6929836e04d122cd76ce8a21f69f..fb27f6129923da28303077844f82a21cbb2af805 100644
--- a/utils/jsffi/prelude.mjs
+++ b/utils/jsffi/prelude.mjs
@@ -51,6 +51,10 @@ export class JSValManager {
 
 // The actual setImmediate() to be used. This is a ESM module top
 // level binding and doesn't pollute the globalThis namespace.
+//
+// To benchmark different setImmediate() implementations in the
+// browser, use https://github.com/jphpsf/setImmediate-shim-demo as a
+// starting point.
 const setImmediate = await (async () => {
   // node, bun, or other scripts might have set this up in the browser
   if (globalThis.setImmediate) {
@@ -67,30 +71,35 @@ const setImmediate = await (async () => {
     return (cb, ...args) => scheduler.postTask(() => cb(...args));
   }
 
-  // A simple & fast setImmediate() implementation for browsers. It's
-  // not a drop-in replacement for node.js setImmediate() because:
-  // 1. There's no clearImmediate(), and setImmediate() doesn't return
-  //    anything
-  // 2. There's no guarantee that callbacks scheduled by setImmediate()
-  //    are executed in the same order (in fact it's the opposite lol),
-  //    but you are never supposed to rely on this assumption anyway
-  class SetImmediate {
-    #fs = [];
-    #mc = new MessageChannel();
+  // Cloudflare workers doesn't support MessageChannel
+  if (globalThis.MessageChannel) {
+    // A simple & fast setImmediate() implementation for browsers. It's
+    // not a drop-in replacement for node.js setImmediate() because:
+    // 1. There's no clearImmediate(), and setImmediate() doesn't return
+    //    anything
+    // 2. There's no guarantee that callbacks scheduled by setImmediate()
+    //    are executed in the same order (in fact it's the opposite lol),
+    //    but you are never supposed to rely on this assumption anyway
+    class SetImmediate {
+      #fs = [];
+      #mc = new MessageChannel();
 
-    constructor() {
-      this.#mc.port1.addEventListener("message", () => {
-        this.#fs.pop()();
-      });
-      this.#mc.port1.start();
-    }
+      constructor() {
+        this.#mc.port1.addEventListener("message", () => {
+          this.#fs.pop()();
+        });
+        this.#mc.port1.start();
+      }
 
-    setImmediate(cb, ...args) {
-      this.#fs.push(() => cb(...args));
-      this.#mc.port2.postMessage(undefined);
+      setImmediate(cb, ...args) {
+        this.#fs.push(() => cb(...args));
+        this.#mc.port2.postMessage(undefined);
+      }
     }
+
+    const sm = new SetImmediate();
+    return (cb, ...args) => sm.setImmediate(cb, ...args);
   }
 
-  const sm = new SetImmediate();
-  return (cb, ...args) => sm.setImmediate(cb, ...args);
+  return (cb, ...args) => setTimeout(cb, 0, ...args);
 })();