Apache Kafka is a distributed event platform. It stores and moves streams of records in topics. Teams use it for data pipelines, messaging, and event driven services.
The Kafka plugin brings Kafka signals into Backstage. It adds a tab on your service pages with topic offsets and consumer group offsets. You can see lag and spot trouble in seconds. It works across multiple clusters and reads simple annotations on your entities. You can add links to external dashboards like AKHQ or Confluent, so people can jump from Backstage to deeper views when they need to. This keeps the day to day checks in one place and helps during incidents or deploys.You can see others using Kafka with Backstage in the wild.
Peaksys Engineering wrote about trying the Kafka plugin during their journey. In their words, they “first tested the Kafka plugin” as part of a broader Kafka integration, before later building extras for multi cluster views.
If you run Kafka already, this plugin gives engineers a shared window into topics and groups. It lowers context switching. It makes offsets and lag visible next to code, docs, and ownership.
Installation Instructions
These instructions apply to self-hosted Backstage only.
Install the packages
# from your Backstage root directory
yarn --cwd packages/app add @backstage-community/plugin-kafka
yarn --cwd packages/backend add @backstage-community/plugin-kafka-backend
Add the backend plugin legacy backend
Create a router file
// packages/backend/src/plugins/kafka.ts
import { createRouter } from '@backstage-community/plugin-kafka-backend';
import { Router } from 'express';
import { PluginEnvironment } from '../types';
export default async function createPlugin(
env: PluginEnvironment,
): Promise<Router> {
return await createRouter({
logger: env.logger,
config: env.config,
});
}
Mount the router
// packages/backend/src/index.ts
import kafka from './plugins/kafka';
// inside main
async function main() {
// other envs
const kafkaEnv = useHotMemoize(module, () => createEnv('kafka'));
// other routers
apiRouter.use('/kafka', await kafka(kafkaEnv));
// server start stays the same
}
Configure Kafka in app config
Add your clusters to app config
# app-config.yaml
kafka:
clientId: backstage
clusters:
- name: cluster-name
brokers:
- localhost:9092
You can add a dashboard url per cluster if you want
# app-config.yaml
kafka:
clientId: backstage
clusters:
- name: cluster-name
brokers:
- localhost:9092
dashboardUrl: https://dashboard.com
Annotate your components with consumer groups
Add the consumer groups annotation on the service entity. You can list more than one group with commas.
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: my-service
annotations:
kafka.apache.org/consumer-groups: cluster-name/consumer-group-name
spec:
type: service
You can also attach dashboard urls by annotation
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: my-service
annotations:
kafka.apache.org/dashboard-urls: cluster-name/consumer-group-name/dashboard-url
spec:
type: service
The consumer group name in the dashboard urls annotation is optional
Add the Kafka tab legacy frontend
Import the Kafka entity content and add a tab on the service entity page
// packages/app/src/components/catalog/EntityPage.tsx
import React from 'react';
import { EntityLayout } from '@backstage/plugin-catalog';
import {
EntityKafkaContent,
isKafkaAvailable,
} from '@backstage-community/plugin-kafka';
const serviceEntityPage = (
<EntityLayout>
{/* other tabs */}
<EntityLayout.Route path="/kafka" title="Kafka">
<EntityKafkaContent />
</EntityLayout.Route>
</EntityLayout>
);
// Optional show the tab only when Kafka is available on the entity
// wrap your routes in an EntitySwitch if your app uses it
/*
import { EntitySwitch } from '@backstage/plugin-catalog';
const serviceEntityPage = (
<EntitySwitch>
<EntitySwitch.Case if={isKafkaAvailable}>
<EntityLayout>
<EntityLayout.Route path="/kafka" title="Kafka">
<EntityKafkaContent />
</EntityLayout.Route>
</EntityLayout>
</EntitySwitch.Case>
</EntitySwitch>
);
*/
Use the new frontend system
You can let the app auto detect the Kafka plugin or enable it in code
Enable via config
# app-config.yaml
# enable package discovery for all plugins
app:
packages: 'all'
---
# or enable discovery only for Kafka
app:
packages:
include:
- '@backstage-community/plugin-kafka'
Enable via code
// packages/app/src/App.tsx
import { createApp } from '@backstage/frontend-defaults';
import kafkaPlugin from '@backstage-community/plugin-kafka/alpha';
const app = createApp({
features: [
kafkaPlugin,
],
});
export default app.createRoot();
Customize the Kafka tab with extensions config
# app-config.yaml
app:
extensions:
# disable the Kafka entity content if needed
- 'entity-content:kafka': false
# or customize the tab path and title
- 'entity-content:kafka':
config:
path: '/events'
title: 'Events'
Backend new system
The backend package here exposes an Express router. The steps above show the legacy backend wiring. There is no new backend system module documented for this plugin. Use the router setup shown above in your backend.
Changelog
This changelog is produced from commits made to the Kafka plugin since a year ago, and based on the code located here. It may not contain information about all commits. Releases and version bumps are intentionally omitted. This changelog is generated by AI.
Features
- Migrate Kafka plugin to the new frontend system. Expose an alpha subpath. Legacy exports stay the same. No visual changes. #5386 merged 10 days ago
Documentation
- Update docs to reference the Kafka backend plugin. Add link to KafkaJS SSL options. #2902 merged 7 months ago
Maintenance
- Remove unused dev dependency canvas. #3565 merged 5 months ago
- Reduce knip false positives by using a workspace config. Update repo tools to 0.13.0. #3018 merged 6 months ago
- Remove uses of backstage backend common in Kafka packages. #1967 merged 10 months ago
Breaking changes
- None
Set up Backstage in minutes with Roadie
Focus on using Backstage, rather than building and maintaining it.