1. Introduction
When building real-time streaming architectures with Apache Kafka, streaming directly into cloud storage (like Amazon S3 or Google Cloud Storage) seems straightforward. However, high-throughput topics written with low batch timeouts quickly create millions of micro-files—often under 1 MB each.
This "Small File Problem" leads to two massive issues:
Exploding Cloud Costs: AWS charges per 1,000
PUTrequests ($0.005per 1,000 requests adds up fast when writing 100 files/second).Abysmal Query Speeds: Query engines like AWS Athena, Trino, and Snowflake must open, read, and close thousands of separate file footers, slowing down analytical queries from seconds to minutes.
In this guide, we’ll explore how to configure Kafka Connect (S3 Sink Connector) and PySpark Structured Streaming to batch, compress, and optimize real-time data before it hits long-term storage.
2. Solution Strategy 1: Tuning Kafka Connect S3 Sink
If you are using Kafka Connect, the key is balancing Latency vs. File Size. You should target file sizes between 128 MB and 512 MB per object.
Modify your connect-s3-sink.json configuration with these three parameters:
Why these settings matter:
s3.part.size = 67108864(64 MB): Sets the minimum upload buffer part size for multi-part uploads.flush.size = 100000: Forces a file write only after accumulating 100,000 records.rotate.interval.ms = 300000(5 minutes): Guarantees files are committed at least every 5 minutes so low-volume topics don't leave data stuck in memory forever.
3. Solution Strategy 2: Dynamic Repartitioning in PySpark
If you consume Kafka with PySpark Structured Streaming, simply saving the stream using .writeStream without repartitioning will create one file per Kafka partition for every trigger interval.
To avoid thousands of micro-partitions, use .repartition() or configure Trigger Intervals combined with Snappy-compressed Parquet:
4. Production Best Practices: Compaction Jobs
Even with batching, spike traffic can occasionally produce sub-optimal file sizes. Implement an automated Compaction Job (using Delta Lake OPTIMIZE or PySpark) that runs overnight to rewrite micro-files into uniform 512 MB Parquet files.
