Skip to content
DocsTry Aspire
DocsTry

Set up Apache Kafka in the AppHost

Apache Kafka logo

This article is the reference for the Aspire Apache Kafka Hosting integration. It enumerates the AppHost APIs — with examples for both AppHost.cs and apphost.mts — that you use to model a Kafka resource in your AppHost project.

If you’re new to the Apache Kafka integration, start with the Get started with Apache Kafka integrations guide. For how consuming apps read the connection information this page exposes, see Connect to Apache Kafka.

To start building an Aspire app that uses Apache Kafka, install the 📦 Aspire.Hosting.Kafka NuGet package:

Terminal
aspire add kafka

Learn more about aspire add in the command reference.

This updates your aspire.config.json with the Kafka hosting integration package:

aspire.config.json
{
"packages": {
"Aspire.Hosting.Kafka": "13.5.3"
}
}

Once you’ve installed the hosting integration in your AppHost project, you can add a Kafka server resource as shown in the following examples:

apphost.mts
import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
const kafka = await builder.addKafka("kafka");
await builder.addNodeApp("api", "./api", "index.js")
.withReference(kafka);
// After adding all resources, run the app...
  1. When Aspire adds a container image to the AppHost, as shown in the preceding example with the confluentinc/confluent-local image, it creates a new Kafka server instance on your local machine.

  2. The AppHost reference call configures a connection in the consuming project named after the referenced Kafka resource, such as kafka in the preceding example.

  • Kafka container imageDocker Hub
    docker.io/confluentinc/confluent-local:8.2.0

    Added by AddKafka()addKafka().

    Source

Tags reflect the latest defaults on the microsoft/aspire main branch, and may be newer than the version pinned by the package you install.

Add the Kafka UI sub-resource to the Kafka server resource to get a web interface for monitoring and managing your Kafka cluster during development:

apphost.mts
import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
const kafka = await builder.addKafka("kafka");
await kafka.withKafkaUI();
await builder.addNodeApp("api", "./api", "index.js")
.withReference(kafka);
// After adding all resources, run the app...

The Kafka UI is a free, open-source web UI to monitor and manage Apache Kafka clusters. It’s automatically linked to your Kafka server and appears as a separate resource in the Aspire dashboard.

  • Kafka UI container imageCompanion · KafkaDocker Hub
    docker.io/kafbat/kafka-ui:v1.5.0

    Added by WithKafkaUI()withKafkaUI().

    Source

Tags reflect the latest defaults on the microsoft/aspire main branch, and may be newer than the version pinned by the package you install.

To change the host port the Kafka UI listens on, chain a call to WithHostPort (or withHostPort):

apphost.mts
import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
const kafka = await builder.addKafka("kafka");
await kafka.withKafkaUI({
configureContainer: async (kafkaUI) => {
await kafkaUI.withHostPort({ port: 9100 });
},
});
await builder.addNodeApp("api", "./api", "index.js")
.withReference(kafka);
// After adding all resources, run the app...

Add a data volume to the Kafka server resource to persist data outside the lifecycle of its container:

apphost.mts
import {
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
} from './.aspire/modules/aspire.mjs';
const
const builder: IDistributedApplicationBuilder
builder
= await
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
();
const
const kafka: KafkaServerResource
kafka
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addKafka(name: string, options?: {
port?: number;
}): KafkaServerResource (+1 overload)

Adds a Kafka resource to the application. A container is used for local development.

addKafka
("kafka");
await
const kafka: KafkaServerResource
kafka
.
KafkaServerResource.withDataVolume(options?: {
name?: string;
isReadOnly?: boolean;
}): KafkaServerResource (+1 overload)

Adds a named volume for the data folder to a Kafka container resource.

withDataVolume
({
isReadOnly?: boolean | undefined
isReadOnly
: false });
await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addNodeApp(name: string, appDirectory: string, scriptPath: string): NodeAppResource

Adds a node application to the application model. Node should be available on the PATH.

addNodeApp
("api", "./api", "index.js")
.
ExecutableResource.withReference(source: EndpointReference | string | uri, options?: {
connectionName?: string;
optional?: boolean;
name?: string;
} | undefined): NodeAppResource (+1 overload)

Adds a reference to another resource

withReference
(
const kafka: KafkaServerResource
kafka
);
// After adding all resources, run the app...

The data volume is used to persist Kafka broker data outside the lifecycle of its container. For more information on data volumes and details on why they’re preferred over bind mounts, see Docker docs: Volumes.

Add a data bind mount to the Kafka server resource as shown in the following examples:

apphost.mts
import {
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
} from './.aspire/modules/aspire.mjs';
const
const builder: IDistributedApplicationBuilder
builder
= await
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
();
const
const kafka: KafkaServerResource
kafka
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addKafka(name: string, options?: {
port?: number;
}): KafkaServerResource (+1 overload)

Adds a Kafka resource to the application. A container is used for local development.

addKafka
("kafka");
await
const kafka: KafkaServerResource
kafka
.
KafkaServerResource.withDataBindMount(source: string, options?: {
isReadOnly?: boolean;
}): KafkaServerResource (+1 overload)

Adds a bind mount for the data folder to a Kafka container resource.

withDataBindMount
("/Kafka/Data", {
isReadOnly?: boolean | undefined
isReadOnly
: false });
await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addNodeApp(name: string, appDirectory: string, scriptPath: string): NodeAppResource

Adds a node application to the application model. Node should be available on the PATH.

addNodeApp
("api", "./api", "index.js")
.
ExecutableResource.withReference(source: EndpointReference | string | uri, options?: {
connectionName?: string;
optional?: boolean;
name?: string;
} | undefined): NodeAppResource (+1 overload)

Adds a reference to another resource

withReference
(
const kafka: KafkaServerResource
kafka
);
// After adding all resources, run the app...

The Aspire Kafka integration deploys a container from the confluentinc/confluent-local image, which provides a simple Apache Kafka cluster running in KRaft mode with no further configuration required. It’s ideal for local development and testing, but this image is for local experimentation only and isn’t supported by Confluent in production.

To use a full broker topology in non-development environments, switch to an externally managed Kafka cluster via a connection string:

apphost.mts
import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
// Use a local container for development; use an external connection string otherwise.
// The TypeScript AppHost doesn't expose an execution-context check; use an environment
// variable or configuration to select between the two at startup.
const kafka = await builder.addKafka("kafka");
await kafka.withKafkaUI();
await builder.addNodeApp("api", "./api", "index.js")
.withReference(kafka);
// After adding all resources, run the app...

By default, Aspire injects the Kafka connection information using variable names derived from the resource name (for example, KAFKA_HOST, KAFKA_PORT). If your consuming app expects a different set of environment variable names, pass individual connection properties from the AppHost:

apphost.mts
import {
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
} from './.aspire/modules/aspire.mjs';
const
const builder: IDistributedApplicationBuilder
builder
= await
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
();
const
const kafka: KafkaServerResource
kafka
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addKafka(name: string, options?: {
port?: number;
}): KafkaServerResource (+1 overload)

Adds a Kafka resource to the application. A container is used for local development.

addKafka
("kafka");
const
const kafkaHost: EndpointReferenceExpression
kafkaHost
= await
const kafka: KafkaServerResource
kafka
.
KafkaServerResource.host: () => Promise<EndpointReferenceExpression>

Gets the host endpoint reference for the primary endpoint.

host
();
const
const kafkaPort: EndpointReferenceExpression
kafkaPort
= await
const kafka: KafkaServerResource
kafka
.
KafkaServerResource.port: () => Promise<EndpointReferenceExpression>

Gets the port endpoint reference for the primary endpoint.

port
();
await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addNodeApp(name: string, appDirectory: string, scriptPath: string): NodeAppResource

Adds a node application to the application model. Node should be available on the PATH.

addNodeApp
("my-app", "./app", "index.js")
.
ExecutableResource.withReference(source: EndpointReference | string | uri, options?: {
connectionName?: string;
optional?: boolean;
name?: string;
} | undefined): NodeAppResource (+1 overload)

Adds a reference to another resource

withReference
(
const kafka: KafkaServerResource
kafka
)
.
ExecutableResource.withEnvironment(name: string, value: string | IResourceWithConnectionString | IValueProvider): NodeAppResource

Sets an environment variable

withEnvironment
("BOOTSTRAP_SERVERS_HOST",
const kafkaHost: EndpointReferenceExpression
kafkaHost
)
.
ExecutableResource.withEnvironment(name: string, value: string | IResourceWithConnectionString | IValueProvider): NodeAppResource

Sets an environment variable

withEnvironment
("BOOTSTRAP_SERVERS_PORT",
const kafkaPort: EndpointReferenceExpression
kafkaPort
);
await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.build(): DistributedApplication

Builds the distributed application

build
().
DistributedApplication.run(cancellationToken?: cancellationToken): void

Runs the distributed application

run
();

To reference an externally managed Kafka instance rather than spinning up a local container:

apphost.mts
import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
const kafka = await builder.addConnectionString("kafka");
const exampleProject = await builder.addProject("apiservice", "../ExampleProject/ExampleProject.csproj");
await exampleProject.withReference(kafka);
// After adding all resources, run the app...

For the full reference of Kafka connection properties — and how consuming apps in C#, TypeScript, Python, and Go read them — see Connect to Apache Kafka.

The Kafka hosting integration automatically adds a health check for the Kafka server resource. The health check verifies that a Kafka producer with the specified connection name can connect and persist a topic to the Kafka server.