Elastic APM can automatically instrument supported Node.js frameworks and libraries, collect transactions, spans, errors, and metrics, and send them to an Elastic Observability deployment. The key implementation detail is initialization order: the APM agent must start before modules such as Express are loaded if you want automatic instrumentation to work correctly.
This tutorial deliberately uses the native elastic-apm-node agent. Elastic now encourages users to consider the Elastic Distribution of OpenTelemetry (EDOT) for some new observability deployments, but the native agent remains documented and supported. Keeping the scope explicit prevents the setup from mixing two different instrumentation approaches.
Last verified: September 10, 2026. npm lists elastic-apm-node 4.18.0 as the current latest release. Recheck the package and Elastic supported-technologies page before applying a pinned version later.
What You'll Accomplish
You will:
- install the current native Elastic APM Node.js agent;
- configure service identity and APM connectivity without hard-coding secrets;
- start the agent before Express or other instrumented modules;
- generate normal traffic and a controlled error;
- verify the service, transactions, and errors in Elastic; and
- diagnose initialization, authentication, TLS, ESM, and framework-compatibility problems.
Prerequisites
You need:
- an Elastic deployment with APM ingestion available;
- a supported Node.js runtime;
- a simple Node/Express application;
- npm access;
- the APM Server/Elastic endpoint and any token or secret required by your deployment;
- permission to change the application's startup/configuration.
Elastic's current support page says agent 4.x supports Node.js 14.17.0 and later, while support follows Node's lifecycle. In production, use an actively supported Node LTS rather than choosing an end-of-life runtime simply because the agent can technically run on it.
Quick Answer
Install the agent with npm install --save elastic-apm-node. Start it before requiring or importing Express and other instrumented modules. For CommonJS, put require('elastic-apm-node').start() at the very top of the entry point or use elastic-apm-node/start with environment-variable configuration. Configure values such as service name, server URL, environment, and secret/token through environment or deployment configuration. Start the application, send test requests, trigger one controlled error, and verify fresh transactions and errors in Elastic. If data is missing, check initialization order first, then connectivity/authentication, supported framework versions, and ESM/transpiler behavior.
Step 1: Install the Native Node.js Agent
Install the package:
npm install --save elastic-apm-node
For a reproducible lab tied to this verification date:
npm install --save [email protected]
A pinned version makes the procedure reproducible, but it should not become a permanent upgrade policy. Recheck the current release and security/support status before deployment.
Step 2: Configure the Connection Outside Source Code
Prefer environment variables or your deployment platform's protected configuration.
A representative set is:
export ELASTIC_APM_SERVICE_NAME="checkout-api"
export ELASTIC_APM_SERVER_URL="https://<YOUR_APM_ENDPOINT>"
export ELASTIC_APM_ENVIRONMENT="staging"
If your deployment requires a secret token or API key, configure it through the appropriate current Elastic variable or secret-management mechanism rather than placing it in source code.
Do not publish real credentials in examples, screenshots, CI output, or public repositories.
Elastic documents configuration precedence with central configuration ahead of environment variables, then explicit start() options, then configuration-file values. Know which layer owns each production setting so a central override does not surprise application operators.
Step 3: Start the Agent Before Express
For CommonJS, the direct documented pattern is:
const apm = require("elastic-apm-node").start();
const express = require("express");
The order matters.
Elastic's agent instruments supported modules by intercepting them as they load. If Express, http, a database client, or another supported library loads first, the agent may miss automatic instrumentation.
Another environment-driven startup pattern is:
require("elastic-apm-node/start");
const express = require("express");
This works well when all agent configuration is provided outside the application.
Step 4: Create a Minimal Express Route
A small test route gives you deterministic traffic:
const express = require("express");
const app = express();
app.get("/hello", (req, res) => {
res.json({ ok: true });
});
app.listen(3000, () => {
console.log("Listening on http://localhost:3000");
});
Generate requests:
for i in 1 2 3 4 5; do
curl -s http://localhost:3000/hello > /dev/null
done
The goal is not load testing. It is to create several transactions that should be visible after ingestion.
Step 5: Add One Controlled Error
Add a temporary test route in development/staging:
app.get("/apm-test-error", (req, res) => {
throw new Error("Elastic APM verification error");
});
Then request it once:
curl -i http://localhost:3000/apm-test-error
How Express handles the uncaught route error depends on application error middleware and framework behavior, but Elastic APM is intended to capture supported errors.
Remove or protect the route after verification. A public endpoint that creates errors on demand can be abused and pollute telemetry.
Step 6: Verify the Service in Elastic
Open the APM/Services experience in your Elastic deployment and locate the service name you configured.
Confirm:
- the service exists;
- transaction timestamps are current;
- the
/helloroute or corresponding transaction is visible; - latency looks plausible;
- the controlled error appears;
- environment metadata is correct.
A service entity appearing without fresh transactions is not enough. Confirm recent data generated by your test.
Step 7: Understand ESM and Transpiler Constraints
This is one of the areas most likely to become stale.
Elastic currently describes ESM instrumentation support as limited/experimental for the Node agent. The support page also notes that TypeScript or JavaScript compiled to CommonJS can be instrumented using CommonJS-compatible output.
If your application uses native ESM, do not force a CommonJS tutorial command into production. Read the current ESM documentation for the exact agent/runtime combination.
If you use TypeScript transpiled to CommonJS, initialization still needs to occur before the compiled application imports the modules to be instrumented.
The practical troubleshooting rule is:
if manual agent API calls work but framework/database spans are absent, recheck startup order and module format.
Verify the Setup
Consider APM ready only when:
- the intended current agent version is installed;
- secrets are stored outside source code;
- service/environment identity is correct;
- the agent starts before supported application modules;
- fresh application transactions are visible;
- a controlled error is visible;
- timestamps correspond to your verification requests; and
- no unsupported runtime/framework assumption is hiding missing spans.
This tutorial provides a documented procedure; it does not claim PerfMonitoring executed it in your Elastic environment.
Common Problems and Fixes
Problem: The service never appears
Likely causes: wrong APM endpoint, authentication failure, TLS/network egress issue, or the agent never started.
Fix: inspect application startup logs and Elastic agent diagnostics. Confirm the endpoint from the deployment and test network reachability without printing credentials.
Problem: The service appears but Express transactions are missing
Likely cause: Express loaded before the APM agent.
Fix: move agent startup to the very top of the first loaded application file or use the documented preload/start module.
Problem: Some database spans are missing
Likely cause: unsupported library/version or import happened before agent initialization.
Fix: compare the exact package version with Elastic's current supported-technologies table. Do not assume all client libraries are automatically instrumented.
Problem: ESM application has incomplete instrumentation
Likely cause: native ESM support has different limitations than CommonJS.
Fix: consult the current Elastic ESM guidance and supported-technologies page. Avoid presenting an older CommonJS workaround as universal.
Problem: The agent can connect in development but not production
Likely cause: production proxy, firewall, certificate chain, or credential differences.
Fix: compare environment configuration and outbound connectivity. Fix trust/network configuration rather than disabling TLS verification globally.
Problem: Sensitive information appears in telemetry
Likely cause: application context or request capture includes data that should not leave the service.
Fix: review current Elastic agent sanitization/capture settings and minimize collected context.
Best Practices
Keep service names stable
Use a predictable service identity across deployments so dashboards and traces aggregate correctly.
Separate environment from service identity
checkout-api can exist in staging and production. Environment should distinguish them rather than creating arbitrary service names such as checkout-api-prod-2026-09-10.
Start early and once
Centralize agent initialization and make the startup contract explicit in the project.
Review supported technologies during upgrades
Framework and database-client support changes. Revalidate before upgrading a major runtime or dependency.
Consider EDOT deliberately, not accidentally
Elastic's current documentation suggests considering EDOT/OpenTelemetry for observability data. If you choose that architecture, follow the OpenTelemetry/EDOT path intentionally instead of running overlapping instrumentation without design.
When This Setup Makes Sense
The native Elastic APM Node.js agent makes sense when:
- Elastic is your primary observability backend;
- you want supported automatic instrumentation;
- the application/framework is compatible with the agent;
- you prefer Elastic-native setup and central configuration.
A vendor-neutral OpenTelemetry pipeline may be preferable when telemetry must feed multiple backends or when your organization standardizes on OpenTelemetry instrumentation.
FAQ
Does the Elastic APM agent need to start before Express?
Yes. Current Elastic documentation explicitly says the agent must start before modules it needs to instrument.
Which version was verified for this tutorial?
elastic-apm-node 4.18.0 was the npm latest version on September 10, 2026.
Does Elastic recommend OpenTelemetry now?
Elastic's current Node agent documentation says to consider EDOT/OpenTelemetry. That does not make the native agent invalid; it means architecture choice should be deliberate.
Why does my service appear but have missing spans?
Check initialization order, supported library versions, module format/ESM behavior, and whether the expected code path actually ran.
Conclusion
Elastic APM setup succeeds or fails mainly on initialization order and connectivity. Install the current native agent, keep credentials outside source, start it before application modules, generate deterministic traffic, and verify both transactions and an error.
Do not hide version-sensitive ESM or framework behavior. Record a Last verified date and recheck support tables whenever Node.js, the agent, or major framework dependencies change.
References
- Elastic Docs — "Starting the agent | APM Node.js agent" — https://www.elastic.co/docs/reference/apm/agents/nodejs/starting-agent — accessed September 10, 2026.
- Elastic Docs — "Get started with Express | APM Node.js agent" — https://www.elastic.co/docs/reference/apm/agents/nodejs/express — accessed September 10, 2026.
- Elastic Docs — "Supported technologies | APM Node.js agent" — https://www.elastic.co/docs/reference/apm/agents/nodejs/supported-technologies — accessed September 10, 2026.
- Elastic Docs — "Configuring the agent | APM Node.js agent" — https://www.elastic.co/docs/reference/apm/agents/nodejs/configuring-agent — accessed September 10, 2026.
- npm — "elastic-apm-node" — Elastic — https://www.npmjs.com/package/elastic-apm-node — accessed September 10, 2026.