# Cancel Subscription (/sdks/nodejs/how-to/events/cancel-subscription)



## Overview [#overview]

A live Events subscription holds a client-side stream open indefinitely, so a long-running service needs an explicit way to tear one down without closing the whole client connection — for example when a feature flag disables a channel, a worker is draining before shutdown, or a subscription needs to be re-created with different options. Calling `cancel()` on the handle returned by `subscribeToEvents()` stops delivery cleanly and frees those resources on both sides.

`subscribeToEvents()` returns a handle immediately and invokes your `onEvent` callback for each message as it arrives, so the subscription runs in the background until you cancel it. `cancel()` stops delivery right away, and because it's idempotent, it's safe to call from inside the `onEvent` callback itself — a common pattern for stopping mid-stream once some condition is met, as opposed to only cancelling from outside code.

**Gotchas:** `cancel()` only affects this one handle — other subscribers on the same channel keep receiving events. Events already in flight when you call it may still be delivered, since publish and cancel race independently. And because Events are fire-and-forget, anything published after cancellation is simply dropped for this subscriber — there's no queue to catch up from later.

## Prerequisites [#prerequisites]

* KubeMQ server running on `localhost:50000`
* Node.js SDK installed (`npm install kubemq-js`)

## Code [#code]

```typescript title="cancel-subscription.ts"
import { KubeMQClient, createEventMessage } from 'kubemq-js';

async function main() {
  const client = await KubeMQClient.create({
    address: 'localhost:50000',
    clientId: 'js-events-cancel-subscription-client',
  });

  try {
    let received = 0;
    const sub = client.subscribeToEvents({
      channel: 'js-events.cancel-subscription',
      onEvent: (event) => {
        received++;
        console.log(`Received #${received}:`, new TextDecoder().decode(event.body));
        if (received >= 3) sub.cancel();
      },
      onError: (err) => {
        console.error('Error:', err.message);
      },
    });

    for (let i = 1; i <= 5; i++) {
      await client.sendEvent(
        createEventMessage({ channel: 'js-events.cancel-subscription', body: `msg-${i}` }),
      );
    }

    await new Promise((r) => setTimeout(r, 1000));
    console.log('Total received before cancel:', received);
  } finally {
    await client.close();
  }
}

main().catch(console.error);

```

## How It Works [#how-it-works]

* `subscribeToEvents()` returns a handle whose `cancel()` method stops delivery immediately.
* The `onEvent` callback increments a counter and calls `sub.cancel()` once 3 messages are received — demonstrating mid-stream cancellation from inside the callback itself.
* The 5 published messages race against the cancellation; only the first 3 are delivered.
* The subscription object (`sub`) is captured by closure in the callback, which is safe because `cancel()` is idempotent.

## Related [#related]

* [Pattern overview](/learn/events/getting-started)
* [Node.js SDK Reference](/sdks/nodejs/reference)
* [Basic Pub/Sub](/sdks/nodejs/tutorials/basic-pubsub)
* [Consumer Group](/sdks/nodejs/how-to/events/consumer-group)
