# Close a KubeMQ Go Client (/sdks/go/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, batch jobs, test suites) you leak connections until the process is killed.

`client.Close()` drains operations already in flight, then tears down the underlying gRPC transport. Once it returns, the client is in a terminal closed state — every call after that fails fast with `ErrClientClosed` instead of hanging or panicking.

**Gotchas:** the drain window is bounded (`WithDrainTimeout`, default 5 seconds), 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, build a new one; and `defer client.Close()` right after `NewClient` is the safest default so shutdown runs on every exit path, not just the happy one.

## Prerequisites [#prerequisites]

* KubeMQ server running on `localhost:50000`
* Go SDK installed (`go get github.com/kubemq-io/kubemq-go/v2`)

## Code [#code]

```go title="main.go"
// Example: connection/close
//
// Demonstrates how to gracefully close a KubeMQ client connection.
// Close drains in-flight operations before shutting down.
//
// Channel: go-connection.close
// Client ID: go-connection-close-client
//
// Run with a KubeMQ server on localhost:50000
// (see https://docs.kubemq.io/deploy).
package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/kubemq-io/kubemq-go/v2"
)

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	client, err := kubemq.NewClient(ctx,
		kubemq.WithAddress("localhost", 50000),
		kubemq.WithClientId("go-connection-close-client"),
	)
	if err != nil {
		log.Fatal(err)
	}

	// Verify connectivity before closing.
	info, err := client.Ping(ctx)
	if err != nil {
		log.Fatalf("Ping failed: %v", err)
	}
	fmt.Printf("Connected: host=%s version=%s\n", info.Host, info.Version)

	// Close the client gracefully, draining in-flight operations.
	if err := client.Close(); err != nil {
		log.Fatalf("Close failed: %v", err)
	}
	fmt.Println("Client closed successfully")
}

```

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

1. `client.Close()` sends a graceful shutdown signal to the broker, drains any in-flight operations, and closes the underlying gRPC transport.
2. After `Close` returns, any subsequent method call on the client returns an `ErrClientClosed` error — no panics, just a stable closed state.
3. The example calls `Ping` first to confirm the connection is live before demonstrating the close; in real code, `defer client.Close()` handles shutdown unconditionally.
4. If you need a drain budget, configure `WithDrainTimeout(d)` at construction time; the default is 5 seconds.

## Related [#related]

* [Go SDK Reference](/sdks/go/reference)
* [Connect](/sdks/go/tutorials/connect)
* [Ping](/sdks/go/how-to/connection/ping)
