Skip to content

Build1 publisher3 min readPublished

A single-node Kafka in Docker keeps a wrong predicate off the shared cluster

Kafka cannot take a record back, so trying a Streams predicate on the team's cluster writes output that real consumers may already read. A dev.to post seeds a disposable stack from two folders of your own schemas and records.

The Engineer · Build desk

Illustration accompanying A single-node Kafka in Docker keeps a wrong predicate off the shared cluster

What happened

  • A dev.to post argues that the only place to try a new Kafka Streams predicate is the shared cluster, where it creates a consumer group, internal topics and output that a real consumer may already read.
  • One docker compose up -d brings up a single-node Kafka, a Schema Registry and a console that runs Streams topologies, bound to the machine with no volumes, and down returns it to its prior state.
  • Two folders beside the compose file, schemas and records, are read at every up, so what you put there survives the teardown that erases everything else.
  • As you type a predicate into a filter node, the console evaluates it against the newest record on the topic and shows the input record, the output and the verdict beside the editor.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • capability An edge case production has never produced can be written by hand as one line in the records file and evaluated without any other consumer seeing it.
  • cost The work moves from running the topology to choosing the sample, because a small file only helps if it holds the ordinary record and the ones that break the predicate.
  • exposure Sampled production records land in a folder on a developer machine, and the post puts redaction of anything personal on whoever copies them there.
  • constraint The sandbox settles whether the predicate matches the shapes in your data, so anything that depends on volume still has to be answered on the cluster.

No volumes is what makes the reset cheap: nothing the broker or the registry writes outlives the containers [5]. The seeded state comes back on the next `up`, with topics, real Avro records against a registered subject, and a topology already running, so the first screen has numbers on it [6].

Your own topics arrive through the file name. A schema saved as `shipments-value.json` is registered as the subject `shipments-value`, and `.avsc` and `.proto` do the same for Avro and Protobuf [9]. `shipments.json-schema.jsonl` is produced into the topic `shipments`, one record per line, each value framed against that subject, with a pipe separating an optional key from the JSON [10]. Three serialization formats go through one convention. Onboarding a topic is two files, one schema and one sample [20][21]. A typo in the file name is a typo in the subject name.

The post sets three conditions for a short loop: the records you evaluate against are real, the evaluation you see before deploying is the one that will run after, and being wrong leaves nothing behind [12]. The first and third are properties of the sandbox, and you can read them off the compose file. The second is a claim about two systems agreeing, and it is the one that has to hold for anything learned locally to survive the border. For it to hold, the local registry has to resolve the same subject that production resolves, and the application has to use the same serde on both sides. Keeping the topic and subject names identical to the real ones, which the post tells you to do because the design carries them, is the visible part of that [11].

The requirement is stated in the post as "a stack of your own that you are free to break, and a way to carry what you learned across the border without carrying the stack with it" [23]. The published text breaks off mid-sentence while putting a `mapValues` in front of the filter, so the second half of that sentence is asserted and not demonstrated [22]. The playground is the author's own, and the case for it leans on an earlier post, "The compiler was never what you wanted", which located the cost in the loop between having an idea and finding out, and argued that on a shared cluster the loop is long enough that you run it rarely [19].

The safety claim is the one I would credit outright: a private single-node broker with no volumes puts your colleagues' topics out of reach [5]. The post makes no measurement of the loop it says it shortens, and for the third condition it does not have to. Its premise is one sentence: "Kafka does not take records back" [2]. A wrong predicate on the shared cluster means wrong records that somebody downstream has already acted on [3], and the post's account of what usually follows is that you shelve the idea and never learn it was the right one [4].

What to watch

  • Whether the compose file pins Kafka and Schema Registry versions near production's, since a floating latest moves serde differences into the sandbox.
  • Whether teams put a records/ folder of sampled production data under version control, and what redaction that then requires of every reader of the repo.
  • Whether a published step for turning a console design into deployed Streams code appears, which is what the second of the three conditions rests on.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories