Node.js
Instrument your Node.js services with the Incidentary SDK.
Node.js Quickstart
This guide gets you from zero to your first captured trace in a Node.js service.
Prerequisites
- Node.js 20+
- An Incidentary workspace and API key (from the dashboard under Settings → API Keys)
Install
npm install @incidentary/sdk-nodeInitialize the client
import { IncidentaryClient, createExpressMiddleware } from '@incidentary/sdk-node';
const incidentary = new IncidentaryClient({
apiKey: process.env.INCIDENTARY_API_KEY!,
serviceName: 'my-service',
});That's the core setup. The SDK automatically instruments outbound HTTP calls (http, https, and fetch()), supported queue libraries, databases, and gRPC — no additional code needed.
Mount inbound middleware
Pick your framework:
Express
app.use(createExpressMiddleware(incidentary));Fastify
import { FastifyIntegration } from '@incidentary/sdk-node';
const fastifyIntegration = new FastifyIntegration();
fastifyIntegration.patch(incidentary);
fastify.register(fastifyIntegration.plugin());Koa
import { KoaIntegration } from '@incidentary/sdk-node';
const koaIntegration = new KoaIntegration();
koaIntegration.patch(incidentary);
app.use(koaIntegration.middleware());Hapi
import { HapiIntegration } from '@incidentary/sdk-node';
const hapiIntegration = new HapiIntegration();
hapiIntegration.patch(incidentary);
await server.register(hapiIntegration.plugin());The middleware captures every inbound HTTP request automatically. It writes to an in-memory buffer and flushes to Incidentary in the background. Your request handling is not affected.
Outbound HTTP — automatic
The SDK patches http.request, https.request, and fetch() at initialization. Every outbound HTTP call from your service automatically gets x-incidentary-trace-id and x-incidentary-parent-ce headers injected. This works with any HTTP client — axios, got, node-fetch, undici, or plain http.request.
No code changes needed. If you already use OpenTelemetry's HTTP instrumentation, the SDK detects it and skips its own patching to avoid conflicts.
Queue instrumentation — automatic
If your service uses any of these queue libraries, the SDK auto-patches them at startup:
| Library | Producer | Consumer |
|---|---|---|
| BullMQ | Queue.add / addBulk | Worker processor |
| amqplib | Channel.publish / sendToQueue | Channel.consume callback |
| kafkajs | Producer.send / sendBatch | Consumer.run eachMessage |
Context flows automatically: the producer injects trace context into the message, the consumer extracts it, and all downstream calls from the consumer inherit the trace.
Database instrumentation — automatic
| Library | What's captured |
|---|---|
| pg | Client.prototype.query — SQL text (truncated, no parameters) |
| ioredis | Redis.prototype.sendCommand — command name only (no values) |
Database events appear as INTERNAL context events in the trace, helping you see what queries ran during an incident.
gRPC support
import { GrpcIntegration } from '@incidentary/sdk-node';
const grpcIntegration = new GrpcIntegration();
grpcIntegration.patch(incidentary);
// Client-side: add interceptor to inject trace context
const channel = new grpc.Client(addr, creds, {
interceptors: [grpcIntegration.clientInterceptor()],
});
// Server-side: add middleware
server.addService(serviceDefinition, implementation);
// Use grpcIntegration.serverMiddleware() in your call handlingRecording custom events
Queue, job, and webhook events can also be recorded manually when auto-instrumentation doesn't cover your use case:
incidentary.recordQueuePublish({ eventAttrs: { topic: 'orders.created' } });
incidentary.recordQueueConsume();
incidentary.recordJobStart({ eventAttrs: { worker: 'invoice-sync' } });
incidentary.recordJobEnd();
incidentary.recordWebhookIn();
incidentary.recordWebhookOut({ status: 202 });Environment variables
| Variable | Required | Default | Description |
|---|---|---|---|
INCIDENTARY_API_KEY | Yes | — | Workspace API key (sk_...) from the dashboard |
INCIDENTARY_SERVICE_NAME | No | — | Alternative to passing serviceName in code |
INCIDENTARY_ENVIRONMENT | No | production | Environment label (production, staging, etc.) |
INCIDENTARY_API_URL | No | https://api.incidentary.com | Override for self-hosted or local dev |
Verify capture
After deploying with the SDK installed:
- Make a request to your service
- Open the Incidentary dashboard → Traces
- A trace should appear within a few seconds
If no trace appears within 30 seconds, see the troubleshooting section below.
What happens during an incident
When an alert fires (via Slack, PagerDuty, or OpsGenie), Incidentary assembles the causal chain from events your service has already captured. The SDK continuously maintains a rolling window of recent activity — events from before the alert fired are included in the assembled artifact.
The SDK does not create incidents or page anyone. It is passive until an alert arrives.
Troubleshooting
401 Unauthorized on ingest: You are using a user session token, not a workspace API key. API keys start with sk_ and are found in Settings → API Keys.
No traces in the dashboard: Ensure your process calls flushToBackend() after requests. In serverless environments, you may need to call this explicitly at the end of each invocation.
426 SDK_VERSION_TOO_OLD: Upgrade to @incidentary/sdk-node@0.2.0 or newer.
Services not linked: You are not propagating the x-incidentary-trace-id and x-incidentary-parent-ce headers on outbound calls. See the outbound propagation section above.