diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index f347b0d3..3fccd287 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -65,22 +65,40 @@ The SDK supports both CommonJS and ESM module systems, using different intercept
#### CommonJS Module Interception
-- **Package**: `require-in-the-middle`
-- **How it works**: Hooks into `Module.prototype.require` globally
-- **When it activates**: When `require()` is called
-- **Setup**: Automatic - no special flags needed
-- **Use case**: Works for all CommonJS modules
+- **Package**: `require-in-the-middle` (RITM)
+- **How it works**: CJS modules are loaded through a single JavaScript function (`Module._load`). RITM monkey-patches this function so that every `require()` call passes through the patch, giving the SDK a chance to intercept and wrap module exports.
+- **Setup**: Automatic -- no special flags or loader registration needed. Just calling `TuskDrift.initialize()` before other `require()` calls is sufficient.
#### ESM Module Interception
-- **Package**: `import-in-the-middle`, created by [Datadog](https://opensource.datadoghq.com/projects/node/#the-import-in-the-middle-library)
-- **How it works**: Uses Node.js loader hooks to intercept imports before they're cached
-- **When it activates**: During module resolution/loading phase
-- **Setup**: Requires `--import` flag or `module.register()` call
-- **Use case**: Required for ESM modules
-- **Loader file**: `hook.mjs` - re-exports loader hooks from `import-in-the-middle`
+- **Package**: `import-in-the-middle` (IITM), created by [Datadog](https://opensource.datadoghq.com/projects/node/#the-import-in-the-middle-library)
+- **How it works**: Unlike CJS, ESM module loading is handled by Node.js internals (C++), not a patchable JavaScript function. The only way to intercept ESM imports is through Node's official [customization hooks API](https://nodejs.org/api/module.html#customization-hooks) (`module.register`), which runs hook code in a separate loader thread.
+- **Setup**: The SDK automatically registers ESM loader hooks inside `TuskDrift.initialize()` via `module.register()` (see `src/core/esmLoader.ts`). ESM applications must still use `--import` to ensure the init file runs before the application's import graph is resolved. The `hook.mjs` file at the package root is kept for backward compatibility but is no longer required for manual registration.
-**Key difference**: CommonJS's `require()` is synchronous and sequential, so you can control order. ESM's `import` is hoisted and parallel, requiring loader hooks to intercept before evaluation.
+#### How ESM instrumentation works end-to-end
+
+1. **Loader registration**: `initializeEsmLoader()` (called from `TuskDrift.initialize()`) uses `createAddHookMessageChannel()` from IITM to set up a `MessagePort` between the main thread and the loader thread, then calls `module.register('import-in-the-middle/hook.mjs', ...)` to install the loader hooks.
+2. **Module wrapping**: When any ESM module is imported, IITM's `load` hook transforms its source code on the fly, replacing all named exports with getter/setter proxies. The module works normally, but exports now pass through a proxy layer.
+3. **Hook registration**: `TdInstrumentationBase.enable()` creates `new HookImport(['pg'], {}, hookFn)` for each instrumented module. This registers a callback and sends the module name to the loader thread via the `MessagePort` so the loader knows to watch for it.
+4. **Interception at runtime**: When application code accesses a wrapped module's exports (e.g., `import { Client } from 'pg'`), the getter proxy fires, the `hookFn` callback runs, and the SDK patches the export with its instrumented version.
+
+For CJS, steps 1-2 are unnecessary -- RITM patches `Module._load` directly in the main thread, and the rest works the same way.
+
+#### Why `--import` is still needed for ESM
+
+In CJS, `require()` is synchronous and imperative -- putting `require('./tuskDriftInit')` first guarantees it runs before other modules. In ESM, all `import` declarations are hoisted and the entire module graph is resolved before any module-level code executes. The `--import` flag runs the init file in a pre-evaluation phase, ensuring `TuskDrift.initialize()` (and the loader registration) happens before the application's imports are resolved.
+
+#### Node.js built-in modules are always CJS
+
+Node.js built-in modules (`http`, `https`, `net`, `fs`, etc.) are loaded through the CJS `require()` path internally, even when imported via ESM `import` syntax. This means RITM can intercept them regardless of the application's module system, and the ESM loader hooks are not required for built-in module instrumentation.
+
+#### The `registerEsmLoaderHooks` opt-out
+
+Because we pass `include: []` during `module.register()`, IITM starts with an empty allowlist and only wraps modules that are explicitly registered via `new Hook([...])` on the main thread (sent to the loader thread over the `MessagePort`). This means only modules the SDK actually instruments get their exports wrapped with getter/setter proxies -- unrelated modules are left untouched. In rare cases, the wrapping can still conflict with non-standard export patterns, native/WASM bindings, or bundler-generated ESM in the instrumented modules themselves. Users can disable this with `registerEsmLoaderHooks: false` in `TuskDrift.initialize()`, which means only CJS-loaded modules will be instrumentable. See `docs/initialization.md` for the user-facing documentation.
+
+#### Compatibility with other IITM consumers (Sentry, OpenTelemetry)
+
+Multiple SDKs can each call `module.register()` with their own IITM loader instance and `MessagePort`. IITM detects the duplicate initialization (`global.__import_in_the_middle_initialized__`) and logs a warning, but both SDKs' hooks will fire correctly. Patches layer on top of each other -- if Sentry wraps `pg.Client.query` and Drift also wraps it, the final export passes through both wrappers.
### When Does an Instrumentation Need Special ESM Handling?
diff --git a/docs/initialization.md b/docs/initialization.md
index fbfc6bc8..2f63e6be 100644
--- a/docs/initialization.md
+++ b/docs/initialization.md
@@ -20,26 +20,7 @@ Create a separate file (e.g. `tuskDriftInit.ts` or `tuskDriftInit.js`) to initia
**IMPORTANT**: Ensure that `TuskDrift` is initialized before any other telemetry providers (e.g. OpenTelemetry, Sentry, etc.). If not, your existing telemetry may not work properly.
-### Determining Your Module System
-
-Before proceeding, you need to determine whether your application uses **CommonJS** or **ESM** (ECMAScript Modules).
-
-The easiest way to determine this is by looking at your import syntax.
-
-**If your application uses `require()`:**
-
-- Your application is CommonJS (use the CommonJS setup below)
-
-**If your application uses `import` statements:**
-
-- This could be either CommonJS or ESM, depending on your build configuration
-- Check your compiled output (if you compile to a directory like `dist/`):
- - If the compiled code contains `require()` statements → CommonJS application
- - If the compiled code contains `import` statements → ESM application
-- If you don't compile your code (running source files directly):
- - It is an ESM application
-
-### For CommonJS Applications
+The initialization file is the same for both CommonJS and ESM applications. The SDK automatically registers ESM loader hooks when running in an ESM environment (Node.js >= 18.19.0 or >= 20.6.0).
```typescript
// tuskDriftInit.ts or tuskDriftInit.js
@@ -54,31 +35,7 @@ TuskDrift.initialize({
export { TuskDrift };
```
-### For ESM Applications
-
-ESM applications require additional setup to properly intercept module imports:
-
-```typescript
-// tuskDriftInit.ts
-import { register } from "node:module";
-import { pathToFileURL } from "node:url";
-
-// Register the ESM loader
-// This enables interception of ESM module imports
-register("@use-tusk/drift-node-sdk/hook.mjs", pathToFileURL("./"));
-
-import { TuskDrift } from "@use-tusk/drift-node-sdk";
-
-// Initialize SDK immediately
-TuskDrift.initialize({
- apiKey: process.env.TUSK_API_KEY,
- env: process.env.NODE_ENV,
-});
-
-export { TuskDrift };
-```
-
-**Why the ESM loader is needed**: ESM imports are statically analyzed and hoisted, meaning all imports are resolved before any code runs. The `register()` call sets up Node.js loader hooks that intercept module imports, allowing the SDK to instrument packages like `postgres`, `http`, etc. Without this, the SDK cannot patch ESM modules.
+> **Note:** ESM applications still require the `--import` flag when starting Node.js. See [Step 2](#2-import-sdk-at-application-entry-point) for details.
### Initialization Parameters
@@ -116,6 +73,12 @@ export { TuskDrift };
1.0 |
Override sampling rate (0.0 - 1.0) for recording. Takes precedence over TUSK_SAMPLING_RATE env var and config file. |
+
+ registerEsmLoaderHooks |
+ boolean |
+ true |
+ Automatically register ESM loader hooks for module interception. Set to false to disable if import-in-the-middle causes issues with certain packages. See Troubleshooting ESM. |
+
@@ -123,6 +86,23 @@ export { TuskDrift };
## 2. Import SDK at Application Entry Point
+### Determining Your Module System
+
+You need to know whether your application uses **CommonJS** or **ESM** (ECMAScript Modules) because the entry point setup differs.
+
+**If your application uses `require()`:**
+
+- Your application is CommonJS
+
+**If your application uses `import` statements:**
+
+- This could be either CommonJS or ESM, depending on your build configuration
+- Check your compiled output (if you compile to a directory like `dist/`):
+ - If the compiled code contains `require()` statements → CommonJS application
+ - If the compiled code contains `import` statements → ESM application
+- If you don't compile your code (running source files directly):
+ - It is an ESM application
+
### For CommonJS Applications
In your main server file (e.g., `server.ts`, `index.ts`, `app.ts`), require the initialized SDK **at the very top**, before any other requires:
@@ -153,7 +133,7 @@ For ESM applications, you **cannot** control import order within your applicatio
}
```
-**Why `--import` is required for ESM**: In ESM, all `import` statements are hoisted and evaluated before any code runs, making it impossible to control import order within a file. The `--import` flag ensures the SDK initialization (including loader registration) happens in a separate phase before your application code loads, guaranteeing proper module interception.
+**Why `--import` is required for ESM**: In ESM, all `import` statements are hoisted and evaluated before any code runs, making it impossible to control import order within a file. The `--import` flag ensures the SDK initialization happens in a separate phase before your application code loads, guaranteeing proper module interception.
### 3. Configure Sampling Rate
@@ -255,3 +235,33 @@ app.listen(8000, () => {
console.log("Server started and ready for Tusk Drift");
});
```
+
+## Troubleshooting ESM
+
+The SDK automatically registers ESM loader hooks via [`import-in-the-middle`](https://www.npmjs.com/package/import-in-the-middle) to intercept ES module imports. Only modules that the SDK instruments have their exports wrapped with getter/setter proxies -- unrelated modules are left untouched.
+
+In rare cases, the wrapping can cause issues with instrumented packages:
+
+- **Non-standard export patterns**: Some packages use dynamic `export *` re-exports or conditional exports that the wrapper's static analysis cannot parse, resulting in runtime syntax errors.
+- **Native or WASM bindings**: Packages with native addons loaded via ESM can conflict with the proxy wrapping mechanism.
+- **Bundler-generated ESM**: Code that was bundled (e.g., by esbuild or webpack) into ESM sometimes produces patterns the wrapper does not handle correctly.
+- **Circular ESM imports**: The proxy layer can interact badly with circular ESM import graphs in some edge cases.
+
+If you encounter errors like:
+
+```
+SyntaxError: The requested module '...' does not provide an export named '...'
+(node:1234) Error: 'import-in-the-middle' failed to wrap 'file://../../path/to/file.js'
+```
+
+You can disable the automatic ESM hook registration:
+
+```typescript
+TuskDrift.initialize({
+ apiKey: process.env.TUSK_API_KEY,
+ env: process.env.NODE_ENV,
+ registerEsmLoaderHooks: false,
+});
+```
+
+> **Note:** Disabling ESM loader hooks means the SDK will only be able to instrument packages loaded via CommonJS (`require()`). Packages loaded purely through ESM `import` statements will not be intercepted. Node.js built-in modules (like `http`, `https`, `net`) are always loaded through the CJS path internally, so they will continue to be instrumented regardless of this setting.
diff --git a/src/core/TuskDrift.ts b/src/core/TuskDrift.ts
index 795346e0..d916a757 100644
--- a/src/core/TuskDrift.ts
+++ b/src/core/TuskDrift.ts
@@ -40,11 +40,13 @@ import {
loadTuskConfig,
TuskConfig,
OriginalGlobalUtils,
+ isCommonJS,
} from "./utils";
import { TransformConfigs } from "../instrumentation/libraries/types";
import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
import { Resource } from "@opentelemetry/resources";
import { getRustCoreStartupStatus } from "./rustCoreBinding";
+import { initializeEsmLoader } from "./esmLoader";
export interface InitParams {
apiKey?: string;
@@ -52,6 +54,8 @@ export interface InitParams {
logLevel?: LogLevel;
transforms?: TransformConfigs;
samplingRate?: number;
+ /** Set to `false` to disable automatic ESM loader hook registration. Defaults to `true`. */
+ registerEsmLoaderHooks?: boolean;
}
export enum TuskDriftMode {
@@ -83,15 +87,6 @@ export class TuskDriftCore {
this.config = loadTuskConfig() || {};
}
- private isCommonJS(): boolean {
- return (
- typeof module !== "undefined" &&
- "exports" in module &&
- typeof require !== "undefined" &&
- typeof require.cache !== "undefined"
- );
- }
-
private getPackageName(modulePath: string): string | null {
let dir = path.dirname(modulePath);
while (dir) {
@@ -117,7 +112,7 @@ export class TuskDriftCore {
private alreadyRequiredModules(): Set {
const alreadyRequiredModuleNames = new Set();
- if (this.isCommonJS()) {
+ if (isCommonJS()) {
const requireCache = Object.keys(require.cache);
for (const modulePath of requireCache) {
if (modulePath.includes("node_modules")) {
@@ -478,6 +473,10 @@ export class TuskDriftCore {
return;
}
+ if (initParams.registerEsmLoaderHooks !== false) {
+ initializeEsmLoader();
+ }
+
this.logRustCoreStartupStatus();
logger.debug(`Initializing in ${this.mode} mode`);
diff --git a/src/core/esmLoader.ts b/src/core/esmLoader.ts
new file mode 100644
index 00000000..d5597410
--- /dev/null
+++ b/src/core/esmLoader.ts
@@ -0,0 +1,70 @@
+import { createAddHookMessageChannel } from "import-in-the-middle";
+import * as moduleModule from "module";
+import { logger } from "./utils";
+import { isCommonJS } from "./utils/runtimeDetectionUtils";
+
+const NODE_MAJOR = parseInt(process.versions.node.split(".")[0]!, 10);
+const NODE_MINOR = parseInt(process.versions.node.split(".")[1]!, 10);
+
+function supportsModuleRegister(): boolean {
+ return (
+ NODE_MAJOR >= 21 ||
+ (NODE_MAJOR === 20 && NODE_MINOR >= 6) ||
+ (NODE_MAJOR === 18 && NODE_MINOR >= 19)
+ );
+}
+
+/**
+ * Automatically register ESM loader hooks via `import-in-the-middle` so that
+ * ESM imports can be intercepted for instrumentation.
+ *
+ * In CJS mode this is a no-op because `require-in-the-middle` handles
+ * interception. On Node versions that lack `module.register` support
+ * (< 18.19, < 20.6) we log a warning and skip.
+ *
+ * https://nodejs.org/api/module.html#moduleregisterspecifier-parenturl-options
+ */
+export function initializeEsmLoader(): void {
+ if (isCommonJS()) {
+ return;
+ }
+
+ if (!supportsModuleRegister()) {
+ logger.warn(
+ `Node.js ${process.versions.node} does not support module.register(). ` +
+ `ESM loader hooks will not be registered automatically. ` +
+ `Upgrade to Node.js >= 18.19.0 or >= 20.6.0, or register the hooks manually.`,
+ );
+ return;
+ }
+
+ if ((globalThis as any).__tuskDriftEsmLoaderRegistered) {
+ return;
+ }
+ (globalThis as any).__tuskDriftEsmLoaderRegistered = true;
+
+ try {
+ // createAddHookMessageChannel sets up a MessagePort so the main thread can
+ // send new hook registrations (from `new Hook(...)` calls in userland) to
+ // the loader thread, which runs in a separate context.
+ const { addHookMessagePort } = createAddHookMessageChannel();
+
+ // The IITM loader hook module that intercepts ESM imports.
+ // Resolved relative to this SDK package (import.meta.url) so the hook
+ // module is found from node_modules regardless of the user's cwd.
+ // @ts-expect-error register exists on module in supported Node versions
+ moduleModule.register("import-in-the-middle/hook.mjs", import.meta.url, {
+ // Payload sent to the loader hook's initialize() function:
+ // - addHookMessagePort: the MessagePort for main↔loader communication
+ // - include: [] starts with an empty allowlist; only modules registered
+ // via new Hook([...]) on the main thread get added dynamically through
+ // the MessagePort, so only instrumented modules are wrapped.
+ data: { addHookMessagePort, include: [] },
+ // Transfer (not clone) the port — a MessagePort can only be owned by one thread
+ transferList: [addHookMessagePort],
+ });
+ logger.debug("ESM loader hooks registered successfully");
+ } catch (error) {
+ logger.warn("Failed to register ESM loader hooks:", error);
+ }
+}
diff --git a/src/core/utils/runtimeDetectionUtils.ts b/src/core/utils/runtimeDetectionUtils.ts
index c01c8c4b..2440985d 100644
--- a/src/core/utils/runtimeDetectionUtils.ts
+++ b/src/core/utils/runtimeDetectionUtils.ts
@@ -1,3 +1,16 @@
+export function isCommonJS(): boolean {
+ try {
+ return (
+ typeof module !== "undefined" &&
+ "exports" in module &&
+ typeof require !== "undefined" &&
+ typeof require.cache !== "undefined"
+ );
+ } catch {
+ return false;
+ }
+}
+
export function isNextJsRuntime(): boolean {
return (
process.env.NEXT_RUNTIME !== undefined || typeof (global as any).__NEXT_DATA__ !== "undefined"
diff --git a/src/instrumentation/libraries/fetch/e2e-tests/esm-fetch/src/tdInit.ts b/src/instrumentation/libraries/fetch/e2e-tests/esm-fetch/src/tdInit.ts
index d8e4a51f..b7f7e9a6 100644
--- a/src/instrumentation/libraries/fetch/e2e-tests/esm-fetch/src/tdInit.ts
+++ b/src/instrumentation/libraries/fetch/e2e-tests/esm-fetch/src/tdInit.ts
@@ -1,11 +1,4 @@
-import { register } from 'node:module';
-import { pathToFileURL } from 'node:url';
-
-// Register the ESM loader
-// This enables interception of ESM module imports
-register('@use-tusk/drift-node-sdk/hook.mjs', pathToFileURL('./'));
-
-import { TuskDrift } from '@use-tusk/drift-node-sdk';
+import { TuskDrift } from "@use-tusk/drift-node-sdk";
TuskDrift.initialize({
apiKey: "api-key",
diff --git a/src/instrumentation/libraries/firestore/e2e-tests/esm-firestore/src/tdInit.ts b/src/instrumentation/libraries/firestore/e2e-tests/esm-firestore/src/tdInit.ts
index d8e4a51f..b7f7e9a6 100644
--- a/src/instrumentation/libraries/firestore/e2e-tests/esm-firestore/src/tdInit.ts
+++ b/src/instrumentation/libraries/firestore/e2e-tests/esm-firestore/src/tdInit.ts
@@ -1,11 +1,4 @@
-import { register } from 'node:module';
-import { pathToFileURL } from 'node:url';
-
-// Register the ESM loader
-// This enables interception of ESM module imports
-register('@use-tusk/drift-node-sdk/hook.mjs', pathToFileURL('./'));
-
-import { TuskDrift } from '@use-tusk/drift-node-sdk';
+import { TuskDrift } from "@use-tusk/drift-node-sdk";
TuskDrift.initialize({
apiKey: "api-key",
diff --git a/src/instrumentation/libraries/grpc/e2e-tests/esm-grpc/src/tdInit.ts b/src/instrumentation/libraries/grpc/e2e-tests/esm-grpc/src/tdInit.ts
index d8e4a51f..b7f7e9a6 100644
--- a/src/instrumentation/libraries/grpc/e2e-tests/esm-grpc/src/tdInit.ts
+++ b/src/instrumentation/libraries/grpc/e2e-tests/esm-grpc/src/tdInit.ts
@@ -1,11 +1,4 @@
-import { register } from 'node:module';
-import { pathToFileURL } from 'node:url';
-
-// Register the ESM loader
-// This enables interception of ESM module imports
-register('@use-tusk/drift-node-sdk/hook.mjs', pathToFileURL('./'));
-
-import { TuskDrift } from '@use-tusk/drift-node-sdk';
+import { TuskDrift } from "@use-tusk/drift-node-sdk";
TuskDrift.initialize({
apiKey: "api-key",
diff --git a/src/instrumentation/libraries/http/e2e-tests/esm-http/src/tdInit.ts b/src/instrumentation/libraries/http/e2e-tests/esm-http/src/tdInit.ts
index d8e4a51f..b7f7e9a6 100644
--- a/src/instrumentation/libraries/http/e2e-tests/esm-http/src/tdInit.ts
+++ b/src/instrumentation/libraries/http/e2e-tests/esm-http/src/tdInit.ts
@@ -1,11 +1,4 @@
-import { register } from 'node:module';
-import { pathToFileURL } from 'node:url';
-
-// Register the ESM loader
-// This enables interception of ESM module imports
-register('@use-tusk/drift-node-sdk/hook.mjs', pathToFileURL('./'));
-
-import { TuskDrift } from '@use-tusk/drift-node-sdk';
+import { TuskDrift } from "@use-tusk/drift-node-sdk";
TuskDrift.initialize({
apiKey: "api-key",
diff --git a/src/instrumentation/libraries/ioredis/e2e-tests/esm-ioredis/src/tdInit.ts b/src/instrumentation/libraries/ioredis/e2e-tests/esm-ioredis/src/tdInit.ts
index d8e4a51f..b7f7e9a6 100644
--- a/src/instrumentation/libraries/ioredis/e2e-tests/esm-ioredis/src/tdInit.ts
+++ b/src/instrumentation/libraries/ioredis/e2e-tests/esm-ioredis/src/tdInit.ts
@@ -1,11 +1,4 @@
-import { register } from 'node:module';
-import { pathToFileURL } from 'node:url';
-
-// Register the ESM loader
-// This enables interception of ESM module imports
-register('@use-tusk/drift-node-sdk/hook.mjs', pathToFileURL('./'));
-
-import { TuskDrift } from '@use-tusk/drift-node-sdk';
+import { TuskDrift } from "@use-tusk/drift-node-sdk";
TuskDrift.initialize({
apiKey: "api-key",
diff --git a/src/instrumentation/libraries/mongodb/e2e-tests/esm-mongodb/src/tdInit.ts b/src/instrumentation/libraries/mongodb/e2e-tests/esm-mongodb/src/tdInit.ts
index d01058a3..b7f7e9a6 100644
--- a/src/instrumentation/libraries/mongodb/e2e-tests/esm-mongodb/src/tdInit.ts
+++ b/src/instrumentation/libraries/mongodb/e2e-tests/esm-mongodb/src/tdInit.ts
@@ -1,10 +1,3 @@
-import { register } from "node:module";
-import { pathToFileURL } from "node:url";
-
-// Register the ESM loader
-// This enables interception of ESM module imports
-register("@use-tusk/drift-node-sdk/hook.mjs", pathToFileURL("./"));
-
import { TuskDrift } from "@use-tusk/drift-node-sdk";
TuskDrift.initialize({
diff --git a/src/instrumentation/libraries/mysql/e2e-tests/esm-mysql/src/tdInit.ts b/src/instrumentation/libraries/mysql/e2e-tests/esm-mysql/src/tdInit.ts
index d8e4a51f..b7f7e9a6 100644
--- a/src/instrumentation/libraries/mysql/e2e-tests/esm-mysql/src/tdInit.ts
+++ b/src/instrumentation/libraries/mysql/e2e-tests/esm-mysql/src/tdInit.ts
@@ -1,11 +1,4 @@
-import { register } from 'node:module';
-import { pathToFileURL } from 'node:url';
-
-// Register the ESM loader
-// This enables interception of ESM module imports
-register('@use-tusk/drift-node-sdk/hook.mjs', pathToFileURL('./'));
-
-import { TuskDrift } from '@use-tusk/drift-node-sdk';
+import { TuskDrift } from "@use-tusk/drift-node-sdk";
TuskDrift.initialize({
apiKey: "api-key",
diff --git a/src/instrumentation/libraries/mysql2/e2e-tests/esm-mysql2/src/tdInit.ts b/src/instrumentation/libraries/mysql2/e2e-tests/esm-mysql2/src/tdInit.ts
index d8e4a51f..b7f7e9a6 100644
--- a/src/instrumentation/libraries/mysql2/e2e-tests/esm-mysql2/src/tdInit.ts
+++ b/src/instrumentation/libraries/mysql2/e2e-tests/esm-mysql2/src/tdInit.ts
@@ -1,11 +1,4 @@
-import { register } from 'node:module';
-import { pathToFileURL } from 'node:url';
-
-// Register the ESM loader
-// This enables interception of ESM module imports
-register('@use-tusk/drift-node-sdk/hook.mjs', pathToFileURL('./'));
-
-import { TuskDrift } from '@use-tusk/drift-node-sdk';
+import { TuskDrift } from "@use-tusk/drift-node-sdk";
TuskDrift.initialize({
apiKey: "api-key",
diff --git a/src/instrumentation/libraries/pg/e2e-tests/esm-pg/src/tdInit.ts b/src/instrumentation/libraries/pg/e2e-tests/esm-pg/src/tdInit.ts
index d8e4a51f..b7f7e9a6 100644
--- a/src/instrumentation/libraries/pg/e2e-tests/esm-pg/src/tdInit.ts
+++ b/src/instrumentation/libraries/pg/e2e-tests/esm-pg/src/tdInit.ts
@@ -1,11 +1,4 @@
-import { register } from 'node:module';
-import { pathToFileURL } from 'node:url';
-
-// Register the ESM loader
-// This enables interception of ESM module imports
-register('@use-tusk/drift-node-sdk/hook.mjs', pathToFileURL('./'));
-
-import { TuskDrift } from '@use-tusk/drift-node-sdk';
+import { TuskDrift } from "@use-tusk/drift-node-sdk";
TuskDrift.initialize({
apiKey: "api-key",
diff --git a/src/instrumentation/libraries/postgres/e2e-tests/esm-postgres/src/tdInit.ts b/src/instrumentation/libraries/postgres/e2e-tests/esm-postgres/src/tdInit.ts
index d8e4a51f..b7f7e9a6 100644
--- a/src/instrumentation/libraries/postgres/e2e-tests/esm-postgres/src/tdInit.ts
+++ b/src/instrumentation/libraries/postgres/e2e-tests/esm-postgres/src/tdInit.ts
@@ -1,11 +1,4 @@
-import { register } from 'node:module';
-import { pathToFileURL } from 'node:url';
-
-// Register the ESM loader
-// This enables interception of ESM module imports
-register('@use-tusk/drift-node-sdk/hook.mjs', pathToFileURL('./'));
-
-import { TuskDrift } from '@use-tusk/drift-node-sdk';
+import { TuskDrift } from "@use-tusk/drift-node-sdk";
TuskDrift.initialize({
apiKey: "api-key",
diff --git a/src/instrumentation/libraries/prisma/e2e-tests/esm-prisma/src/tdInit.ts b/src/instrumentation/libraries/prisma/e2e-tests/esm-prisma/src/tdInit.ts
index c0c40e35..b7f7e9a6 100644
--- a/src/instrumentation/libraries/prisma/e2e-tests/esm-prisma/src/tdInit.ts
+++ b/src/instrumentation/libraries/prisma/e2e-tests/esm-prisma/src/tdInit.ts
@@ -1,12 +1,4 @@
-// ESM-specific: Register the ESM loader FIRST before any imports
-import { register } from 'node:module';
-import { pathToFileURL } from 'node:url';
-
-// Register the ESM loader
-// This enables interception of ESM module imports
-register('@use-tusk/drift-node-sdk/hook.mjs', pathToFileURL('./'));
-
-import { TuskDrift } from '@use-tusk/drift-node-sdk';
+import { TuskDrift } from "@use-tusk/drift-node-sdk";
TuskDrift.initialize({
apiKey: "api-key",
diff --git a/src/instrumentation/libraries/redis/e2e-tests/esm-redis/src/tdInit.ts b/src/instrumentation/libraries/redis/e2e-tests/esm-redis/src/tdInit.ts
index d01058a3..b7f7e9a6 100644
--- a/src/instrumentation/libraries/redis/e2e-tests/esm-redis/src/tdInit.ts
+++ b/src/instrumentation/libraries/redis/e2e-tests/esm-redis/src/tdInit.ts
@@ -1,10 +1,3 @@
-import { register } from "node:module";
-import { pathToFileURL } from "node:url";
-
-// Register the ESM loader
-// This enables interception of ESM module imports
-register("@use-tusk/drift-node-sdk/hook.mjs", pathToFileURL("./"));
-
import { TuskDrift } from "@use-tusk/drift-node-sdk";
TuskDrift.initialize({
diff --git a/src/instrumentation/libraries/upstash-redis-js/e2e-tests/esm-upstash-redis-js/src/tdInit.ts b/src/instrumentation/libraries/upstash-redis-js/e2e-tests/esm-upstash-redis-js/src/tdInit.ts
index d8e4a51f..b7f7e9a6 100644
--- a/src/instrumentation/libraries/upstash-redis-js/e2e-tests/esm-upstash-redis-js/src/tdInit.ts
+++ b/src/instrumentation/libraries/upstash-redis-js/e2e-tests/esm-upstash-redis-js/src/tdInit.ts
@@ -1,11 +1,4 @@
-import { register } from 'node:module';
-import { pathToFileURL } from 'node:url';
-
-// Register the ESM loader
-// This enables interception of ESM module imports
-register('@use-tusk/drift-node-sdk/hook.mjs', pathToFileURL('./'));
-
-import { TuskDrift } from '@use-tusk/drift-node-sdk';
+import { TuskDrift } from "@use-tusk/drift-node-sdk";
TuskDrift.initialize({
apiKey: "api-key",