# Configuration (/integrations/masstransit/how-to/configuration)



Every MassTransit.KubeMQ application configures the transport in one place: the `UsingKubeMQ` (or `AddKubeMQRider`) callback inside `AddMassTransit`. The connection settings — host, port, authentication, TLS, and poll behavior — are modeled by a single configuration POCO, `KubeMQTransportOptions`, which you can set in code, parse from a `kubemq://` URI, or bind from `appsettings.json`. This page walks through every option and the three ways to supply it.

Before you connect, start a broker with the gRPC port exposed:

<RunKubeMQ ports="[50000, 9090]" />

Port `50000` is the gRPC port the transport connects to. Port `9090` is the shared HTTP server that hosts the REST, CloudEvents, MCP, and A2A connectors — it is not used by the transport itself.

## Prerequisites [#prerequisites]

* The `MassTransit.KubeMQ` package installed (`dotnet add package MassTransit.KubeMQ`) in a MassTransit `>= 8.5.0` project targeting `net8.0`
* The broker above running and reachable

## Transport Options [#transport-options]

`KubeMQTransportOptions` is the central configuration class. It is bindable to `IOptions<T>` and `appsettings.json`, and the same property names appear on the host configurator (`h.AuthToken`, `h.UseTls`, and so on). The table below lists every property with its default and validation range.

<TypeTable
  type="{
  Host: {
    type: 'string',
    default: '&#x22;localhost&#x22;',
    description: 'KubeMQ server hostname. Must be non-empty.',
  },
  Port: {
    type: 'int',
    default: '50000',
    description: 'KubeMQ gRPC port. Must be between 1 and 65535.',
  },
  ClientId: {
    type: 'string?',
    default: 'null',
    description: 'Client identifier for this connection. Auto-generated if not set.',
  },
  AuthToken: {
    type: 'string?',
    default: 'null',
    description: 'Authentication token presented to the broker.',
  },
  UseTls: {
    type: 'bool',
    default: 'false',
    description: 'Enable TLS encryption for the gRPC channel.',
  },
  TlsCertFile: {
    type: 'string?',
    default: 'null',
    description: 'TLS client certificate file path (PEM). Required when TLS is enabled.',
  },
  TlsKeyFile: {
    type: 'string?',
    default: 'null',
    description: 'TLS client private key file path (PEM). Used for mutual TLS.',
  },
  TlsCaFile: {
    type: 'string?',
    default: 'null',
    description: 'TLS CA certificate file path (PEM). Used for mutual TLS.',
  },
  PollTimeoutSeconds: {
    type: 'int',
    default: '5',
    description: 'Queue long-poll wait timeout in seconds. Must be between 1 and 3600.',
  },
  MaxPollMessages: {
    type: 'int',
    default: '32',
    description: 'Maximum messages per poll batch. Must be between 1 and 1024.',
  },
  DefaultCqMode: {
    type: 'CqMode',
    default: 'Queries',
    description: 'Global CQ mode for request/response (Queries or Commands).',
  },
  ConnectionTimeout: {
    type: 'TimeSpan',
    default: '10s',
    description: 'Initial connection timeout. Must be positive.',
  },
  ReconnectTimeout: {
    type: 'TimeSpan',
    default: '60s',
    description: 'Reconnection wait timeout. Must be positive.',
  },
}"
/>

## Host and Port (Recommended) [#host-and-port-recommended]

The simplest and recommended way to point the transport at a broker is `cfg.Host(host, port)` — the `Host` method on `IKubeMQBusFactoryConfigurator`. The port defaults to `50000`, so for a local broker you can omit it entirely.

```csharp title="Program.cs"
services.AddMassTransit(x =>
{
    x.UsingKubeMQ((ctx, cfg) =>
    {
        cfg.Host("kubemq-server.example.com", 50000);

        cfg.ReceiveEndpoint("config-options-queue", e =>
        {
            e.ConfigureKubeMQ(t => { });
        });
    });
});
```

The KubeMQ transport does **not** support MassTransit's `cfg.ConfigureEndpoints(ctx)` auto-configuration — calling it throws `KubeMQTransportConfigurationException` at bus startup (see [Error Handling & DLQ](/integrations/masstransit/how-to/error-handling-dlq) for the full exception model). Declare every receive endpoint explicitly with `cfg.ReceiveEndpoint("channel-name", e => { ... })`, one per channel your consumers read from, as shown above and throughout this guide.

## URI-Based Host [#uri-based-host]

`Host` has a second overload that takes a `Uri`. Use the `kubemq://` scheme, and pass connection options as query parameters. This form is handy when the connection string comes from configuration or an environment variable.

```csharp title="Program.cs"
services.AddMassTransit(x =>
{
    x.UsingKubeMQ((ctx, cfg) =>
    {
        cfg.Host(new Uri("kubemq://kubemq-server:50000?authToken=my-token&tls=true"));

        cfg.ReceiveEndpoint("config-options-queue", e =>
        {
            e.ConfigureKubeMQ(t => { });
        });
    });
});
```

Two query parameters are parsed from the URI:

| Parameter   | Effect                                     |
| ----------- | ------------------------------------------ |
| `authToken` | Sets the authentication token              |
| `tls`       | `true` or `false` to enable or disable TLS |

A common pattern is to read the URI from an environment variable so the same binary runs against different brokers without recompiling:

```csharp title="Program.cs"
var connectionString = Environment.GetEnvironmentVariable("KUBEMQ_CONNECTION_STRING")
    ?? "kubemq://localhost:50000";

cfg.Host(new Uri(connectionString), h =>
{
    h.ClientId = "connstring-client";
});
```

The optional second argument to `Host` is a host configurator callback — you can combine the URI form with explicit settings such as `ClientId`, as above.

## Authentication and TLS [#authentication-and-tls]

For full control, pass a host configurator callback to `cfg.Host(host, port, h => { ... })`. The callback exposes the connection-level settings: `AuthToken`, `UseTls`, the three TLS file paths, and the connection/reconnect timeouts.

<Tabs items="[&#x22;Auth token&#x22;, &#x22;TLS&#x22;, &#x22;Mutual TLS (mTLS)&#x22;]">
  <Tab value="Auth token">
    ```csharp title="Program.cs"
    cfg.Host("kubemq-server.example.com", 50000, h =>
    {
        h.ClientId = "auth-token-client";
        h.AuthToken = "my-secret-token";
    });
    ```
  </Tab>

  <Tab value="TLS">
    ```csharp title="Program.cs"
    cfg.Host("kubemq-server.example.com", 50000, h =>
    {
        h.UseTls = true;
        h.TlsCertFile = "/certs/client.pem";
    });
    ```
  </Tab>

  <Tab value="Mutual TLS (mTLS)">
    ```csharp title="Program.cs"
    cfg.Host("kubemq-server.example.com", 50000, h =>
    {
        h.UseTls = true;
        h.TlsCertFile = "/certs/client.pem";
        h.TlsKeyFile = "/certs/client-key.pem";
        h.TlsCaFile = "/certs/ca.pem";

        h.ConnectionTimeout = TimeSpan.FromSeconds(30);
        h.ReconnectTimeout = TimeSpan.FromSeconds(120);
    });
    ```
  </Tab>
</Tabs>

When `UseTls` is enabled, `TlsCertFile` is required; `TlsKeyFile` and `TlsCaFile` are needed only for mutual TLS, where the client presents its own certificate and validates the server against a CA. `ConnectionTimeout` (default `10s`) bounds the initial connect, and `ReconnectTimeout` (default `60s`) bounds the wait between reconnection attempts.

<Callout type="warn">
  Do not hard-code secrets such as `AuthToken` or certificate paths in source. Read them from environment variables, the .NET configuration system, or a secrets manager. The shipped examples use a graceful-fallback pattern — they check whether the cert files exist (or whether `KUBEMQ_AUTH_TOKEN` is set) and connect without TLS/auth if not, so the demos run against a plain local broker.
</Callout>

## appsettings.json and IOptions Binding [#appsettingsjson-and-ioptions-binding]

`KubeMQTransportOptions` is designed to bind directly from configuration. Define a `KubeMQ` section in `appsettings.json` and bind it with `Configure<KubeMQTransportOptions>`. Note that `ConnectionTimeout` and `ReconnectTimeout` are `TimeSpan` values, so they use the `"hh:mm:ss"` string format.

```json title="appsettings.json"
{
  "KubeMQ": {
    "Host": "kubemq-server.example.com",
    "Port": 50000,
    "AuthToken": "my-token",
    "UseTls": false,
    "PollTimeoutSeconds": 10,
    "MaxPollMessages": 64,
    "DefaultCqMode": "Queries",
    "ConnectionTimeout": "00:00:30",
    "ReconnectTimeout": "00:02:00"
  }
}
```

There are two ways to consume the bound options. The first is to bind the section yourself with `Configure<T>`, then read the resolved `IOptions<KubeMQTransportOptions>` inside the `UsingKubeMQ` callback to configure the host:

```csharp title="Program.cs"
// Bind the "KubeMQ" section to KubeMQTransportOptions
builder.Services.Configure<KubeMQTransportOptions>(
    builder.Configuration.GetSection("KubeMQ"));

builder.Services.AddMassTransit(x =>
{
    x.AddConsumer<OptionsConsumer>();

    x.UsingKubeMQ((context, cfg) =>
    {
        // IOptions<KubeMQTransportOptions> is resolved from DI
        var options = context.GetRequiredService<IOptions<KubeMQTransportOptions>>().Value;

        cfg.Host(options.Host, options.Port, h =>
        {
            if (options.ClientId != null)
                h.ClientId = options.ClientId;
        });

        cfg.ReceiveEndpoint("config-options-queue", e =>
        {
            e.ConfigureKubeMQ(t => { });
        });
    });
});
```

The second is the `UsingKubeMQ` overload that takes a `configureOptions` callback as its last argument. The callback receives a `KubeMQTransportOptions` instance you can mutate; the values flow into the transport configuration. This is convenient for setting a few options inline without binding a configuration section:

```csharp title="Program.cs"
services.AddMassTransit(x =>
{
    x.UsingKubeMQ((ctx, cfg) =>
    {
        cfg.Host("kubemq-server.example.com", 50000);

        cfg.ReceiveEndpoint("config-options-queue", e =>
        {
            e.ConfigureKubeMQ(t => { });
        });
    }, options =>
    {
        options.MaxPollMessages = 64;
        options.PollTimeoutSeconds = 10;
    });
});
```

## Per-Endpoint Overrides [#per-endpoint-overrides]

Poll behavior and KubeMQ-specific transport settings can be tuned per receive endpoint, overriding the global defaults. On the endpoint configurator (`IKubeMQReceiveEndpointConfigurator`) you can set `PollTimeoutSeconds` and `MaxPollMessages` directly, and call `ConfigureKubeMQ` to reach the transport-level options (`IKubeMQEndpointTransportConfigurator`): `ExpirationSeconds` for message TTL and `UseNativeDlq` for the native dead-letter queue.

```csharp title="Program.cs"
x.UsingKubeMQ((context, cfg) =>
{
    cfg.Host("localhost", 50000, h =>
    {
        h.ClientId = "per-endpoint-client";
    });

    // Aggressive polling: short timeout, large batch
    cfg.ReceiveEndpoint("config-fast-poll-queue", e =>
    {
        e.PollTimeoutSeconds = 2;
        e.MaxPollMessages = 128;
        e.ConfigureKubeMQ(t => { });
    });

    // Relaxed polling: longer timeout, smaller batch
    cfg.ReceiveEndpoint("config-slow-poll-queue", e =>
    {
        e.PollTimeoutSeconds = 30;
        e.MaxPollMessages = 8;
        e.ConfigureKubeMQ(t => { });
    });

    // Native DLQ + message expiration
    cfg.ReceiveEndpoint("order-processing", e =>
    {
        e.ConfigureKubeMQ(k =>
        {
            k.ExpirationSeconds = 3600;       // messages expire after 1 hour
            k.UseNativeDlq(5, "orders-dlq");  // max 5 receive attempts, then DLQ
        });
    });
});
```

`UseNativeDlq(maxReceiveCount, dlqChannel)` configures KubeMQ's native dead-letter queue: after `maxReceiveCount` failed receive attempts, the message is routed to the named DLQ channel. `PollTimeoutSeconds` is the long-poll wait — a higher value reduces empty polls on idle queues, while a lower value makes the endpoint more responsive.

<Callout type="info">
  `ConnectionTimeout` and `ReconnectTimeout` are connection-level (set on the host), not per-endpoint. Per-endpoint overrides apply only to poll behavior and the KubeMQ transport options exposed by `ConfigureKubeMQ`.
</Callout>

## Validation [#validation]

`KubeMQTransportOptions.Validate()` runs automatically during bus startup. If any value is out of range it throws `KubeMQTransportConfigurationException` (see [Error Handling & DLQ](/integrations/masstransit/how-to/error-handling-dlq) for the full exception model), so misconfiguration fails fast at boot rather than surfacing as an obscure runtime error. The following conditions are rejected:

| Condition                           | Rule                           |
| ----------------------------------- | ------------------------------ |
| `Host` empty or whitespace          | Must be non-empty              |
| `Port` outside 1–65535              | Valid TCP port                 |
| `PollTimeoutSeconds` outside 1–3600 | 1 second to 1 hour             |
| `MaxPollMessages` outside 1–1024    | At least one message per batch |
| `ConnectionTimeout` ≤ 0             | Must be positive               |
| `ReconnectTimeout` ≤ 0              | Must be positive               |

You can run the same validation yourself before startup — useful in tests or a configuration smoke check:

```csharp title="ValidationDemo.cs"
using MassTransit.KubeMQTransport;
using MassTransit.KubeMQTransport.Exceptions;

try
{
    var options = new KubeMQTransportOptions { Port = 99999 };
    options.Validate();
}
catch (KubeMQTransportConfigurationException ex)
{
    // "Port is invalid: 99999 must be between 1 and 65535"
    Console.WriteLine(ex.Message);
}
```

## Endpoint Address Format [#endpoint-address-format]

Send endpoints are addressed with the `kubemq://` URI scheme. The full form names the host, port, and channel:

```text title="address format"
kubemq://host:port/channel-name
```

When resolving a send endpoint at runtime, build the URI from your configured host and port:

```csharp title="Program.cs"
var endpoint = await bus.GetSendEndpoint(
    new Uri("kubemq://localhost:50000/order-processing"));
```

MassTransit also accepts the `queue:` shorthand, which resolves to a channel on the configured host without repeating host and port:

```csharp title="Program.cs"
var endpoint = await bus.GetSendEndpoint(new Uri("queue:order-processing"));
```

## Multi-Transport and Multi-Bus Setups [#multi-transport-and-multi-bus-setups]

When the bus already uses another transport — RabbitMQ, Azure Service Bus, or InMemory — and you want to add KubeMQ alongside it, use `AddKubeMQRider` instead of `UsingKubeMQ`. The rider configurator (`IKubeMQRiderConfigurator`) exposes the same `Host` and `ReceiveEndpoint` methods, so configuration looks identical.

```csharp title="Program.cs"
builder.Services.AddMassTransit(x =>
{
    // Base bus uses InMemory (or any other transport)
    x.UsingInMemory();

    // Add KubeMQ as a supplementary transport
    x.AddKubeMQRider((ctx, k) =>
    {
        k.Host("localhost", 50000);

        k.ReceiveEndpoint("rider-basic-queue", e =>
        {
            e.ConfigureKubeMQ(t => { });
        });
    });
});
```

This is the foundation for multi-bus and domain-separation topologies, where different services or message domains map to distinct endpoints and channels on the same broker.

## Related [#related]

* [Reference](/integrations/masstransit/reference/configuration) for the complete `KubeMQTransportOptions` and validation table
* [Queues (Send)](/integrations/masstransit/how-to/queues) for queue-specific endpoint settings such as poll behavior and DLQ
* [Events Store (Durable Publish)](/integrations/masstransit/how-to/events-store) for persistent publish and subscription start positions
* [Commands & Queries](/integrations/masstransit/how-to/commands-queries) for CQ-mode (Commands vs Queries) configuration
