# Command Group (/sdks/go/how-to/rpc/command-group)



## Overview [#overview]

A command **consumer group** turns a single command handler into a scalable worker pool: run multiple identical instances subscribed with the same group name, and the broker load-balances each incoming command to exactly one member instead of broadcasting it to all of them. This is how you add capacity to handle a growing command volume — start more workers in the same group — without changing anything on the caller's side.

Every subscriber passes the same `group` alongside the `channel` to `SubscribeToCommands`; the broker tracks membership and picks one live member per command. `SendCommand` on the caller side is unaware groups exist — it just blocks for a `CommandReply`, which comes back from whichever worker happened to handle it.

**Gotchas:** group membership is scoped per channel — subscribers on the same channel with *different* group names each get their own full copy of every command (fan-out), which looks like a bug when you expected load-balancing. A slow handler still holds up the caller's timeout, since only one worker is ever picked. And if every member of the group is offline when a command arrives, the send simply fails or times out — commands aren't queued or replayed for a group that has no active listener.

## 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: commands/consumer-group
//
// Demonstrates load-balanced command handling with consumer groups.
// Multiple handlers in the same group share the command workload,
// with each command delivered to exactly one handler.
//
// Channel: go-commands.consumer-group
// Client ID: go-commands-consumer-group-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(), 30*time.Second)
	defer cancel()

	client, err := kubemq.NewClient(ctx,
		kubemq.WithAddress("localhost", 50000),
		kubemq.WithClientId("go-commands-consumer-group-client"),
	)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	channel := "go-commands.consumer-group"
	group := "go-commands-worker-group"
	done := make(chan struct{})

	// Subscribe with a consumer group for load-balanced command handling.
	sub, err := client.SubscribeToCommands(ctx, channel, group,
		kubemq.WithOnCommandReceive(func(cmd *kubemq.CommandReceive) {
			fmt.Printf("Worker received: body=%s\n", cmd.Body)
			resp := kubemq.NewCommandReply().
				SetRequestId(cmd.Id).
				SetResponseTo(cmd.ResponseTo).
				SetExecutedAt(time.Now())
			_ = client.SendCommandResponse(ctx, resp)
			close(done)
		}),
		kubemq.WithOnError(func(err error) {
			log.Println("Group error:", err)
		}),
	)
	if err != nil {
		log.Fatal(err)
	}
	defer sub.Unsubscribe()
	time.Sleep(300 * time.Millisecond)

	// Send a command to the group.
	cmdResp, err := client.SendCommand(ctx, kubemq.NewCommand().
		SetChannel(channel).
		SetBody([]byte("group-task")).
		SetTimeout(10*time.Second))
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Group response: executed=%v\n", cmdResp.Executed)

	<-done
}

```

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

1. `client.SubscribeToCommands(ctx, channel, group, opts...)` passes `group := "go-commands-worker-group"`, activating load-balanced command delivery across all subscribers in the group.
2. The broker routes each command to exactly one member of the group rather than broadcasting — when multiple worker instances subscribe with the same `channel` and `group`, the workload is shared.
3. `client.SendCommand` blocks until one group member sends back a `CommandReply`; the caller does not need to know which specific worker handled the command.
4. `defer sub.Unsubscribe()` cleanly removes this subscriber from the group; the broker will route subsequent commands to the remaining active members.

## Related [#related]

* [Pattern overview](/learn/rpc/getting-started)
* [Go SDK Reference](/sdks/go/reference)
* [Send Command](/sdks/go/tutorials/command-send)
* [Handle Command](/sdks/go/how-to/rpc/command-handle)
