One Flag to Trace Them All — `-r securenow/register` Now Works for ESM and CJS

Stop juggling --require and --import flags. securenow/register now auto-registers the ESM loader hook via module.register() on Node >=20.6, so a single -r flag is all you need for both CommonJS and ESM apps.

Apr 2, 2026·5 min read

One Flag to Trace Them All — -r securenow/register Now Works for ESM and CJS

Adding OpenTelemetry to a Node.js application has historically meant remembering different flags depending on whether your project uses CommonJS or ES modules:

# CommonJS — one flag
node --require securenow/register app.js

# ESM ("type": "module") — two flags
node --import @opentelemetry/instrumentation/hook.mjs --require securenow/register app.js

Getting the second form wrong (forgetting the --import, wrong path, Windows file:// issues) meant traces silently never appeared. That two-flag requirement has been the most common support question we see.

Starting now, you only need one flag regardless of your module system:

node -r securenow/register app.js

This post explains what changed, why it works, and what you need to do (hint: almost nothing).

...

What changed: auto-ESM registration via module.register()

Node.js 20.6 introduced module.register(), a programmatic API that lets a CommonJS preload script register ESM loader hooks at runtime — the same hooks that --import registers at launch time.

securenow/register now uses this API automatically. When it loads:

  1. It checks if your app is ESM ("type": "module" in the nearest package.json).
  2. If yes and no --import hook is already present, it calls module.register() to register the OpenTelemetry ESM loader hook.
  3. Then it proceeds with the normal OTel SDK setup.

The result: a single --require securenow/register is all Node needs to instrument both CJS and ESM code.

...

How to use it

Existing start script

If you already use --require securenow/register, you are done. Nothing changes for CJS apps, and ESM apps that previously needed the extra --import flag no longer do (on Node >=20.6).

New setup

npm install securenow

Add one flag to however you start your app:

node -r securenow/register src/index.js

Or keep your existing npm start unchanged and use NODE_OPTIONS:

NODE_OPTIONS="-r securenow/register" npm start

package.json

{
  "scripts": {
    "start": "node -r securenow/register src/index.js",
    "dev": "node -r securenow/register --watch src/index.js"
  }
}

PM2

// ecosystem.config.cjs
module.exports = {
  apps: [{
    name: 'my-app',
    script: './src/index.js',
    node_args: '-r securenow/register',
    env: {
      SECURENOW_APPID: 'your-app-key',
      SECURENOW_INSTANCE: 'https://ingest.securenow.ai',
    }
  }]
};

Docker

CMD ["node", "-r", "securenow/register", "src/index.js"]
...

Node version compatibility

Node versionCJS appsESM appsNotes
18.xSingle -r flagNeeds --import toomodule.register() not available
20.6+Single -r flagSingle -r flagAuto-ESM registration
22.xSingle -r flagSingle -r flagStable module.register()

If you are still on Node 18 with an ESM app, the register file will print a warning with the exact flags you need. But we recommend upgrading to Node 20+ — it is the current LTS and the single-flag experience is much nicer.

...

What happens under the hood

When node -r securenow/register loads:

  1. dotenv — Loads .env into process.env (optional, if dotenv is installed).
  2. ESM detection — Reads the nearest package.json to check "type": "module".
  3. Auto-register — If ESM and Node >=20.6, calls module.register('@opentelemetry/instrumentation/hook.mjs', ...). If --import is already present in process.execArgv, this step is skipped.
  4. OTel SDK — Initializes the OpenTelemetry SDK with trace exporters, log exporters, auto-instrumentation, and all the configuration from your environment variables.

The entire sequence runs before your application's first import or require, which is exactly when instrumentation needs to load.

...

Before vs after

ScenarioBeforeAfter
CJS appnode -r securenow/register app.jsnode -r securenow/register app.js (unchanged)
ESM appnode --import @opentelemetry/instrumentation/hook.mjs -r securenow/register app.jsnode -r securenow/register app.js
ESM + Windowsnode --import file:///C:/.../.../hook.mjs -r securenow/register app.jsnode -r securenow/register app.js
NODE_OPTIONSNODE_OPTIONS="--import .../hook.mjs -r securenow/register"NODE_OPTIONS="-r securenow/register"

The biggest win is for ESM users on Windows, where the file:// URL requirement for --import was a constant source of confusion.

...

What about securenow run?

The securenow CLI also includes a convenience securenow run <script> command that wraps node with the right flags. It is useful if you prefer not to modify your Node command at all, but most teams will find the -r flag simpler and more transparent since it keeps your start scripts standard node commands.

...

Conclusion

Observability should not require memorizing flag combinations. With securenow/register auto-registering the ESM hook on Node >=20.6, a single -r flag is all it takes — for CommonJS, for ESM, on Linux, macOS, and Windows.

Update your securenow package, verify your Node version, and enjoy shorter start scripts.

...

Related reading

  • The Nuxt 3 guide covers the dedicated securenow/nuxt module for Nuxt applications.
  • Other Getting Started posts in this blog cover Express, Fastify, NestJS, and more.
  • The SecureNow docs describe exporters, sampling, and the dashboard — everything after instrumentation.

Frequently Asked Questions

Do I need to change my start scripts?

Just add `-r securenow/register` to your existing `node` command, or set `NODE_OPTIONS="-r securenow/register"`. Your entry file and everything else stays the same.

What about Node 18?

Node 18 does not support `module.register()`. For ESM apps on Node 18 you still need `--import @opentelemetry/instrumentation/hook.mjs`. We recommend upgrading to Node 20+ where the single `-r` flag handles everything.

Does this work with TypeScript entry files?

Yes. Pair it with your usual TypeScript runner: `node -r securenow/register -r ts-node/register src/main.ts`, or compile first and run the JS output.

Can I still use PM2, Docker, or Kubernetes?

Absolutely. Use `node_args: '-r securenow/register'` in PM2, or `CMD ["node", "-r", "securenow/register", "app.js"]` in Docker. The flag works everywhere `node` runs.

What if I was using --import before?

It still works. If `--import @opentelemetry/instrumentation/hook.mjs` is present, the auto-registration step is skipped. There is no double-loading.

Recommended reading

Secure a Next.js App with SecureNow Using This AI Onboarding Prompt

A copy-paste prompt that lets an AI coding agent install SecureNow, wire Next.js instrumentation, verify traces and logs, deploy to AWS, simulate attacks, and prove firewall blocking with human approval gates.

May 18
nextjs securenow ai onboarding prompt
Adding Backend Tracing to a Sentry Stack with OpenTelemetry

If your team uses Sentry for frontend errors and needs backend distributed tracing without doubling the Sentry bill, here's the OpenTelemetry path that doesn't make you choose.

May 9
How to Block Bot Traffic in Express With No Extra Infra

Five approaches to bot blocking in Express, ranked by effort vs. effectiveness. From a 5-line allowlist to a full IP-reputation firewall — all without Cloudflare, AWS WAF, or any new infrastructure.

May 9