---
title: "Isolate Background Job Scopes"
description: "Learn how to isolate Sentry scopes in NestJS background jobs to prevent breadcrumb leakage into HTTP request events."
url: https://docs.sentry.io/platforms/javascript/guides/nestjs/features/async-context/
---

# Isolate Background Job Scopes for Nest.js

Background jobs need their own isolation scopes to prevent breadcrumbs and tags from leaking into unrelated HTTP request events.

## [Automatic Isolation](https://docs.sentry.io/platforms/javascript/guides/nestjs/features/async-context.md#automatic-isolation)

Sentry automatically forks an isolation scope for each invocation of:

* `@Cron()`, `@Interval()`, and `@Timeout()` handlers from `@nestjs/schedule`
* `@OnEvent()` handlers from `@nestjs/event-emitter`
* The `process()` method of `@Processor()` classes from `@nestjs/bullmq`

These handlers do not need a manual `Sentry.withIsolationScope()` wrapper.

## [Manual Isolation](https://docs.sentry.io/platforms/javascript/guides/nestjs/features/async-context.md#manual-isolation)

For other background tasks, wrap each handler with `Sentry.withIsolationScope()` to give it its own isolated scope.

For example, BullMQ lifecycle event listeners such as `@OnWorkerEvent('completed')` can run outside the isolation scope created for `process()` and need their own wrapper:

```typescript
import * as Sentry from "@sentry/nestjs";
import { OnWorkerEvent, Processor, WorkerHost } from "@nestjs/bullmq";
import { Job } from "bullmq";

@Processor("my-queue")
export class MyProcessor extends WorkerHost {
  async process(job: Job) {
    // Your job processing logic runs in an automatically isolated scope.
  }

  @OnWorkerEvent("completed")
  onCompleted(job: Job) {
    return Sentry.withIsolationScope(() => {
      Sentry.addBreadcrumb({
        message: "Job completed",
        data: { jobId: job.id },
      });
      // Your completion handler logic.
    });
  }
}
```
