A virtual Kafka cluster gives a team its own Kafka endpoint on top of a shared Kafka cluster. It claims part of the backing cluster’s capacity, in Kafka Units, and enforces produce and fetch limits for it. Clients use it like any Kafka cluster.
Key Features
Many teams, one Kafka cluster: each virtual cluster has its own endpoint and its own share of the capacity.
Capacity in Kafka Units: the virtual clusters on a Kafka cluster together can’t claim more than its Cluster Capacity (Kafka Units).
Produce and fetch limits follow the capacity it claims.
OAuth sign-in for clients, with your identity provider’s issuer, audience and keys.
Settings
Basic Configuration: Identifier and Provider.
Kafka Cluster Selection: the backing Kafka Cluster, and the Capacity Allocation (Kafka Units) to claim from it.
Advanced Configuration: client authentication (the OAuth Issuer, Audience, JWKS Endpoint, Authorization URI, Token URI and Scope).
A virtual cluster belongs to the fleet of its Kafka cluster, so the API addresses it under that fleet: $API/fleet/<fleet>/kafka/kvc/.
Before you start
A fleet in Healthy state with room for the Virtual Kafka Cluster workload (see Fleet management).
For the API: an access token in STREAMTIME_TOKEN and your organization identifier in place of <org>. Replace api.example.com with your Streamtime API address.
packagemainimport("bytes""crypto/rand""encoding/hex""encoding/json""net/http""os")constapi="https://api.example.com/organizations/<org>"// newKey returns a random idempotency key.funcnewKey()string{b:=make([]byte,16)rand.Read(b)returnhex.EncodeToString(b)}// call sends one request with the access token and a JSON body (or none).// An optional idempotency key is sent as the Idempotency-Key header.funccall(method,pathstring,bodyany,idempotencyKey...string)(*http.Response,error){varbufbytes.Bufferifbody!=nil{iferr:=json.NewEncoder(&buf).Encode(body);err!=nil{returnnil,err}}req,err:=http.NewRequest(method,api+path,&buf)iferr!=nil{returnnil,err}req.Header.Set("Authorization","Bearer "+os.Getenv("STREAMTIME_TOKEN"))req.Header.Set("Content-Type","application/json")iflen(idempotencyKey)>0{req.Header.Set("Idempotency-Key",idempotencyKey[0])}returnhttp.DefaultClient.Do(req)}
Saving a Virtual Kafka Cluster resource and provisioning it are separate steps in the API: create or change it, then reconcile its new generation. The reconcile returns 202 with the operation it started; the same Idempotency-Key returns that operation again, and a 409 means the generation is out of date.
Create a virtual cluster
In the sidebar, select Virtual Kafka, then Add Virtual Kafka Cluster.
Basic Configuration: enter the Identifier and choose the Provider.
Kafka Cluster Selection: choose the Kafka Cluster and set the Capacity Allocation (Kafka Units).
Advanced Configuration: set up client authentication, then create it. It shows Pending, then Provisioning, then Healthy.
# 1. Save it. The response includes "generation".
curl -X POST "$API/fleet/<fleet>/kafka/kvc/"\-H"Authorization: Bearer $STREAMTIME_TOKEN"\-H"Content-Type: application/json"\-d'{"identifier": "team-a", "kafka_id": "<kafka-cluster>", "kafka_units": 2}'# 2. Provision it
curl -X POST "$API/fleet/<fleet>/kafka/kvc/team-a/reconcile/"\-H"Authorization: Bearer $STREAMTIME_TOKEN"\-H"Content-Type: application/json"\-H"Idempotency-Key: $(uuidgen)"\-d'{"generation": 1}'
identifier, kafka_id and kafka_units are required; provider defaults to kroxy. The request is refused when the Kafka cluster has too little capacity left for the Kafka Units you ask for.
resp,err:=call("GET","/fleet/<fleet>/kafka/kvc/team-a/",nil)// Decode "status" from resp.Body.
streamtime virtual-kafka-cluster list
streamtime virtual-kafka-cluster get team-a
Not available in MCP yet. Check the status from the UI, API or CLI.
Connect clients
Once it’s Healthy, the virtual cluster has its own bootstrap address, a ready-made client configuration and sample commands. Clients sign in with OAuth tokens from the identity provider set in its advanced configuration.
Open the virtual cluster from Virtual Kafka.
Endpoints lists its addresses. Select Test for the client properties and sample commands to copy.
Authorization shows the Issuer, Audience, JWKS Endpoint, Authorization URI, Token URI and Scope clients use to get a token.
# Endpoints, client properties and sample commands are under "resources";# the OAuth settings under "advanced_config.oauth".
curl -s"$API/fleet/<fleet>/kafka/kvc/team-a/"-H"Authorization: Bearer $STREAMTIME_TOKEN"\
| jq '{endpoints: .resources.endpoints, client_properties: .resources.client_properties, oauth: .advanced_config.oauth}'
resp,err:=call("GET","/fleet/<fleet>/kafka/kvc/team-a/",nil)// Decode "resources" (endpoints, client_properties, commands) from resp.Body.
streamtime virtual-kafka-cluster get team-a --output json
The resources field holds the endpoints and client properties.
Not available in MCP yet. Get the connection details from the UI, API or CLI.
Change the configuration or upgrade
Change the capacity it claims (kafka_units) or its client authentication. Produce and fetch limits follow the new capacity.
Open it from Virtual Kafka and select Configuration (or Edit).
Change the settings, then save. Streamtime applies the change, and the status shows Updating, then Healthy.
# 1. Save the change. The response includes the new "generation".GEN=$(curl -s-X PATCH "$API/fleet/<fleet>/kafka/kvc/team-a/"\-H"Authorization: Bearer $STREAMTIME_TOKEN"\-H"Content-Type: application/json"\-d'{"kafka_units": 3}' | jq .generation)# 2. Apply it
curl -X POST "$API/fleet/<fleet>/kafka/kvc/team-a/reconcile/"\-H"Authorization: Bearer $STREAMTIME_TOKEN"\-H"Content-Type: application/json"\-H"Idempotency-Key: $(uuidgen)"\-d"{\"generation\": $GEN}"
The SDK has no typed call for this update yet, so save it with the SDK’s HTTP client, then apply it:
Not available in the CLI yet. Change the configuration from the UI or API.
Not available in MCP yet. Change the configuration from the UI or API.
View metrics, logs and alerts
Open it from Virtual Kafka and select Monitoring for its metrics and logs, and Alert Rules (where shown) for the alerts that watch it. Alerts that fire also appear on the fleet’s Monitoring tab.
Metrics and logs are read through the fleet that runs it:
A draft that was never provisioned is removed at once; otherwise the teardown starts. Poll GET $API/fleet/<fleet>/kafka/kvc/team-a/ until it returns 404.