How to fix DeprecationWarning: domain module is deprecated (use async_hooks instead) in Node.js

Node.jsINTERMEDIATEMEDIUMUpdated Dec 9, 2025ยท 132 views

The Node.js domain module is deprecated and should not be used in new code. This warning appears when you import or use the domain module. Use async_hooks or AsyncResource instead for proper async context tracking.

Quick fix

Fixes DEP0032

grep -r "require('domain')" .
grep -r 'require("domain")' .
grep -r "from 'domain'" .
grep -r 'from "domain"' .
  1. Locate all domain module usage
  2. Understand your domain usage
  3. Replace with AsyncResource for simple cases
  4. Use async_hooks for advanced context tracking
node.js โ€” error
grep -r "require('domain')" .
grep -r 'require("domain")' .
grep -r "from 'domain'" .
grep -r 'from "domain"' .
DeprecationWarning: domain module is deprecated (use async_hooks instead)

What this error means

The domain module was Node.js's original mechanism for handling asynchronous errors and resource cleanup. However, it proved to be fundamentally unreliable in practice, with design limitations that made it unsuitable for modern asynchronous code patterns. Node.js has therefore deprecated the entire domain module and recommends using async_hooks and the AsyncResource API instead. This deprecation warning appears when you require or import the domain module anywhere in your code. While the module still works, it should not be used in new code, and existing code should be migrated to modern alternatives.

Typical symptoms

  • DeprecationWarning appears in console output when running your Node.js application
  • The warning message includes 'domain module is deprecated'
  • Application still runs but shows deprecation notice
  • Linting tools may flag domain module usage as problematic

Common causes

  1. You are importing or requiring the 'domain' module in your code
  2. A dependency or library you're using internally relies on the domain module
  3. Legacy code that hasn't been updated to use modern async patterns

How to fix "DeprecationWarning: domain module is deprecated (use async_hooks instead)"

1Locate all domain module usage

Search your codebase for any imports or requires of the domain module:

bash
grep -r "require('domain')" .
grep -r 'require("domain")' .
grep -r "from 'domain'" .
grep -r 'from "domain"' .

Note the files and lines where domain is used.

2Understand your domain usage

Review the code where domain is used and identify what it's doing:

javascript
// Old domain pattern
const domain = require('domain');
const d = domain.create();

d.on('error', (err) => {
  // error handling
});

d.run(() => {
  // async code
});

Common patterns:
- Creating domains for error handling
- Using domain.run() to execute code within a domain context
- Listening to domain 'error' events

3Replace with AsyncResource for simple cases

For most use cases, replace domain with async_hooks AsyncResource:

javascript
// Modern pattern using AsyncResource
const { AsyncResource } = require('async_hooks');

class MyResource extends AsyncResource {
  constructor(name) {
    super(name);
  }

  run(callback) {
    return this.runInAsyncScope(callback);
  }
}

const resource = new MyResource('MyResource');

try {
  resource.run(() => {
    // async code
  });
} catch (err) {
  // error handling
}

This provides similar context tracking without the deprecated API.

4Use async_hooks for advanced context tracking

For more complex async context tracking needs, use async_hooks directly:

javascript
const async_hooks = require('async_hooks');

const hook = async_hooks.createHook({
  init(asyncId, type, triggerAsyncId) {
    // Track async resource initialization
  },
  before(asyncId) {
    // Code before async callback
  },
  after(asyncId) {
    // Code after async callback
  },
  destroy(asyncId) {
    // Cleanup
  },
});

hook.enable();

This gives you fine-grained control over async lifecycle management.

5Handle errors in async code

Instead of relying on domain error handling, use modern error handling patterns:

javascript
// Promise-based (modern)
async function myAsyncFunction() {
  try {
    // async code
  } catch (err) {
    // handle error
  }
}

// Or with .catch()
Promise.resolve()
  .then(() => {
    // async code
  })
  .catch((err) => {
    // handle error
  });

// Unhandled rejection handler
process.on('unhandledRejection', (reason, promise) => {
  console.error('Unhandled Rejection:', reason);
});
6Update dependencies

If the domain module is being used by a dependency:

1. Check if there's a newer version that has removed domain usage:

bash
npm outdated
   npm update

2. If the dependency is unmaintained, consider replacing it with an actively maintained alternative

3. If it's your own dependency, update it internally to use async_hooks instead

4. Run your test suite after updates:

bash
npm test
7Test and verify

After making changes, verify the deprecation warning is gone:

1. Run your application:

bash
node your-app.js

2. Look for the DeprecationWarning in the output - it should be gone

3. Run your test suite to ensure functionality still works:

bash
npm test

4. Check for any new errors or warnings that may have appeared

Advanced notes

Why domain was unreliable: The domain module attempted to track all asynchronous operations within a domain context, but it had several fundamental issues: it couldn't reliably handle all async patterns (especially Promises), it caused performance overhead, and it was difficult to reason about which operations belonged to which domain.

async_hooks limitations: While async_hooks is more reliable than domain, Node.js itself discourages its use in userland code for most cases. It's a low-level API primarily intended for tooling and instrumentation. For application code, prefer structured error handling patterns (try/catch, .catch(), Promise.allSettled()) and consider using async context libraries like AsyncLocalStorage.

AsyncLocalStorage alternative: For the common use case of tracking request context (like in Express middleware), AsyncLocalStorage provides a cleaner API than raw async_hooks:

javascript
const { AsyncLocalStorage } = require('async_hooks');

const asyncLocalStorage = new AsyncLocalStorage();

// Store context
asyncLocalStorage.run(requestContext, () => {
  // code runs with context
});

// Retrieve context
const context = asyncLocalStorage.getStore();

Node.js versions: The domain module is deprecated in all modern Node.js versions (v4+), but will not be removed for backward compatibility. However, migration to modern patterns is strongly recommended.

Frequently asked questions

What does "DEP0032" mean?
js's original mechanism for handling asynchronous errors and resource cleanup. However, it proved to be fundamentally unreliable in practice, with design limitations that made it unsuitable for modern asynchronous code patterns. js has therefore deprecated the entire domain module and recommends using async_hooks and the AsyncResource API instead.
How do I fix "DEP0032"?
The Node.js domain module is deprecated and should not be used in new code. This warning appears when you import or use the domain module. Use async_hooks or AsyncResource instead for proper async context tracking.
What causes "DEP0032"?
You are importing or requiring the 'domain' module in your code A dependency or library you're using internally relies on the domain module Legacy code that hasn't been updated to use modern async patterns
Is the "DEP0032" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading