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
| Framework | Status |
|---|---|
| Express | Supported |
| NestJS (Express adapter) | Supported |
| NestJS (Fastify adapter) | Supported |
| Connect-compatible middleware | Supported |
| Fastify (standalone) | Coming soon |
| Hono | Coming 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.
| Option | Type | Default | Notes |
|---|---|---|---|
| apiKey | string | required | Project API key (nlx_proj_...) |
| environment | string | required | development, staging or production, case-insensitive |
| endpoint | string | https://server.nolax.net/ingest | Ingest URL, for local testing |
| batchSize | number | 100 | Events that trigger a flush |
| flushIntervalMs | number | 2000 | Milliseconds between timed flushes. Replaces flushInterval |
| maxQueueSize | number | 10000 | Events held in memory. The oldest are dropped first |
| maxInFlight | number | 4 | Concurrent sends |
| release | string | none | Release identifier, up to 64 characters |
| service | string | none | Service name, up to 64 characters |
| consumer | function | none | Returns a consumer identifier for a request, up to 64 characters |
| captureIp | boolean | true | Send the client IP address |
| captureUserAgent | boolean | true | Send the User-Agent header |
| ipHeader | string | none | Header that holds the client IP behind a proxy, for example x-forwarded-for |
| ignorePaths | array | [] | Strings or RegExp. Matching requests are never recorded |
| ignoreMethods | array | [] | Methods that are never recorded, for example OPTIONS |
| beforeSend | function | none | Change an event, or return nothing to drop it |
| dryRun | boolean | false | Print each batch with the key masked and send nothing. Also NOLAX_DRY_RUN=1 |
| debug | boolean | false | Log flush activity |
| onError | function | none | Called 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. SetdryRun: trueto print each batch without sending it. - Too much log output: set
debug: false, or handle failures withonError.
See also Batching and Retries and What the SDK Sends.

