Node.js SDK

Express, NestJS, and any Connect-compatible Node HTTP stack.

@nolax/sdk records request metadata for Connect-compatible Node stacks such as Express and NestJS. Install it and add the middleware.

Package: @nolax/sdk 1.1

Ingest contract: v1.1

Supported frameworks

FrameworkStatus
ExpressSupported
NestJS (Express adapter)Supported
NestJS (Fastify adapter)Supported
Connect-compatible middlewareSupported
Fastify (standalone)Coming soon
HonoComing soon

Install

bash
npm install @nolax/sdk

Express

typescript
import express from 'express'
import { nolax } from '@nolax/sdk'

const app = express()
app.use(nolax({ apiKey: process.env.NOLAX_API_KEY, environment: 'production' }))

NestJS (Express)

Add the middleware in main.ts before app.listen().

typescript
import { NestFactory } from '@nestjs/core'
import { AppModule } from './app.module'
import { nolax } from '@nolax/sdk'

async function bootstrap() {
	const app = await NestFactory.create(AppModule)

	app.use(
		nolax({
			apiKey: process.env.NOLAX_API_KEY,
			environment: 'production',
		}),
	)

	await app.listen(3000)
}
bootstrap()

NestJS (Fastify)

When using the Fastify adapter, forward the raw request/response to the SDK via onRequest.

typescript
import { NestFactory } from '@nestjs/core'
import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify'
import { AppModule } from './app.module'
import { nolax } from '@nolax/sdk'

async function bootstrap() {
	const app = await NestFactory.create<NestFastifyApplication>(AppModule, new FastifyAdapter())

	const middleware = nolax({ apiKey: process.env.NOLAX_API_KEY, environment: 'production' })

	app.getHttpAdapter().getInstance().addHook('onRequest', (req, reply, done) => {
		middleware(req.raw, reply.raw, done)
	})

	await app.listen({ port: 3000 })
}
bootstrap()

Config options

Option names ignore case and underscores, so flushIntervalMs and flush_interval_ms are the same option.

OptionTypeDefaultNotes
apiKeystringrequiredProject API key (nlx_proj_...)
environmentstringrequireddevelopment, staging or production, case-insensitive
endpointstringhttps://server.nolax.net/ingestIngest URL, for local testing
batchSizenumber100Events that trigger a flush
flushIntervalMsnumber2000Milliseconds between timed flushes. Replaces flushInterval
maxQueueSizenumber10000Events held in memory. The oldest are dropped first
maxInFlightnumber4Concurrent sends
releasestringnoneRelease identifier, up to 64 characters
servicestringnoneService name, up to 64 characters
consumerfunctionnoneReturns a consumer identifier for a request, up to 64 characters
captureIpbooleantrueSend the client IP address
captureUserAgentbooleantrueSend the User-Agent header
ipHeaderstringnoneHeader that holds the client IP behind a proxy, for example x-forwarded-for
ignorePathsarray[]Strings or RegExp. Matching requests are never recorded
ignoreMethodsarray[]Methods that are never recorded, for example OPTIONS
beforeSendfunctionnoneChange an event, or return nothing to drop it
dryRunbooleanfalsePrint each batch with the key masked and send nothing. Also NOLAX_DRY_RUN=1
debugbooleanfalseLog flush activity
onErrorfunctionnoneCalled when a batch is dropped

Flushing on shutdown

The SDK flushes queued events when the process emits beforeExit, waiting at most two seconds. It installs no signal handlers. To flush from your own shutdown hook, call flush() on the middleware:

typescript
const middleware = nolax({ apiKey: process.env.NOLAX_API_KEY, environment: 'production' })
app.use(middleware)

process.on('SIGTERM', async () => {
	await middleware.flush()
	process.exit(0)
})

Troubleshooting

  • Routes appear as raw paths such as /users/123: your framework did not expose a route template. Events are still recorded.
  • No events: check NOLAX_API_KEY, endpoint, and that your service can reach the ingest URL. Set dryRun: true to print each batch without sending it.
  • Too much log output: set debug: false, or handle failures with onError.

See also Batching and Retries and What the SDK Sends.