NestJS
NestJS
Scout supports NestJS 10.x+.
1. Install the @scout_apm/scout-apm package:
yarn add @scout_apm/scout-apm
2. Create a scout.ts file and require it before NestJS loads:
// scout.ts
const { init } = require("@scout_apm/scout-apm");
init({
name: process.env.SCOUT_NAME || "my-nestjs-app",
key: process.env.SCOUT_KEY,
monitor: true,
});
// main.ts
import "reflect-metadata"; // safe — no instrumented packages
require("./scout"); // must come before NestJS loads
const { NestFactory } = require("@nestjs/core");
const { AppModule } = require("./app.module");
const { nestMiddleware, nestErrorFilter } = require("@scout_apm/scout-apm");
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use(nestMiddleware({ requestTimeoutMs: 0 }));
app.useGlobalFilters(nestErrorFilter());
await app.listen(3000);
}
bootstrap();
3. Configure Scout via ENV variables:
export SCOUT_MONITOR=true
export SCOUT_KEY="[AVAILABLE IN THE SCOUT UI]"
export SCOUT_NAME="A FRIENDLY NAME FOR YOUR APP"
If you’ve installed Scout via the Heroku Addon, the provisioning process automatically sets SCOUT_MONITOR and SCOUT_KEY via config vars. Only SCOUT_NAME is required.
4. Deploy.
It takes just a few minutes for your data to first appear within the Scout UI.
Pipeline Instrumentation
Scout automatically creates a sibling span for each guard, pipe, and interceptor under the route’s Controller/{METHOD} {path} span — no code changes required:
@Controller()
class OrdersController {
@Get("/orders/:id")
@UseGuards(AuthGuard)
@UseInterceptors(TimingInterceptor)
getOrder(@Param("id") id: string) { /* ... */ }
}
produces:
Controller/GET /orders/:id
├── NestJS/Guards/AuthGuard
├── NestJS/Interceptors/TimingInterceptor
└── ...route handler...
| Span | Appears when | Name |
|---|---|---|
NestJS/Guards/{Name} |
Route has one or more guards | Guard class name(s), comma-joined if more than one |
NestJS/Pipes/{Name} |
Route has one or more pipes | Pipe class name(s) |
NestJS/Interceptors/{Name} |
Route has one or more interceptors | Interceptor class name(s) |
Unresolvable class names fall back to a generic Guard/Pipe/Interceptor. The interceptor span ends at the next.handle() handoff, so it covers pre-handler work only, not the route handler itself.
Scheduled Jobs (@nestjs/schedule)
@Cron, @Interval, and @Timeout jobs from @nestjs/schedule are each wrapped in their own transaction automatically — no manual BackgroundTransaction needed:
| Operation | Trigger |
|---|---|
NestJS/Schedule/Cron/{jobName} |
@Cron() decorated method fires |
NestJS/Schedule/Interval/{jobName} |
@Interval() decorated method fires |
NestJS/Schedule/Timeout/{jobName} |
@Timeout() decorated method fires |
{jobName} is the method name or explicit decorator name.
Supported Versions
Tested against NestJS 10.x. No runtime version check gates this.