Engineering Note

The Large Payload Kafka Handles Well, and the One It Should Not Carry

Kafka is strong at high-volume event streams, but large file payloads can create storage amplification across the whole system.

June 19, 2026 · Pletor Engineering kafkastoragearchitectureoperations

Kafka handles large-scale traffic well. That is why this question comes up:

If Kafka is built for large-scale data, why not send large files through Kafka?

You can make it possible. You can raise producer max.request.size, topic max.message.bytes, consumer fetch.max.bytes, and max.partition.fetch.bytes so that Kafka accepts record batches larger than the defaults. The Apache Kafka documentation also treats producer request size, topic max message size, and consumer fetch size as separate limits.

But this is not mainly a configuration question. The more important difference is the nature of the payload.

The large payload Kafka handles well is usually a large volume of events flowing continuously. Sending a large file as a Kafka message is closer to copying data that is already a file through another file-like path. Both involve bytes, but they create different storage cost models across the system.

The conclusion is simple:

Do not send the file through Kafka.
Send the event that the file exists.
Store the file body in object storage and publish the reference and metadata to Kafka.
Illustration of small event signals flowing while a large file remains in separate storage
Kafka is a better fit for the small event that a file exists than for the file body itself.

Kafka’s Large Scale Is Event-Stream Scale

Kafka was designed for real-time data feeds, high-throughput event streams, and partitioned processing. Producers write events, brokers append them to partition logs, and multiple consumer groups read the same log independently.

A common real-time event flow looks like this:

  1. A producer creates an event.
  2. The producer publishes the event to Kafka.
  3. The producer does not keep that same payload locally for long.
  4. A consumer reads the event and processes it.
  5. The consumer keeps only the result or state it needs.

In this model, Kafka storage pressure is relatively easy to reason about.

Kafka storage ~= incoming bytes/sec
              x retention window
              x replication factor
              x compression/index/segment overhead

Real operations add more variables: compaction, tiered storage, partition distribution, and broker hot spots. Still, the basic shape is clear. Kafka stores the payload in a log for a configured retention window, then removes it.

The important part is that producer and consumer are not usually preserving the same payload as a file source. Events are processing units: state changes, commands, measurements, log fragments, or facts that something happened. A consumer may write a result into another system, but it does not necessarily store the exact same payload again as a file.

File Payloads Move Differently

Large files move differently.

When a producer puts a file into Kafka, it is usually doing one of these things:

  • reading a file that already exists in object storage, NAS, local disk, or a database
  • converting a large binary result directly into a Kafka message
  • receiving an upload request and passing the file body to Kafka so that a later consumer can store it

In that flow, the producer is less like “create an event and discard it” and more like “read a file body and copy it through another path.”

The consumer behaves similarly. If a consumer receives a payload that is tens or hundreds of megabytes, it usually writes that payload somewhere: object storage, a filesystem, another database, or a transformed storage location. The consumer is not merely processing and discarding an event. It is treating the payload as a file again.

At that point, Kafka becomes an intermediate storage layer in a file transfer path.

The Broker Is Not the Only Problem

Large file payloads do put pressure on Kafka brokers.

  • Producer requests become larger.
  • Broker network I/O increases.
  • Partition log segments grow faster.
  • Replication traffic increases.
  • Page cache and disk write paths carry larger bursts.
  • Consumer fetch requests and processing latency may become unstable.

But this view keeps the problem inside the Kafka cluster. The more interesting part is outside Kafka.

Multiple consumer groups do not make Kafka store the same topic data multiple times. Kafka lets different consumer groups read the same log independently. That is one of its strengths.

But when the payload is a file, the story changes. Inside Kafka, the log is shared. Outside Kafka, each consumer group may store the file payload again for its own purpose.

Imagine a topic named uploaded-video.

consumer groupworkdownstream storage
thumbnail-generatorcreates thumbnailsthumbnail bucket
transcodercreates renditionsvideo rendition bucket
moderation-scannerstores review evidencemoderation evidence store
archive-writerkeeps long-term copyarchive bucket

Inside Kafka, these groups are just reading the same message. But if the message payload is the original file, each group may write that payload again in its own downstream storage. The original payload is amplified once by broker replication, then again by downstream storage copies created by consumer groups.

A simplified model looks like this:

Total file payload pressure
  = producer-side original or temporary file
  + Kafka log x replication factor x retention
  + downstream copies per consumer group
  + retry, reprocessing, failure storage, temporary files

The point is not that Kafka storage grows with the number of consumer groups. Kafka shares the log. The point is that a file payload continues to live as a file after it leaves Kafka. As consumer groups grow, system-wide storage amplification can grow with them.

Raising Limits Is Not the Solution

Kafka has settings that control large messages.

  • producer max.request.size
  • topic max.message.bytes
  • broker default message.max.bytes
  • consumer fetch.max.bytes
  • consumer max.partition.fetch.bytes

If these are not aligned, the producer may fail to send, the broker may reject the batch, or the consumer may fetch inefficiently. So the question “Which settings do I need to increase to send large files?” is natural.

But these settings are not a switch that turns large file transfer into a good design. They only change the limits that allow large record batches to pass.

Once the limits are raised, the next questions arrive immediately.

  • Is producer memory and buffering still healthy?
  • Can broker network threads and request queues absorb the larger requests?
  • Can replication keep up?
  • Does the consumer poll loop remain stable while processing large payloads?
  • How much data is resent when retry happens?
  • Will the DLQ or failure topic also store the same large file payload?
  • Are byte rate, request size, disk write, and consumer lag observed together?

Allowing larger messages is only the start. The operating cost model remains.

Better Pattern: Files in Storage, References in Kafka

In most cases, the better design is to separate the file body from the event.

  1. The producer or upload service stores the file in object storage.
  2. After the upload succeeds, it publishes file metadata and a reference to Kafka.
  3. Consumers read the Kafka event and download the file only when needed.
  4. Each consumer stores only the result it owns.

The Kafka message can look like this:

{
  "eventType": "FileUploaded",
  "fileId": "file_01JZ9M0E4A8R6Z7E3N2Q",
  "bucket": "raw-upload",
  "objectKey": "tenant-a/2026/06/19/file_01JZ9M0E4A8R6Z7E3N2Q.bin",
  "sizeBytes": 73400320,
  "contentType": "video/mp4",
  "sha256": "8d8f4c7e...",
  "createdAt": "2026-06-19T08:20:00Z"
}

This is not a workaround because Kafka is weak. It is a division of responsibility.

databetter placewhy
file bodyobject storagelarge binary data, lifecycle, versioning, range reads, access control
fact that a file existsKafkafast fan-out, replay, independent consumer groups
processing resultconsumer-owned storagethumbnails, scan results, indexes, transformed files
operating statemetrics/logs/tracesthroughput, failure rate, latency, storage cost

With this pattern, Kafka messages stay small and easy to replay. Multiple consumer groups no longer need to drag the same large payload through Kafka. Consumers that need the file can fetch it. Consumers that only need metadata can skip the download.

The Reference Pattern Still Has Edges

Publishing object storage references is not free. A few design questions remain.

  • Did the upload succeed before the Kafka event was published?
  • If Kafka publish succeeds but the producer crashes afterward, can orphan objects be cleaned up?
  • Can consumers see the object when they receive the event?
  • Should the event carry a presigned URL, or should consumers use bucket/key with identity-based access?
  • Is URL or token expiration longer than the retry window?
  • Do object lifecycle rules and Kafka retention agree with each other?
  • Is processing idempotent by fileId?
  • Does the consumer verify the downloaded object with a checksum?

These questions are annoying, but they are usually easier than pushing the file body through Kafka. The file lifecycle belongs to the storage layer. Kafka owns the order and distribution of events around that file.

When Is It Acceptable?

Not every binary payload needs to be banned. Small compressed documents, small thumbnails, protocol buffer payloads, and small encrypted blobs can be perfectly reasonable Kafka messages.

The decision is not only about size.

  • Will several consumer groups store the same payload again as a file?
  • Will retry and DLQ paths copy the same payload again?
  • Will retention make broker storage grow sharply?
  • Does the consumer need large memory buffers to process a single message?
  • Do some consumers only need metadata?
  • Does file lifecycle differ from Kafka retention?

If several answers are yes, send a reference rather than the file.

What to Watch Operationally

This is an architecture decision and an observability problem. When large payloads enter Kafka, message count may look ordinary while byte rate, request size, broker disk writes, replication traffic, and consumer fetch latency look very different.

Watch these signals together.

areasignal
producerrequest size, record size, compression ratio, retry rate
brokerbytes in/out, request latency, disk write, replication lag, rejected bytes
topicretention bytes, segment roll, max message size override
consumerfetch size, processing time, lag, retry, downstream write latency
storageobject put/get latency, storage growth, lifecycle cleanup, failed object count

This operational angle is also central to Konduo. Konduo connects operating targets such as Kafka through plugins so teams can read resource status, metric evidence, and alert response in one operating flow. That connected view matters when the real issue spans Kafka, consumers, and storage rather than a single broker metric.

Conclusion

Kafka handling large-scale traffic does not mean every large payload belongs inside Kafka.

Kafka is good at receiving many events into ordered logs and distributing them to multiple consumers. A large file is different. It already has its own storage lifecycle. If you put it into a Kafka message, broker replication, retention, consumer storage, retry, and failure handling can overlap into system-wide storage amplification.

A useful rule is:

Do not send the file through Kafka.
Send the event that the file exists.

Let object storage own the file body. Let Kafka own the event and metadata around it. That boundary is simpler, cheaper, and easier to operate.

Further Reading

For more context connected to this topic, these posts are also worth reading.