# Close a KubeMQ Node.js Client (/sdks/nodejs/how-to/connection/close)



## Overview [#overview]

Closing a client isn't an afterthought — it tells the broker and your own process that this connection is done, so both sides release what they were holding for it. A KubeMQ client is more than a socket: it's a gRPC channel plus whatever subscriptions and in-flight sends it's servicing. Skip the close and those linger — subscriptions keep streaming, the channel stays open — and in short-lived processes (CLI tools, serverless handlers, test suites) you leak connections until the process is killed.

Awaiting `client.close()` flushes in-flight gRPC calls, cancels active subscriptions, and only then releases the underlying channel. Once it returns, the client transitions to a terminal `Closed` state — every call after that fails fast with `ClientClosedError`.

**Gotchas:** the drain window is bounded (`{ timeoutSeconds, callbackTimeoutSeconds }`, unbounded by default), not unlimited, so a slow consumer can still lose the tail of a burst if you close mid-stream; a closed client is dead forever — no reconnect on the same instance, construct a new one; and `close()` belongs in a `finally` block, not just after the last call, so shutdown runs on every exit path, including thrown errors.

## Prerequisites [#prerequisites]

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

## Code [#code]

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

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

  try {
    await client.sendEvent(
      createEventMessage({ channel: 'js-connection.close', body: 'hello before close' }),
    );
    console.log('Event sent successfully');
  } finally {
    await client.close();
    console.log('Client closed gracefully');
  }
}

main().catch(console.error);

```

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

* `client.close()` is always called in the `finally` block — this flushes in-flight gRPC calls, cancels all active subscriptions, and releases the underlying channel.
* The `try/finally` pattern ensures the client is closed even if `sendEvent()` throws, preventing gRPC connection leaks in long-running processes.
* `close()` accepts an optional `{ timeoutSeconds, callbackTimeoutSeconds }` object to bound drain time in shutdown-critical paths; the default waits indefinitely.
* After `close()` the client state transitions to `Closed`; any further operation on the same instance throws `ClientClosedError`.

## Related [#related]

* [Node.js SDK Reference](/sdks/nodejs/reference)
* [Connect](/sdks/nodejs/tutorials/connect)
* [Ping](/sdks/nodejs/how-to/connection/ping)
