Storage Engine Optimization Moves Below the Kernel
The place where a storage engine earns its next unit of performance has moved from compaction policy to the I/O path. Separate what software tuning can buy from what only I/O path investment can buy.
The place where a storage engine earns its next unit of performance has moved from compaction policy to the I/O path.
Changing compaction policy to reduce write amplification has long been the default move in storage engine optimization. Placing the 2025 and 2026 research next to production reports shows a different picture. Several results reached the same order of gain without touching a single line of the algorithm, changing only how the engine talks to the kernel. The decision now requires separating the share that software tuning can earn from the share that only I/O path investment can earn.
The basic structure of an LSM tree and the origin of write amplification are covered in LSM Trees and Write Amplification. This post starts from there and asks which layer the optimization lever has descended into.
The Signal That the Bottleneck Is No Longer at the Top
The RESYSTANCE paper (ICDE 2026, arXiv:2603.05162) states its premise in the first sentence. The spread of fast devices such as NVMe SSDs shifted the primary I/O bottleneck from hardware to software. As devices got faster, the cost of the software stack crossing into and out of the kernel grew in relative terms.
The EcoTune paper (SIGMOD 2025) reaches the same point from another angle. It cites a peak write speed of roughly 45 MB per second in a real Meta workload, while modern NVMe SSDs supply more than 2 GB per second of write bandwidth. When that much write bandwidth is left over, write amplification itself stops constraining write performance. This gap is why the EcoTune authors redefine the goal of a compaction policy as maximizing average query throughput rather than minimizing write amplification.
The two papers solve different problems but stand on the same premise. Device bandwidth is in surplus, and the path taken to reach that bandwidth decides the cost.
What Software Tuning Can Still Earn
Recent results in the algorithm layer are substantial. Vertiorizon (SIGMOD 2025) combines the vertical scheme that adds levels with the horizontal scheme that widens them. Integrated with RocksDB, it incurred about one sixth of the additional space cost of the horizontal scheme. EcoTune treats compaction as a resource investment and picks a policy by dynamic programming, raising average query throughput by 1.5x to 3x over the leveling policy.
ArceKV attaches a lightweight decision engine to ElasticLSM, which removes structural constraints. It reports roughly 3x faster performance when read and write ratios shift.
A lever that changes data placement sits in the same layer. CockroachDB introduced value separation into its storage engine Pebble in v25.4. Large values move to blob files outside the SSTable, and a compaction copies only the value handle. In a benchmark upserting 4 KiB values under a BIGINT primary key, throughput rose about 47% on the same hardware. The same post notes that workloads with smaller values see a smaller gain.
Parameter changes alone also return a meaningful share. Toss approximated write amplification in the RocksDB state backend of Flink as multiplier 10 times the active level count minus one. Disabling the top level cut the active levels from three to two, and write amplification fell from 20 to 10.
| Lever | Example | What it changes | Reported gain |
|---|---|---|---|
| Level growth scheme | Vertiorizon | The direction the tree grows | About 1/6 the extra space cost of the horizontal scheme |
| Compaction policy | EcoTune | Timing and aggressiveness of merges | 1.5x to 3x throughput over leveling |
| Workload adaptation | ArceKV | Policy switching at runtime | About 3x under dynamic workloads |
| Value placement | Pebble value separation | Bytes a compaction copies | About 47% throughput gain on 4 KiB value upserts |
| Parameter tuning | Toss RocksDB | Number of active levels | Write amplification 20 to 10 |
Every gain in this table is tied to a workload assumption. Value separation loses its edge when values are small, and an adaptive structure leaves only decision overhead when the workload is fixed.
Compaction Moved Inside the Kernel
RESYSTANCE touches neither the LSM tree structure nor the compaction algorithm. It measures that background compaction issues a large number of read system calls. It then uses eBPF and io_uring to run the core I/O routines inside the kernel, removing user and kernel space transitions. The evaluation used db_bench, YCSB, and OLTP workloads.
| Metric | Against baseline RocksDB |
|---|---|
| Average system call invocations during compaction | 99% reduction |
| Compaction time | 50% shorter |
| Write-intensive workload throughput | Up to 75% higher |
| p99 latency | 40% reduction |
What makes these numbers support the argument is their location, not their size. No policy changed at all, only the execution path, and the gain landed in the same order as the algorithmic redesigns above. Because the two axes do not overlap, the paper intends this gain to stack on top of the gains in the previous table.
Where Production Actually Got Stuck
The more interesting part of the Toss case comes after the write amplification tuning. Profiling an application whose CPU had saturated while compaction fell behind showed that 96.2% of the 1,766 collected samples sat in the path that reads filter blocks from disk. The bottleneck had nothing to do with compaction policy.
The cause was an I/O path setting. Enabling Direct I/O to make container memory usage predictable under Kubernetes bypasses the OS page cache entirely. A filter block missing from the block cache must then be read from disk every time. With roughly 8 million keys per SST file at 14 bits per key, a single filter block reaches about 15 MB. One cache miss becomes a 15 MB read.
The fix was enabling partitioned-index-filters, which splits the filter block into roughly 4 KB pieces and cut the read per miss by about 2,750 times. That is not an algorithmic change but a change to the path data takes through the kernel and the device. The fundamentals of the page cache and I/O handling are collected in Operating System I/O Management and File Systems.
When the I/O Path Crosses the Network
Separating compute from storage inserts the network into the I/O path. A SIGMOD 2024 empirical study built on PostgreSQL and RocksDB measured this cost stage by stage (checked 2026-09). In the simplest disaggregation, using remote disk with no buffering, reads slowed by 16.4x and writes by 17.9x. An 8 GB buffer reaching an 80% hit ratio narrows the read gap to 1.8x, but writes do not improve no matter how large the buffer grows.
Writes do not respond to buffering because every commit must flush the log remotely. The paper concludes that write performance does not improve significantly even at a 99.5% buffer hit ratio. Murat Demirbas's summary of the paper reads the final write throughput, with every optimization applied, at about 50% of a single node from the charts (an estimate). No amount of tuning in the algorithm layer closes that gap, because the path itself changed.
Other research pushes in the opposite direction. O3-LSM (SIGMOD 2026) uses shared disaggregated memory to offload the memtable, the flush, and the compaction as three layers. Compared with existing disaggregated implementations that offload compaction only, it reports up to 4.5x write throughput. Range query throughput rose up to 5.2x and p99 latency fell by up to 76%.
The Same Shift Happened First in Cache Eviction
The same shift occurred in another component inside the storage engine. S3-FIFO and SIEVE redesigned what to evict and lowered miss ratios. Mobius (SIGMETRICS 2025) came next and removed only lock contention while holding hit ratios comparable. Using two lock-free FIFO queues and a consecutive detection mechanism, it raised concurrent throughput by 1.2x to 8.5x over state-of-the-art methods.
The problem the Mobius authors describe overlaps with the one RESYSTANCE describes. Devices keep getting faster while existing eviction policies fail to deliver concurrent throughput because they rely on coarse-grained locking and complex data structures. The shape is identical: the eviction algorithm stays, the access path changes, and the gain is a multiple. That line of work is covered in detail in FIFO Cache Eviction Replacing LRU.
That Mobius was actually implemented in CacheLib and RocksDB also supports the observation. Cache eviction and compaction are separate subsystems, yet their bottlenecks moved in the same direction.
Conditions Under Which This Argument Fails
First, the argument does not hold when the device is slow. The premise of RESYSTANCE is that the software stack became relatively expensive on fast storage. On spinning disks or low-bandwidth remote volumes the device is still the bottleneck, and there reducing write amplification pays directly.
Second, the algorithm becomes decisive again when a workload breaks its assumptions. The SOLAR study (arXiv:2607.00394) examines the semantic retrieval buffers of LLM agents. In such workloads, which lack temporal locality and frequency concentration, LRU and LFU performed worse than plain FIFO. A learning-augmented replacement approach delivered a 5% to 75% relative improvement over FIFO at tight cache sizes.
Third, the numbers in this post must not be added together. Each came from a different benchmark, different hardware, and a different baseline, and each was confirmed against the paper abstract or public post as of 2026-09. No study measuring the cumulative effect of applying all three layers at once turned up. Non-overlapping axes are a design claim, not a measured fact.
Fourth, I/O path optimization relocates cost rather than removing it. eBPF and io_uring depend on the kernel version, and Direct I/O creates a new cache miss problem, as the Toss case shows. Disaggregated storage ties database availability directly to network availability.
Inspection Order by Layer
Measurement decides the order. Working through the checks below separates which layer deserves the budget.
- Check whether device write bandwidth actually saturates. If it does, reducing write amplification pays directly, so start with compaction policy and the number of active levels.
- If bandwidth is not saturated but throughput is missing, take a CPU profile. System call and cache miss paths near the top point to an I/O path problem.
- Measure the value size distribution. If values of 4 KB or larger make up a meaningful share, value separation delivers at the level of a parameter change.
- If throughput does not scale with thread count, suspect locks on shared data structures. Examine the cache and queue implementations.
- If the network sits in the I/O path, start with the write commit path. Buffering will not solve it.
| Observed signal | Layer to touch | Reference figure |
|---|---|---|
| Write bandwidth saturated, write amplification in double digits | Compaction policy and level count | Toss write amplification 20 to 10 |
| Bandwidth to spare, system calls high in the profile | Kernel I/O path | RESYSTANCE compaction time 50% shorter |
| Large values dominate compaction bytes | Value placement | Pebble throughput about 47% higher |
| Cache misses dominate CPU | Cache structure and filter layout | Toss read per miss about 2,750x lower |
| Throughput flat as threads scale | Concurrency structure | Mobius concurrent throughput 1.2x to 8.5x |
| Remote storage write latency | Architecture | Writes flat as buffers grow, about 50% of a single node (estimate) |
Summary
The place where a storage engine earns its next unit of performance has moved from compaction policy to the I/O path. The evidence is that the multiples reported by recent algorithm-layer research and the multiples earned by changing only the kernel path land in the same order. This shift holds only when the device is fast and the workload has temporal locality, and breaking either condition reverses the judgment. In practice, measure whether device bandwidth saturates first, and if it does not, check the CPU profile for system call and cache miss paths.