ESM without CLI Flag

Learn about running Sentry in an ESM application, without the --import flag.

When running your application in ESM mode, you will most likely want to follow the ESM instructions. However, if you can't use the --import command line option, you can either use direct imports or SEA bootstrap setup if you are using a Node.js Single Executable Application (SEA).

You need to create a file named instrument.mjs that imports and initializes Sentry:

instrument.mjs
Copied
import * as Sentry from "@sentry/node";

// Ensure to call this before importing any other modules!
Sentry.init({
  dsn: "___PUBLIC_DSN___",

  // Add Tracing by setting tracesSampleRate
  // We recommend adjusting this value in production
  tracesSampleRate: 1.0,
});

You need to import the instrument.mjs file before importing any other modules in your application. This is necessary to ensure that Sentry can automatically instrument all modules in your application:

app.mjs
Copied
// Import this first!
import "./instrument";

// Now import other modules
import http from "http";

// Your application code goes here

Node.js Single Executable Applications (SEA) may not load your Sentry instrumentation early enough, so you need to package a small bootstrap file as the SEA main instead of packaging your app entrypoint directly.

The embedded SEA main should only load a filesystem bootstrap file next to the executable:

sea-main.cjs
Copied
const { createRequire } = require("node:module");

createRequire(__filename)("./sea-bootstrap.cjs");

The filesystem bootstrap imports Sentry first, then imports your real app entrypoint:

sea-bootstrap.cjs
Copied
async function startApp() {
  await import("./instrument.mjs");
  await import("./app.mjs");
}

startApp();

Keep your Sentry setup in instrument.mjs:

instrument.mjs
Copied
import * as Sentry from "@sentry/node";

Sentry.init({
  dsn: "___PUBLIC_DSN___",
  tracesSampleRate: 1.0,
});

Then configure SEA to use sea-main.cjs as its main script:

sea-config.json
Copied
{
  "main": "sea-main.cjs",
  "output": "sea-prep.blob",
  "disableExperimentalSEAWarning": true,
  "useSnapshot": false
}

Keep sea-bootstrap.cjs, instrument.mjs, and app.mjs available on the filesystem next to the executable.

This setup lets the Sentry SDK register ESM instrumentation hooks before your application imports instrumented modules, such as Express or database clients. Your instrumentation file and app entrypoint can stay ESM. The verified bootstrap pattern shown here uses CommonJS only for the small SEA entry files.

Node.js SEA support is still evolving, including how embedded ESM entrypoints and module loading are configured. The embedded SEA main may not be able to load filesystem modules with import() directly, so the example above uses module.createRequire() to bridge from the embedded main to a normal filesystem bootstrap. The important requirement is startup order: load Sentry before loading the application modules you want Sentry to instrument.

Was this helpful?
Help improve this content
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").