title: Performance implications of using Async Hooks
body: <p>I'm the author of a Node.js library and I want to use <a href="https://nodejs.org/api/async_hooks.html" rel="nofollow noreferrer">Async Hooks</a> to improve DX. But I'm worried about performance.</p>
  <p>I've read stories saying that everything is fine, as well as stories where performance was a blocker.</p>
  <p>In theory, asynchronicity should only happen for IO operations and performance penality should be pretty much ~0. (As IO operations are several orders of magnitude more expensive than running JS code.)</p>
  <p>But, in practice, does running extra JS on each async call induces a non-negligible performance degradation?</p>
  <p>What is your experience with the performance of async hooks?</p>
  <h2>Use Case</h2>
  <p>The concrete use case is <a href="https://github.com/reframejs/wildcard-api" rel="nofollow noreferrer">Wildcard API</a> where I'm using Async Hooks which enables wonderful ergonomics for Wildcard users:</p>
  <pre class="lang-js prettyprint-override"><code>const { server } = require(&quot;@wildcard-api/server&quot;);
  const { context } = require(&quot;@wildcard-api/context&quot;);
  const db = require(&quot;./path/to/db&quot;);
  
  // Server endpoint for user login
  server.login = async (userEmail, password) =&gt; {
    if (!checkCredentials(userEmail, password)) {
      return { wrongCredentials: true };
    }
    const { userId, userName } = await db.getUser(userEmail);
    // Context modifications are persisted. (Under the hood,
    // Wildcard uses Cookies to persist the context.)
    context.user = {
      userId,
      userName,
    };
  };
  
  // Server endpoint to get the to-do list of the logged-in user.
  server.getTodoList = async () =&gt; {
    // `context.userId` is available here!
    const { userId } = context;
    if (!userId) {
      return { notLoggedIn: true };
    }
    const todos = await db.getTodoList(userId);
    return todos;
  };
  
  // The neat thing here is that the following also works:
  
  &lt;div&gt;
    {/*              ...                  */}
    {/* Somewhere deep in a React tree... */}
    {/*              ...                  */}
    &lt;Header&gt;
      {
        // The Wildcard `context` is availble here!
        // Thanks to async hooks, Wildcard knows to which
        // HTTP request `context` belongs too. (While doing SSR.)
        context.userId ? &lt;SignIn /&gt; : &lt;Logout /&gt;
      }
    &lt;/Header&gt;;
  &lt;/div&gt;;
  </code></pre>
  <p>Thanks to Async Hooks, the Wildcard <code>context</code> is availble anywhere(!) within the lifecycle of the HTTP request.</p>
  <p>Wildcard's async hook <a href="https://github.com/reframejs/wildcard-api/blob/9ac10fcd8a673515c854a143362c9ac4fced6100/src/server/context/async-hook-management.ts#L42-L84" rel="nofollow noreferrer">code is small</a> but runs for <em>each</em> async call happening whithin the context of an HTTP request.</p>
  <p>The main danger here are memory leaks but Wildcard's test suit is checking that there are no memory leaks.</p>