The next source of storage engine performance gains has shifted from compaction policy to the I/O path.
Changing compaction policy to reduce write amplification has long been a standard storage engine optimization. Research and production reports from 2025 and 2026 also show large gains from changing only the I/O path. A tuning decision should separate the gains available from compaction work from those available in the I/O path.
The results use different hardware, workloads, and baselines, so their gains cannot be added. No cited evaluation measures the cumulative effect of applying all layers together. The comparison helps determine where to look for the current bottleneck.
The basic structure of an LSM tree and the origin of write amplification are covered in LSM Trees and Write Amplification. This post builds on that explanation to identify which layer now offers optimization opportunities.
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.
| Observation | First bottleneck to suspect | How to check |
|---|---|---|
| Device bandwidth saturated | Compaction and write amplification | Compare disk writes with application writes |
| Device bandwidth available, CPU saturated | System calls and memory path | Capture a CPU profile and system call counts |
| Remote commit latency | Network I/O path | Measure log flush latency and round trips |
flowchart TD
subgraph ENGINE["Storage engine layer"]
P["Compaction policy<br/>Vertiorizon · EcoTune · ArceKV"]
V["Value placement<br/>Pebble value separation"]
C["Block cache · filters<br/>Mobius · partitioned filter blocks"]
end
subgraph KERNEL["Kernel layer"]
S["System calls · page cache<br/>RESYSTANCE eBPF · io_uring"]
end
subgraph DEVICE["Device · network layer"]
D["Local NVMe SSD"]
N["Remote storage · disaggregated memory<br/>O3-LSM"]
end
P --> V --> C --> S
S --> D
S --> N
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 selects a policy through dynamic programming. It raises average query throughput by 1.5x to 3x over the leveling policy. ArceKV attaches a lightweight decision engine to ElasticLSM. It reports roughly 3x faster performance when read and write ratios shift.
Data placement can also be changed in the algorithm 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 improve performance. 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 |
These results came from changing the execution path without changing the compaction policy. The algorithm and I/O path can therefore be separate optimization candidates. The evaluation does not show that their gains accumulate independently, so applying both requires a separate benchmark.
| Combination | Can be combined by design | Cumulative effect measured in the cited results |
|---|---|---|
| Compaction policy + kernel I/O path | Yes | No |
| Value separation + partitioned filters | Yes | No |
| Cache eviction + remote storage | Yes | No |
Where Production Actually Got Stuck
The more interesting part of the Toss case comes after the write amplification tuning. The application had a saturated CPU, and compaction was falling behind. Profiling showed that 96.2% of the 1,766 collected samples were 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. This 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. However, existing eviction policies rely on coarse-grained locking and complex data structures, which limit concurrent throughput. 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, hardware configuration, and baseline. 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.
| Condition | Likely bottleneck | First action |
|---|---|---|
| Slow device or saturated bandwidth | Device writes | Tune write amplification and compaction |
| Fast device and high system call cost | Software path | Profile I/O calls |
| Cache workload without locality | Eviction algorithm | Validate a workload-specific policy |
| Disaggregated storage | Network commit | Measure the log flush path |
Inspection Order by Layer
Measurement decides the order. Working through the checks below separates which layer deserves the budget.
- Check whether device write bandwidth is saturated. If so, reducing write amplification directly improves performance. Start with compaction policy and the number of active levels.
- If bandwidth remains available but throughput is low, take a CPU profile. System calls and cache misses near the top point to the I/O path.
- Measure the value size distribution. If large values dominate compaction bytes, evaluate value separation.
- If throughput does not scale with thread count, inspect locks in shared cache and queue structures.
- If the network sits in the I/O path, inspect the write commit path first. A larger read buffer does not remove remote log flush latency.
| 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
On fast storage, the I/O path can be as relevant a tuning target as the compaction policy. When the device is slow or saturated, reduce write amplification first. When bandwidth remains available, inspect CPU profiles for system call and cache miss paths.
Each reported gain uses different conditions and a different baseline. Applying several layers together requires a new measurement of the cumulative effect. An operational decision starts by measuring the current bottleneck rather than adding figures from separate evaluations.