ESM / instrumentation order
Node ESM apps go quiet when a client is imported before init() — here's where init belongs in each framework.
Node only. Calls succeed, the dashboard is empty, and firewall: "enforce" blocks nothing.
Symptoms
- Nothing at all arrives, in a Next.js, Vite, tsup-ESM, Bun, or Deno app.
- One library arrives and another doesn't — typically the one imported highest in your entry file.
- It worked under
ts-node/CommonJS and stopped after moving to native ESM.
All three have the same cause: a provider client that was imported before tp.init() ran is
left un-instrumented, silently, by fail-open design.
Two things fix it, and you generally want both: pass your provider modules to init() via
instrumentModules, and put init() somewhere that runs first. The full key list and import
forms are in Node & ESM; the placement is below.
Where init goes per framework
Next.js (app router) — put init in instrumentation.ts at the project root, guarded to the
Node runtime. Next loads it once before serving any route.
Vite / tsup / Bun / Deno — put init in its own module and import it first in your entry
file, before anything else:
// entry.ts
import "./instrument"; // must be the first import
import { startServer } from "./server";LangChain / LangGraph — install the token-police-langchain companion package, and static-import
@langchain/core/language_models/chat_models and @langchain/core/callbacks/manager before
init(). Keep every other @langchain/* import out of the entry module. See
LangChain.
LlamaIndex — pass each @llamaindex/* provider namespace under instrumentModules.llamaIndex.
See LlamaIndex.
Vercel AI SDK — first-party providers are found automatically; community providers go in the
aiSdkProviders array, and bundled or edge builds use the middleware instead. See
Vercel AI SDK.

