Skip to content

onAfterResponse does not work on Cloudflare Workers Runtime #1383

@nzws

Description

@nzws

What version of Elysia is running?

1.3.21

What platform is your computer?

Darwin 24.6.0 arm64 arm

What environment are you using

Cloudflare Workers (2025-09-05)

Are you using dynamic mode?

Yes

What steps can reproduce the bug?

Run this code with the npx wrangler dev ./index.ts --compatibility-date=2025-09-05 --compatibility-flags=nodejs_compat --port=3000 command:

import { Elysia } from "elysia";

export const app = new Elysia({ aot: false })
  .onRequest((ctx) => {
    console.log("onRequest", ctx.request.url);
  })
  .onBeforeHandle((ctx) => {
    console.log("onBeforeHandle", ctx.request.url);
  })
  .onAfterHandle((ctx) => {
    console.log("onAfterHandle", ctx.request.url);
  })
  .onAfterResponse((ctx) => {
    console.log("onAfterResponse", ctx.request.url);
  })
  .get("/", (ctx) => {
    console.log("Handling", ctx.request.url);
    return "Hello, world!";
  });

export default app;

What is the expected behavior?

The function registered in onAfterResponse should be executed.

onRequest http://localhost:3000/
onBeforeHandle http://localhost:3000/
Handling http://localhost:3000/
onAfterHandle http://localhost:3000/
onAfterResponse http://localhost:3000/
[wrangler:info] GET / 200 OK (6ms)

What do you see instead?

The function registered in onAfterResponse is not executed.

onRequest http://localhost:3000/
onBeforeHandle http://localhost:3000/
Handling http://localhost:3000/
onAfterHandle http://localhost:3000/
[wrangler:info] GET / 200 OK (3ms)

Additional information

This bug does not occur in v1.3.8, but it does occur starting from v1.3.9. Using git bisect, I found that this commit introduced the bug: d81da3d

This commit seems to delay the execution of onAfterResponse using setImmediate. However, based on my investigation of the Workers Runtime, it appears that functions scheduled with setImmediate are not executed once the fetch function has finished.

To work around this, I think it is necessary to wait until the setImmediate function completes by using ctx.waitUntil. However, I’m not sure how this can be achieved with elysiajs.

export default {
  async fetch(request, env, ctx) {
    const { promise, resolve } = Promise.withResolvers();

    ctx.waitUntil(promise);
    
    setImmediate(() => {
      console.log('It works');
      resolve();
    });

    setImmediate(() => {
      console.log('Not working');
    });
    
    return new Response('Hello World!');
  },
};

Have you try removing the node_modules and bun.lockb and try again yet?

Yes

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions