You wrote a consumer and want to see it handle one message. Writing a throwaway producer app for that is slow. Here are three ways to do it, from fastest to most realistic.

1. One message with kcat

kcat reads from stdin and produces to a topic. -K: tells it the key and value are separated by a colon, and -H adds a header.

echo 'user_1001:{"eventId":"evt_001","userId":"user_1001","status":"ACTIVE"}' \ | kcat -b localhost:9092 -t user.events -P -K: \ -H "eventType=USER_CREATED" -H "version=v1" 

Two things trip people up:

  • The delimiter splits at its first occurrence. With -K: a key such as user:1001 is cut at the first colon. Pick a delimiter that cannot appear in the key, for example -K'|'.
  • Quote the JSON with single quotes so the shell leaves the double quotes alone.

2. Several messages from a file

Put one key:value pair per line and pass the file with -l:

kcat -b localhost:9092 -t user.events -P -K: -l messages.txt 

Messages with the same key go to the same partition, so if your consumer depends on per-key ordering, reuse a key across lines to test it.

3. From Java, when headers and types matter

When the consumer reads headers or you want the same serializer as production, a ProducerRecord is the honest test:

ProducerRecord<String, String> record = new ProducerRecord<>( "user.events", "user_1001", objectMapper.writeValueAsString(payload)); record.headers().add("eventType", "USER_CREATED".getBytes(StandardCharsets.UTF_8)); record.headers().add("version", "v1".getBytes(StandardCharsets.UTF_8)); producer.send(record).get(); 

Header values are bytes. If the consumer decodes them with a different charset than the producer used, the header looks corrupted, so state UTF-8 on both sides.

Check what landed

Read the last message of each partition back, including key and headers:

kcat -b localhost:9092 -t user.events -C -o -1 -e \ -f 'key=%k headers=%h value=%s\n' 

If the key is empty here, the -K delimiter did not match when you produced.

Getting a payload that matches the schema

The slow part is usually not the command but writing JSON that satisfies the schema: every required field, the right types, the nested records. I built a small browser tool for that step. You paste an Avro schema or a JSON Schema, set the topic, key field and headers, and it returns a matching sample payload, the full message, a ProducerRecord snippet and a kcat command:

The values are fixed placeholders based on field type and name, not random data, and it makes up to 20 messages per run. That is enough to check that a consumer parses the message; it is not a load generator. Everything runs in the browser and the schema is not uploaded.

Summary

Need Use
One message, right now `echo ... \
A batch, or ordering per key {% raw %}kcat -P -K: -l file
Headers and production serializers ProducerRecord in a test
Confirm key, headers and value kcat -C -o -1 -e -f ...