---
title: "Nest.js"
description: "Configure Middleware APM for NestJS applications for enhanced monitoring, error tracking, and detailed performance insights."
section: "APM"
breadcrumb: "APM > Nest.JS"
canonical: "https://docs.middleware.io/get-started/apm/nestjs"
---
# Nest.js

Use the Middleware Node.js APM SDK in a NestJS application to collect traces, metrics and application logs from your controllers, providers and database calls. The table shows which data types it collects.

| Traces | Metrics | App Logs | Custom Logs | Profiling |
| --- | --- | --- | --- | --- |
| ✅ | ✅ | ✅ | ✅ | ✅ |

## 1. Prerequisites

Node.js 18.17.1+ and Python 3.9+ (for builds like `node-gyp`). Check with:

```bash
  node --version
python3 --version
```

- Middleware Host Agent on the same machine/cluster (Host mode). In containers, set MW_AGENT_SERVICE so your app can reach the agent:

  - Docker: `MW_AGENT_SERVICE=172.17.0.1`
  - Kubernetes: `MW_AGENT_SERVICE=mw-service.mw-agent-ns.svc.cluster.local`
    (Use this only when the app isn’t on the host network namespace.)

## 2. Install Nest.js APM package

```bash
  npm install @middleware.io/nestjs-apm
```

## 3. Initialise the module (and add the interceptor)

Add the module in `app.module.ts`. Use `serviceName` (and optionally `projectName`).
Then add the global interceptor in `main.ts` so requests/spans are captured.

`app.module.ts:`

```javascript
  import { Module } from '@nestjs/common';
import { MiddlewareApmModule } from '@middleware.io/nestjs-apm';

@Module({
  imports: [
    MiddlewareApmModule.forRoot({
      projectName: 'Your application name',
      serviceName: 'Your service name',
      // You may also set options via env vars (see table below)
    }),
  ],
})
export class AppModule {}
```

`main.ts`

```javascript
  import { NestFactory, Reflector } from '@nestjs/core';
import { AppModule } from './app.module';
import { MiddlewareApmInterceptor } from '@middleware.io/nestjs-apm';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalInterceptors(new MiddlewareApmInterceptor(app.get(Reflector)));
  await app.listen(3000);
}
bootstrap();
```

## 4. Basic Usage

Ignore routes you don’t want traced (e.g., health checks):

```javascript
  import { Controller, Get } from '@nestjs/common';
import { IgnoreApmTrace } from '@middleware.io/nestjs-apm';

@Controller('users')
export class UsersController {
  @IgnoreApmTrace()
  @Get('health')
  healthCheck() {
    return 'OK';
  }
}
```

## 5. Advanced instrumentation

Custom attributes:

```javascript
  import { Controller, Post } from '@nestjs/common';
import { WithAttributes } from '@middleware.io/nestjs-apm';

@Controller('orders')
export class OrdersController {
  @WithAttributes({ 'business.type': 'order', 'business.tier': 'premium' })
  @Post()
  createOrder() {}
}
```

Custom spans:

```javascript
  import { Injectable } from '@nestjs/common';
import { CreateSpan } from '@middleware.io/nestjs-apm';

@Injectable()
export class UserService {
  @CreateSpan('user.registration', { 'user.type': 'new' })
  async registerUser() {}
}
```

Record method params as span attributes:

```javascript
  import { Controller, Post } from '@nestjs/common';
import { RecordParams } from '@middleware.io/nestjs-apm';

@Controller('users')
export class UsersController {
  @RecordParams(['userId', 'action'])
  @Post(':userId/action')
  performAction(userId: string, action: string) {}
}
```

Logging integration (Nest logger is captured automatically):

```javascript
  import { Logger, Injectable } from '@nestjs/common';

@Injectable()
export class UserService {
  private readonly logger = new Logger(UserService.name);
  async createUser() {
    try {
      this.logger.log('Creating new user');
    } catch (e) {
      this.logger.error('Failed to create user', e);
      throw e;
    }
  }
}
```

## 6. Serverless (no Host Agent)

Send directly to Middleware by supplying your tenant target and API key. Put options in `forRoot` (or via env vars).

```javascript
  MiddlewareApmModule.forRoot({
  serviceName: 'Your service',
  projectName: 'Your app',
  accessToken: 'your-initial-token',
  target: 'your-initial-uid',
});
```

(Use secrets manager for keys in production.)

## 7. View your data

Give it 3–5 minutes after starting, then open [APM → Traces](https://app.middleware.io/apm/traces), Logs, and [APM → Continuous Profiling](https://app.middleware.io/apm/profiling) in your Middleware account.

## 8. Environment variables — quick reference

These map 1:1 to `MiddlewareApmModule.forRoot` options (env usually wins).
Values shown are typical; defaults noted where the package defines them.

| Variable | Maps to (forRoot) | Purpose / Default | Example |
| --- | --- | --- | --- |
| `MW_API_KEY` | `accessToken` | Auth token used to export data. No default. | `xxxxxxxx…` |
| `MW_TARGET` | `target` | OTLP endpoint (serverless/remote). Default: `http://localhost:9319` | `https://<MW_UID>.middleware.io:443` |
| `MW_SERVICE_NAME` | `serviceName` | APM service identifier. | `payments-svc` |
| `MW_PROJECT_NAME` | `projectName` | Logical project/app name. | `ShopApp` |
| `MW_CONSOLE_EXPORTER` | `consoleExporter` | Log spans/metrics to console (dev). Default: `false` | `true` |
| `MW_APM_TRACES_ENABLED` | `pauseTraces` | Enable/disable traces. Default: `true` | `true` |
| `MW_APM_METRICS_ENABLED` | `pauseMetrics` | Enable/disable metrics. Default: `true` | `true` |
| `MW_SELF_INSTRUMENTATION` | `enableSelfInstrumentation` | Trace the APM itself. Default: `false` | `false` |
| `MW_FS_INSTRUMENTATION` | `enableFsInstrumentation` | Filesystem tracing (⚠️ perf cost). Default: `false` | `false` |
| `MW_NODE_DISABLED_INSTRUMENTATIONS` | `disabledInstrumentations` | Comma-separated list of instrumentations to disable. | `dns, net` |
| `MW_AGENT_SERVICE` | (Host-agent helper) | Host/Service for agent in containers (Docker/K8s). | `172.17.0.1` / `mw-service.mw-agent-ns.svc.cluster.local` |

(Env → option mappings and defaults come from the package README; `MW_AGENT_SERVICE` comes from the Node APM guidance for container networking.)

## 9. Troubleshooting quick checks

- No traces/logs? Ensure the global interceptor is added (see step 3).
- Container cannot reach Host Agent? Set `MW_AGENT_SERVICE` as per Docker/K8s examples above.
- Local debugging: set `MW_CONSOLE_EXPORTER=true` to echo telemetry to stdout.
