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.
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:
- It checks if your app is ESM (
"type": "module"in the nearestpackage.json). - If yes and no
--importhook is already present, it callsmodule.register()to register the OpenTelemetry ESM loader hook. - 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://freetrial.securenow.ai:4318',
}
}]
};
Docker
CMD ["node", "-r", "securenow/register", "src/index.js"]
Node version compatibility
| Node version | CJS apps | ESM apps | Notes |
|---|---|---|---|
| 18.x | Single -r flag | Needs --import too | module.register() not available |
| 20.6+ | Single -r flag | Single -r flag | Auto-ESM registration |
| 22.x | Single -r flag | Single -r flag | Stable 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:
- dotenv — Loads
.envintoprocess.env(optional, ifdotenvis installed). - ESM detection — Reads the nearest
package.jsonto check"type": "module". - Auto-register — If ESM and Node >=20.6, calls
module.register('@opentelemetry/instrumentation/hook.mjs', ...). If--importis already present inprocess.execArgv, this step is skipped. - 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
| Scenario | Before | After |
|---|---|---|
| CJS app | node -r securenow/register app.js | node -r securenow/register app.js (unchanged) |
| ESM app | node --import @opentelemetry/instrumentation/hook.mjs -r securenow/register app.js | node -r securenow/register app.js |
| ESM + Windows | node --import file:///C:/.../.../hook.mjs -r securenow/register app.js | node -r securenow/register app.js |
| NODE_OPTIONS | NODE_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/nuxtmodule 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
A hands-on walkthrough for adding security observability to a Nuxt 3 app using the securenow npm package and official Nuxt module. Covers installation, nuxt.config.ts setup, environment variables, optional tuning, deployment targets, CLI verification, and troubleshooting.
Apr 2Step-by-step guide to integrating SecureNow into a self-hosted Next.js application on AWS EC2. Covers installation, instrumentation, environment configuration, verifying traces and logs, enabling request body capture, and creating alert rules.
Mar 29
Step-by-step guide to adding security monitoring to your Fastify API with the securenow npm package. Covers CLI setup, instrumentation, body capture caveats, PM2, Docker, and dashboard verification.
Mar 26