Producing a Message in Kafka

Producing a Message in Kafka

What really happens between the moment your program decides to send an event and the moment Kafka considers it safely written. A close look at the journey of a single message.

Imagine dropping a registered letter into a post office counter instead of an ordinary street mailbox. You do not just push it through a slot and walk away; the clerk weighs it, decides which sorting route it should follow, stamps it, and hands you a receipt confirming it is now safely in the system. Only then do you leave, confident the letter is tracked and will not simply vanish. Sending, or producing, a message in Kafka works remarkably similarly: there is far more happening behind that one simple action than most beginners expect.

1The Big Picture: What Does “Producing” Mean?

Producing simply means a program creating a piece of data and handing it to Kafka to be stored and eventually delivered.

In Kafka’s world, any program that creates and sends data is called a producer. A producer might be a website’s checkout service announcing “an order was placed,” a mobile app reporting “the user tapped this button,” or a factory sensor reporting “the temperature just changed.” Whatever the source, the act of producing is the same: package up a small piece of information, called a message or an event, and send it to a specific topic, Kafka’s named, ordered stream for that kind of data.

It is tempting to imagine this as a single, instant action, throw the message and forget it, but Kafka producers are actually careful, deliberate pieces of software. They decide exactly where a message should go, how to describe it, whether to wait for confirmation, and what to do if something goes wrong along the way.

Simple Analogy

Sending an SMS through a mobile network is not really “instant” either, even though it feels that way. The message is handed to a tower, routed through the network, confirmed as delivered, and only then does your phone show the little checkmark. Producing a message to Kafka involves a similar, careful hand-off, just measured in milliseconds instead of seconds.

2The Anatomy of a Kafka Message

Before a message can be sent, it needs to be assembled from a few distinct pieces, each with its own job.

Part 1

Topic

The named stream the message is destined for, such as “orders” or “user-signups.” Every message belongs to exactly one topic.

Part 2

Key

An optional label, such as a customer ID, used to decide which partition the message lands in and to keep related messages in order.

Part 3

Value

The actual payload, the real content being communicated, such as the details of an order.

Part 4

Headers

Small optional metadata tags attached to the message, such as which system produced it or a tracing identifier.

Part 5

Timestamp

The moment the message was created or sent, recorded automatically or set explicitly by the producer.

Part 6

Partition (Optional)

A specific partition number can be chosen directly, bypassing the usual key-based decision entirely.

Simple Analogy

Think of a courier package. The topic is the destination city, the key is the customer’s account number used to route it to the right local depot, the value is what is actually inside the box, and headers are the extra stickers, “fragile,” “priority,” attached to the outside.

3How a Message Chooses Its Partition

A topic is usually split into several partitions, and every message needs a clear, predictable way of landing in exactly one of them.

When a message includes a key, Kafka runs that key through a consistent formula, called a hashing function, which always produces the same partition number for the same key. This means every message about, say, “customer 88” will always land in the same partition, keeping that customer’s history in perfect order.

When a message has no key at all, Kafka instead spreads messages across all available partitions in a rotating, balanced pattern, so that no single partition becomes overloaded while others sit idle. This is a reasonable default when strict per-entity ordering does not matter.

flowchart LR
    M1["Message: key=customer-88"] --> H{Hash the Key}
    H --> P1[Partition 1]
    M2["Message: key=customer-42"] --> H2{Hash the Key}
    H2 --> P2[Partition 2]
    M3["Message: no key"] --> R{Round-Robin}
    R --> P0[Partition 0]
    R --> P1
    R --> P2
        
FIG 1 — A key consistently maps to one partition; a keyless message spreads across all partitions
i
Good to Know

Choosing a good key matters more than it might first appear. Related events that must stay in order, all actions for one customer, for example, should always share the same key so they are guaranteed to land in the same partition.

4Serialization: Turning Data Into Bytes

Before a message can travel across a network, it must be converted from a program’s internal data structure into a flat, transportable format.

This conversion process is called serialization. A producer takes a structured piece of data, perhaps an object representing an order with a customer name, items, and a total price, and flattens it into a simple sequence of bytes that any system can transmit and store, regardless of what programming language wrote it. On the receiving end, a consumer reverses this process, called deserialization, turning the bytes back into a usable structure.

Common Serialization Formats

Plain text formats like JSON are popular for their simplicity and readability. More compact, structured formats like Avro or Protobuf are common in larger systems because they are smaller, faster, and can enforce a strict, agreed-upon shape for the data.

Simple Analogy

Serialization is like folding a full-size paper airplane design into a flat sheet before mailing it overseas. The recipient unfolds it back into the exact same shape on arrival. Both sides must agree on the folding pattern, or the shape gets lost in translation.

!
Common Mistake

Changing a message’s structure without warning the teams consuming it. If a field is renamed or removed without coordination, consumers expecting the old shape can fail unexpectedly while trying to deserialize the new messages.

5The Journey of a Message, Step by Step

From the instant a program decides to send something, to the moment it is durably stored, a message passes through several distinct stages.

1

The application builds the message

The producer assembles the topic, key, value, and any headers into a single message ready to send.

2

The message is serialized

The key and value are converted into raw bytes using the agreed serialization format.

3

A partition is chosen

Based on the key, or a rotating pattern if there is no key, Kafka determines exactly which partition will receive it.

4

The message enters a local batch

Rather than sending one message at a time, the producer briefly groups it with other messages headed to the same partition.

5

The batch is sent to the leader broker

The producer sends the batch across the network to the broker currently acting as leader for that partition.

6

The broker writes and confirms

The leader appends the message to its log, waits for whatever acknowledgement level was configured, and sends confirmation back.

sequenceDiagram
    participant App as Application
    participant Prod as Producer
    participant B as Broker (Leader)
    App->>Prod: Build message
    Prod->>Prod: Serialize + choose partition
    Prod->>Prod: Add to batch
    Prod->>B: Send batch
    B->>B: Append to partition log
    B-->>Prod: Acknowledge
    Prod-->>App: Confirm send success
        
FIG 2 — The full path a message takes from the application to durable storage

6Batching: Why Kafka Groups Messages Together

Sending one tiny network request per message would be wasteful. Kafka producers are smart enough to bundle messages together first.

Rather than firing off a separate network call for every single message, a producer briefly holds newly created messages in a small local batch, grouped by which partition they are headed to. Once the batch reaches a certain size, or a short amount of time passes, whichever happens first, the entire batch is sent together in one network request.

SettingWhat It ControlsEffect of a Larger Value
Batch SizeHow much data can accumulate before a batch is sentFewer, larger network requests; slightly higher delay per message
Linger TimeHow long the producer waits, hoping more messages arrive to batch togetherBetter batching efficiency; slightly higher delay before the first send
Simple Analogy

Batching is like a delivery van waiting a few extra minutes to see if more packages for the same neighborhood arrive before setting off, rather than making a separate trip for every single parcel. A little patience saves a great deal of fuel and time overall.

i
Good to Know

Batching is one of the biggest reasons Kafka can handle such enormous throughput. Fewer, larger network trips are dramatically more efficient than a flood of tiny individual ones.

7Acknowledgements: How Sure Should the Producer Be?

Once a message is sent, Kafka lets the producer decide exactly how much proof it wants before considering the send truly successful.

This setting is often called acks, short for acknowledgements, and it is one of the most important decisions a producer makes. It controls a direct trade-off between speed and safety: waiting for less confirmation is faster but riskier, while waiting for more confirmation is safer but slightly slower.

Acks SettingWhat It Waits ForRisk If Something Fails
acks = 0Nothing at all; fires and moves on immediatelyThe message could be lost entirely without the producer ever knowing
acks = 1Only the leader broker confirms it has the messageIf the leader fails right after, before followers copy it, the message can still be lost
acks = allEvery in-sync replica confirms it has the messageVery low risk of loss, at the cost of a little extra waiting time
!
Common Mistake

Using acks = 0 for genuinely important data, such as payment events, purely to shave off a little latency. The speed gained rarely justifies the risk of silently losing critical business data.

8What Happens When Sending Fails

Networks glitch, brokers restart, and messages do not always reach their destination on the first try. Producers are built to handle this gracefully.

If a producer does not receive the expected acknowledgement in time, it typically assumes the send may have failed and automatically retries, sending the same batch again. This built-in resilience is one of Kafka’s strengths, but it introduces a subtle new problem: what if the original message actually did succeed, and only the acknowledgement was lost on its way back? The retry could then create a duplicate.

Idempotent Producers

To solve this, Kafka supports a mode where each producer is given a unique identity, and every message it sends carries a sequence number. The broker can then recognize and silently discard an accidental duplicate caused by a retry, ensuring each message is written exactly once despite the retry happening.

1

Send attempt is made

The producer sends the batch and starts waiting for acknowledgement.

2

No acknowledgement arrives in time

A network hiccup or broker slowdown means the confirmation never comes back before the timeout.

3

The producer automatically retries

It sends the same batch again, following its configured retry policy.

4

The broker recognizes a duplicate, if idempotence is enabled

Using the sequence number, the broker safely ignores the repeated attempt if the original already succeeded.

i
Good to Know

Even without idempotence enabled, a consumer built to treat repeated messages safely, an idempotent consumer, provides a second layer of protection against the occasional duplicate.

9Synchronous vs Asynchronous Sending

A producer can be told to wait for confirmation before continuing, or to keep working and check on the result later.

In synchronous sending, the application pauses and waits until it receives confirmation that the message was safely written before moving on to its next task. This is simple to reason about but can slow the application down, since every send briefly blocks other work.

In asynchronous sending, the application fires the message off and immediately continues with other work, without waiting. A callback, a small piece of code that runs later, is triggered once the result, success or failure, eventually becomes known. This approach is far more efficient for high-throughput systems.

Synchronous Sending

  • Simple, predictable, easy-to-follow logic.
  • Guarantees the application knows the outcome before proceeding.
  • Slower overall, since each send briefly pauses the application.

Asynchronous Sending

  • Much higher throughput, since sends do not block other work.
  • Requires careful callback handling to catch failures properly.
  • Slightly more complex code to write and reason about.

10Ordering Guarantees While Producing

Producers play a direct role in whether messages end up in the correct order once they are stored.

Because all messages sharing the same key always land in the same partition, and a single partition always writes messages in the exact order it receives them, choosing a consistent key is the single most important decision a producer makes for ordering. Messages sent without a key, spread across multiple partitions, carry no such guarantee relative to each other.

Retries introduce a subtlety here too: if retries are not handled carefully, an older message that needed to be resent could theoretically be written after a newer message that succeeded on its first attempt. Kafka’s idempotent producer mode specifically protects against this, preserving the original sending order even through retries.

Simple Analogy

Picture a queue of people at a single ticket counter, always served in the order they arrived. But if someone briefly steps out of the line and rejoins later, without a clear rule about where they re-enter, they might accidentally cut ahead of people who were originally behind them. Idempotent producers are the rule that puts them firmly back in their correct original spot.

11Real-World and Industry Examples

Producing messages carefully and correctly is the foundation every downstream Kafka use case is built on.

E-commerce Checkout Flows

An order service produces an “order placed” event, keyed by customer ID, so every action for a single customer stays in strict, correct order.

Ride-Hailing Location Updates

A driver’s mobile app produces a location event every few seconds, keyed by driver ID, ensuring the route history for one driver is always consistent.

Banking Transaction Systems

Payment services almost always use acks = all together with idempotent producers, since losing or duplicating a financial transaction is simply unacceptable.

IoT Sensor Networks

Thousands of sensors produce readings continuously, often without keys, spreading evenly across many partitions for maximum parallel throughput.

Clickstream and Analytics Pipelines

Web and mobile apps produce a steady stream of user interaction events, usually favoring speed with a lighter acknowledgement setting since occasional loss is tolerable.

12Advantages, Disadvantages and Trade-offs

Producing messages carefully takes some deliberate configuration, but each choice trades off against another.

Advantages of Careful Production

  • Strong ordering guarantees when related messages share a sensible key.
  • High throughput thanks to efficient batching of messages before sending.
  • Resilience against network hiccups through automatic retries.
  • Protection against accidental duplicates when idempotence is enabled.

Disadvantages / Trade-offs

  • Stronger acknowledgement settings add a little extra latency to every send.
  • Batching introduces a small, deliberate delay before messages are actually sent.
  • Poor key choices can create uneven load across partitions.
  • Handling retries and duplicates correctly adds real design complexity.

13Security While Producing

A producer is often the very first point where sensitive data enters a Kafka system, making it a natural place to enforce security.

Layer 1

Authentication

The producer should prove its identity to the broker before it is allowed to send anything at all.

Layer 2

Authorization

Even an authenticated producer should only be permitted to write to the specific topics it genuinely needs.

Layer 3

Encryption in Transit

Data traveling from the producer to the broker should be encrypted, so it cannot be read if intercepted along the way.

Layer 4

Careful Payload Design

Avoid placing highly sensitive raw data directly into a message’s value when a safe reference or masked version would do.

!
Something to Watch

Since Kafka can retain messages for a long time, anything written by a producer today may still be readable weeks or months later. Think carefully about what actually belongs in a message before it is sent.

14Monitoring a Producer’s Health

A producer that looks fine from the outside can still be quietly struggling. A few key numbers reveal the truth.

Metric 1

Send Error Rate

How often sends are failing outright, a direct signal of trouble reaching the broker.

Metric 2

Retry Rate

How often messages need to be resent, often an early warning of network or broker instability.

Metric 3

Request Latency

How long it takes for a send to be acknowledged, which directly affects how quickly the application can proceed.

Metric 4

Batch Size and Fill Rate

Whether batches are filling up efficiently or being sent mostly empty, revealing whether batching settings are well tuned.

i
Practical Tip

A sudden rise in retry rate, even without outright failures, is often the earliest sign of a struggling broker, well before anything looks obviously broken elsewhere.

15Design Patterns and Anti-patterns

A few consistent habits separate producers that behave predictably from ones that cause quiet, hard-to-trace problems later.

Helpful patterns

  • Consistent keying — always use the same key for related events, so their order is preserved.
  • Idempotent production — enable it whenever accidental duplicates would cause real harm.
  • Asynchronous sending with proper callbacks — for high-throughput systems that cannot afford to block.
  • Schema agreement — settle on a message format and version it deliberately, rather than changing it silently.
ANTI-PATTERN-01 Avoid
Problem

Using a single, tiny message per network call for a high-volume producer, disabling or ignoring batching entirely.

Why It’s Harmful

An enormous number of tiny network requests is far less efficient, wasting both producer and broker resources that could be spent handling far more data.

Correct Approach

Allow the producer to batch messages naturally, tuning batch size and linger time to match the traffic pattern.

ANTI-PATTERN-02 Avoid
Problem

Picking a key with very few distinct values, such as always using a fixed region name for millions of events.

Why It’s Harmful

All those messages pile into just a handful of partitions, leaving other partitions idle and creating an uneven, inefficient load across the cluster.

Correct Approach

Choose a key with enough natural variety, such as an individual customer or device ID, to spread load evenly while still preserving the order that actually matters.

ANTI-PATTERN-03 Avoid
Problem

Ignoring the result of an asynchronous send entirely, with no callback checking whether it actually succeeded.

Why It’s Harmful

A silently failed send can mean an important event simply never happened as far as the rest of the system is concerned, with no one aware anything went wrong.

Correct Approach

Always attach a callback or equivalent check to every asynchronous send, logging or handling failures deliberately rather than assuming success.

16Best Practices and Common Mistakes

A short checklist for producing messages with confidence.

Best Practices

  • Choose keys deliberately, based on what genuinely needs to stay in order.
  • Match the acknowledgement setting to how critical the data actually is.
  • Enable idempotent production for anything sensitive to duplicates.
  • Handle send failures explicitly rather than assuming every send succeeds.
  • Agree on and version the message format ahead of time.

Common Mistakes

  • Using acks = 0 for data that genuinely cannot afford to be lost.
  • Choosing keys with too little variety, overloading a small number of partitions.
  • Ignoring retry and error metrics until customers notice something is wrong.
  • Changing a message’s structure without coordinating with the teams consuming it.
“A producer’s job does not end the moment .send() is called. It ends only when the outcome is known and handled.”

17Frequently Asked Questions

Q1Does a message need a key to be sent?

No, a key is optional. Without one, Kafka spreads messages evenly across all partitions using a rotating pattern instead of routing by key.

Q2Why does Kafka wait before sending a batch instead of sending each message right away?

Grouping messages together into a batch dramatically reduces the number of network requests needed, which is one of the main reasons Kafka can handle such high volumes of data efficiently.

Q3What is the safest acknowledgement setting to use?

Acks = all offers the strongest protection, since it waits for every in-sync replica to confirm the message before considering the send successful, at the cost of slightly higher latency.

Q4Can the same message be sent twice by accident?

Yes, this can happen if an acknowledgement is lost and the producer retries a message that actually already succeeded. Enabling idempotent production specifically prevents this from creating a true duplicate.

Q5Is asynchronous sending always the better choice?

Not always. It offers much higher throughput, which suits high-volume systems, but synchronous sending can be simpler to reason about for lower-volume or simpler applications.

Q6What happens if a producer sends a message to a partition whose leader has just failed?

The producer detects the failure and automatically redirects the send to the newly elected leader, usually with only a brief delay, and without requiring any manual intervention.

Q7Do all messages in a topic need to use the same format?

It is strongly recommended, and usually enforced through an agreed schema, since consumers rely on a predictable, consistent shape to correctly deserialize and process every message they receive.

18Summary and Key Takeaways

We began at a post office counter and ended inside the careful, multi-step journey a message takes through a Kafka producer. Producing a message is never truly as simple as “send and forget”; it involves choosing a partition through a key, serializing data into a transportable form, batching efficiently for performance, deciding how much confirmation to demand, and gracefully handling the retries and duplicates that inevitably happen in any real network. Understanding this full journey is what separates a system that occasionally loses or duplicates data from one that behaves reliably, even under real-world failure conditions.

Key Takeaways

  • A message has several parts — topic, key, value, headers, and timestamp each play a distinct role in how it is handled.
  • Keys decide the partition — a consistent key keeps related messages in strict, correct order.
  • Serialization makes data transportable — structured data is flattened into bytes before it can travel across the network.
  • Batching drives efficiency — grouping messages together dramatically improves throughput.
  • Acks is a deliberate trade-off — more confirmation means more safety, at the cost of a little extra latency.
  • Retries can create duplicates — idempotent production protects against this without sacrificing resilience.
  • The job isn’t done at send time — a well-built producer always checks and handles the eventual outcome of every send.