Skip to content

AxonOps — AI-Native Control Plane for Open Source Data Platforms

Filesystem Selection for Kafka

Filesystem choice impacts Kafka’s throughput and latency, particularly for high-volume deployments. This guide covers Kafka’s I/O architecture, filesystem recommendations, and optimization strategies.


Kafka stores all data as append-only log segments on disk.

Log segment files within a topic partitionLog segment files within a topic partitionTopic PartitionSegment 0(oldest)Segment 1Active Segment(current)00000000000000000000.log00000000000000000000.index00000000000000000000.timeindex00000000000000012345.log00000000000000012345.index00000000000000012345.timeindex00000000000000024690.log00000000000000024690.index00000000000000024690.timeindexOnly active segment receives writesSequential append-onlyRolled when size/time threshold reached

File types per segment:

FilePurposeI/O Pattern
.logMessage dataSequential write, sequential/random read
.indexOffset to position mappingSparse writes, memory-mapped reads
.timeindexTimestamp to offset mappingSparse writes, memory-mapped reads

Kafka’s write path is optimized for sequential I/O.

Kafka write path from producer through page cache to diskKafka write path from producer through page cache to diskBrokerNetwork ThreadRequest QueueI/O ThreadPage CacheLog SegmentProducerDiskWrites go to page cache firstOS handles flushing to diskfsync controlled by configurationproduce requestwrite to page cacheasync flushOS writeback

Key characteristics:

  • Writes append to active segment only (sequential)
  • Data written to OS page cache, not directly to disk
  • Configurable fsync behavior (log.flush.interval.messages, log.flush.interval.ms)
  • Default: rely on OS page cache and replication for durability

Kafka uses zero-copy (sendfile) for consumer reads, bypassing user space entirely.

Traditional read copies compared with zero-copy sendfileTraditional read copies compared with zero-copy sendfileTraditional ReadZero-Copy (sendfile)DiskPage CacheUser Buffer(JVM)Socket BufferNICDiskPage CacheSocket BufferNICNo copy to user space~4x fewer copiesRequires page cache1. read2. copy to user3. copy to socket4. send1. read2. DMA to socket3. send

Zero-copy requirements:

  • Data must be in page cache (or will be read from disk)
  • Filesystem must support sendfile() - all modern Linux filesystems do
  • TLS/SSL disables zero-copy (data must be encrypted in user space)

Kafka relies heavily on the OS page cache for performance.

Broker memory split between JVM heap, operating system, and page cacheBroker memory split between JVM heap, operating system, and page cacheMemory AllocationTotal RAM(e.g., 64GB)JVM Heap(6-8GB typical)OS/Kernel(~2GB)Page Cache(remaining ~54GB)Page cache is critical for KafkaCaches log segmentsEnables zero-copy readsShould be majority of RAM

Page cache sizing:

WorkloadRecommended Page CacheRationale
Real-time consumers> active data sizeRecent data served from cache
Catch-up consumersAs large as possibleReduce disk reads for historical data
Mixed workloads50-80% of RAMBalance between heap and cache

XFS is the recommended filesystem for Kafka log directories.

Advantages for Kafka:

FeatureBenefit for Kafka
Allocation groupsParallel writes across multiple log directories
Extent-based allocationEfficient for large sequential segment files
Delayed allocationBetter block placement for append workloads
PreallocationReduces fragmentation during segment growth

XFS behavior with Kafka workloads:

XFS delayed allocation applied to Kafka append writesXFS delayed allocation applied to Kafka append writesKafka Write PatternLog Segment(growing)XFS DelayedAllocationContiguousExtentsDiskXFS buffers allocation decisionsAllocates contiguous extentsOptimal for append-only workloadsappend writesallocate at flushsequential blocks

ext4 is a reasonable alternative, particularly for smaller deployments.

Comparison with XFS:

Aspectext4XFS
Sequential writesGoodExcellent
Parallel I/OLimited (single lock)Excellent (per-AG)
Large filesGood (up to 16TB)Excellent (up to 8EB)
Many directoriesGoodBetter (B+ tree dirs)
Extent coalescingGoodBetter

When ext4 is acceptable:

  • Single log directory (no parallelism benefit from XFS)
  • Smaller deployments (< 1TB per broker)
  • Familiarity and existing tooling

ZFS presents similar challenges for Kafka as for Cassandra.

Issues with Kafka workloads:

ChallengeImpact on Kafka
Copy-on-writeWrite amplification for append workloads
ARC memoryCompetes with page cache
ChecksummingCPU overhead (Kafka has CRC32 already)
CoW fragmentationDegrades sequential read performance over time
ZFS copy-on-write write amplification for Kafka appendsZFS copy-on-write write amplification for Kafka appendsZFS Write AmplificationKafka Append(1 write)ZFS CoW(3+ writes)Effective I/OKafka's append-only patternbecomes random I/O with CoWNegates sequential write benefitssingle appenddata + indirect + uberblock

If ZFS is required:

Terminal window
# Create dataset with Kafka-optimized settings
zfs create -o recordsize=128K \
-o compression=off \
-o atime=off \
-o xattr=sa \
-o primarycache=metadata \
-o logbias=throughput \
tank/kafka
# Limit ARC to leave room for page cache
echo "options zfs zfs_arc_max=4294967296" >> /etc/modprobe.d/zfs.conf # 4GB
FeatureXFSext4ZFS
Sequential writeExcellentGoodPoor (CoW)
Parallel I/OExcellentLimitedGood
Page cache friendlyYesYesCompetes (ARC)
Zero-copy supportYesYesYes
Write amplificationLowLowHigh (2-3x)
Kafka suitabilityExcellentGoodPoor

XFS (recommended):

/etc/fstab
/dev/nvme0n1p1 /kafka/data xfs defaults,noatime,nodiratime 0 2
OptionPurpose
noatimeDisable access time updates (significant for high-throughput)
nodiratimeDisable directory access time updates

ext4:

/etc/fstab
/dev/nvme0n1p1 /kafka/data ext4 defaults,noatime,nodiratime 0 2

XFS:

Terminal window
# Standard formatting (recommended - uses optimal defaults)
mkfs.xfs -f /dev/nvme0n1p1
# Verify filesystem parameters
xfs_info /dev/nvme0n1p1

XFS automatically calculates optimal allocation group count and log size based on device characteristics. Manual tuning is rarely necessary for modern NVMe/SSD storage.

ext4:

Terminal window
# Standard formatting
mkfs.ext4 /dev/nvme0n1p1

Kafka supports multiple log directories for parallelism and capacity.

server.properties
log.dirs=/kafka/data1,/kafka/data2,/kafka/data3,/kafka/data4

Benefits:

  • Distributes I/O across multiple disks
  • XFS allocation groups provide additional parallelism per disk
  • Partitions distributed round-robin across directories
Partitions distributed across multiple log directoriesPartitions distributed across multiple log directoriesBrokerlog.dirsPartitions/kafka/data1(NVMe 1)/kafka/data2(NVMe 2)/kafka/data3(NVMe 3)/kafka/data4(NVMe 4)topic-0topic-1topic-2topic-3Partitions distributed across directoriesEach directory should be separate diskXFS recommended for each mount

Best practices:

  • One filesystem per physical disk (no RAID 0 across directories)
  • Use XFS for each mount point
  • Equal-sized disks for balanced distribution

/etc/sysctl.conf
# Dirty page ratios
vm.dirty_ratio = 80 # Max dirty pages before blocking writes
vm.dirty_background_ratio = 5 # Start background writeback
# Alternative: absolute values for large memory systems
# vm.dirty_bytes = 2147483648 # 2GB max dirty
# vm.dirty_background_bytes = 536870912 # 512MB background threshold
# Swappiness
vm.swappiness = 1 # Minimize swapping (0 can cause OOM)
# Page cache pressure
vm.vfs_cache_pressure = 50 # Retain page cache over dentries/inodes

Parameter explanations:

ParameterRecommendedRationale
vm.dirty_ratio80Allow large dirty cache before blocking producers
vm.dirty_background_ratio5Start flushing early to avoid write stalls
vm.swappiness1Keep data in RAM, minimal swap
vm.vfs_cache_pressure50Favor page cache retention
Terminal window
# For NVMe/SSD (recommended)
echo none > /sys/block/nvme0n1/queue/scheduler
# For SATA SSD
echo deadline > /sys/block/sda/queue/scheduler
# Persistent configuration (/etc/udev/rules.d/60-kafka.rules)
ACTION=="add|change", KERNEL=="nvme[0-9]*", ATTR{queue/scheduler}="none"
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/scheduler}="deadline"
Terminal window
# Check current setting
blockdev --getra /dev/nvme0n1
# Set read-ahead (in 512-byte sectors)
# 0 for NVMe (no benefit)
# 256-4096 for HDDs
blockdev --setra 0 /dev/nvme0n1 # NVMe
blockdev --setra 4096 /dev/sda # HDD (2MB read-ahead)

DeploymentRecommendedNotes
Production (any scale)XFSBest sequential write performance
Small/Devext4 or XFSEither acceptable
Multiple disksXFS per diskLeverage allocation group parallelism
Existing ZFS infrastructureZFS with tuningSee ZFS section for required optimizations

Optimal Kafka filesystem setup:

Terminal window
# Format each disk with XFS
mkfs.xfs -f /dev/nvme0n1
mkfs.xfs -f /dev/nvme1n1
# Mount with optimal options
mount -o noatime,nodiratime /dev/nvme0n1 /kafka/data1
mount -o noatime,nodiratime /dev/nvme1n1 /kafka/data2
# Configure Kafka
# server.properties
log.dirs=/kafka/data1,/kafka/data2

Kernel tuning:

/etc/sysctl.conf
vm.dirty_ratio = 80
vm.dirty_background_ratio = 5
vm.swappiness = 1
vm.vfs_cache_pressure = 50
# Apply
sysctl -p
ConfigurationIssue
ZFS for productionWrite amplification, ARC competition
RAID 0 across log.dirsSingle disk failure loses all data
Small page cacheIncreases disk I/O, disables effective zero-copy
High swappinessJVM and page cache evicted to swap
atime enabledUnnecessary write overhead

Terminal window
# Disk I/O statistics
iostat -xz 1
# Key metrics:
# - %util: Device utilization (< 80% target)
# - await: Average I/O wait time
# - w/s: Writes per second
Terminal window
# Page cache usage
free -h
# Cached column shows page cache size
# Detailed memory info
cat /proc/meminfo | grep -E "Cached|Dirty|Writeback"
# Per-file cache status
vmtouch /kafka/data1/topic-*/*.log
Terminal window
# Check disk usage per log directory
du -sh /kafka/data*
# Check segment distribution
find /kafka/data* -name "*.log" | wc -l
# Verify XFS health
xfs_info /kafka/data1
xfs_repair -n /dev/nvme0n1 # Dry-run check

RecommendationRationale
Use XFS for all log directoriesOptimized for sequential writes, allocation groups enable parallelism
Avoid ZFS for productionCoW overhead, ARC competes with page cache
Configure multiple log.dirs on separate disksDistributes I/O, increases throughput
Tune page cache parametersKafka depends on page cache for performance
Use noatime mount optionEliminates unnecessary metadata writes
Leave majority of RAM for page cacheEnables zero-copy, reduces disk I/O