voonhous commented on code in PR #19320:
URL: https://github.com/apache/hudi/pull/19320#discussion_r3613720632


##########
website/blog/2026-07-17-async-compaction-background-maintenance.mdx:
##########
@@ -0,0 +1,240 @@
+---
+title: "Can a Lakehouse Really Run Maintenance Without Blocking Writes?"
+excerpt: "Async compaction in Hudi is not a performance tweak layered onto 
ingestion — it is the natural consequence of a storage engine that separates 
correctness from optimization, a principle mature databases have followed for 
decades."
+description: "Async compaction in Hudi is not a performance tweak layered onto 
ingestion — it is the natural consequence of a storage engine that separates 
correctness from optimization, a principle mature databases have followed for 
decades."
+authors: [sivabalan]
+category: deep-dive
+image: 
/assets/images/blog/2026-07-17-async-compaction-background-maintenance/mor-separates-correctness-from-optimization.png
+tags:
+- mor
+- merge on read
+- compaction
+- architecture
+- data lakehouse
+- metadata
+- clustering
+---
+
+---
+
+_This is the fourth post in a series on Merge-On-Read as an architectural 
shift in Apache Hudi. The [first 
post](/blog/2026/05/14/mor-isnt-a-storage-optimization-its-an-architectural-shift)
 made the broad case; the 
[second](/blog/2026/06/05/why-metadata-has-to-be-mutation-friendly) showed how 
the metadata table inherits the same append-first model; the 
[third](/blog/2026/06/25/building-indexes-on-a-moving-target) traced how async 
indexing extends the pattern to live index construction. This one follows the 
pattern one step further — into how storage optimization itself becomes an 
independent concern._
+
+---
+
+<div style={{ fontSize: '1.15rem', lineHeight: '1.75' }}>
+
+Every storage system eventually accumulates technical debt. As data is 
continuously written, small files begin to appear, updates scatter across 
existing layouts, indexes drift away from the latest state, and storage 
gradually becomes less efficient for analytical queries. Left unattended, write 
performance deteriorates, read latency increases, and operational costs 
steadily rise. Storage optimization is therefore not an optional feature — it 
is an unavoidable consequence of maintaining a long-lived data system.
+
+The question is **not whether maintenance should happen, but when it should 
happen.**
+
+Traditional database systems answered this question decades ago. They 
established a simple but profound principle: user transactions are responsible 
for correctness, while background maintenance is responsible for efficiency. 
Operations such as 
[VACUUM](https://www.postgresql.org/docs/current/sql-vacuum.html) in 
PostgreSQL, 
[compaction](https://en.wikipedia.org/wiki/Log-structured_merge-tree) in 
LSM-based databases, online index builds, and checkpointing continuously 
improve the storage engine without becoming part of the critical transaction 
path. Applications continue writing data while the storage engine quietly 
reorganizes itself in the background.
+
+The first generation of lakehouse table formats emerged under a different set 
of assumptions. They were designed during a period when most analytical 
datasets were largely append-only, refreshed through scheduled batch pipelines, 
and stored as immutable Parquet files on object storage. Snapshot isolation and 
file replacement naturally became the dominant architectural primitives, 
providing a simple and robust foundation for managing analytical data at scale.
+
+Today's workloads are fundamentally different. Change Data Capture (CDC), 
streaming ingestion, operational analytics, feature stores, and AI pipelines 
have transformed lakehouses into continuously mutating systems. Storage 
optimization is no longer an occasional maintenance task performed after 
nightly ETL jobs — it must coexist with thousands of ongoing updates without 
delaying ingestion or compromising data freshness.
+
+This raises an architectural question that modern databases answered decades 
ago, but that is becoming increasingly relevant for lakehouses:
+
+**Should storage optimization compete with writes, or should it evolve 
independently?**
+
+Apache Hudi's Merge-On-Read architecture approached this question differently 
from the beginning. Introduced in 2017, with asynchronous compaction following 
in 2019, it treated background maintenance not as an optimization layered onto 
the write path, but as a foundational architectural primitive. At the time, 
these capabilities were often viewed as implementation details that improved 
write performance. Looking back, they represented something much deeper: a 
different philosophy for organizing work inside a mutable storage engine.
+
+---
+
+## The Evolution of Background Maintenance
+
+Every long-running storage system eventually converges on the same 
realization: maintaining correctness is only half the problem. The other half 
is maintaining efficiency.
+
+Every storage engine continuously makes local decisions. A newly inserted row 
is written wherever space is available. An updated record is appended to a 
write-optimized structure. An index is modified just enough to preserve 
correctness. Each individual operation is intentionally optimized for low 
latency.
+
+Over time, however, thousands or millions of these local decisions accumulate. 
Data becomes fragmented. Small files proliferate. Obsolete versions remain on 
disk. Physical layouts drift away from what analytical queries would ideally 
prefer.
+
+Left unattended, the storage engine gradually becomes less efficient — not 
because anything is incorrect, but because correctness alone does not guarantee 
an optimal physical layout.
+
+This distinction gave rise to one of the most important architectural ideas in 
modern databases: **background maintenance**.
+
+<div style={{ textAlign: 'center' }}>
+  <img 
src="/assets/images/blog/2026-07-17-async-compaction-background-maintenance/background-maintenance-across-storage-engines.png"
 alt="Background maintenance across storage engines" width="800"/>
+</div>
+
+This philosophy appears across nearly every mature storage engine, although 
the implementation differs.
+
+PostgreSQL periodically runs **VACUUM** to reclaim obsolete row versions 
created by MVCC. LSM-tree based systems such as 
[RocksDB](https://github.com/facebook/rocksdb/wiki/Universal-Compaction), 
[LevelDB](https://github.com/facebook/rocksdb/wiki/Leveled-Compaction), 
Cassandra, and ScyllaDB continuously compact SSTables to reduce read 
amplification and reclaim space. SQL Server and Oracle rebuild indexes online, 
while checkpointing mechanisms asynchronously persist in-memory state without 
delaying foreground transactions.
+
+Although these systems differ substantially in implementation, they all share 
a common architectural principle:
+
+**Foreground operations establish correctness. Background operations restore 
efficiency.**
+
+This separation is remarkably powerful.
+
+A user inserting a row into PostgreSQL does not wait for VACUUM to complete. A 
write into RocksDB is not blocked until multiple SSTables have been compacted 
into a larger one. An online index rebuild does not require applications to 
stop modifying the underlying table.
+
+Instead, user transactions continue making forward progress while the storage 
engine quietly reorganizes itself in the background.
+
+This distinction is easy to overlook because modern databases have made it 
feel ordinary. Yet it represents one of the most important architectural 
lessons learned over decades of storage engine evolution: **maintenance should 
improve the system without becoming part of the critical write path.**
+
+An important consequence of this separation is that maintenance becomes 
schedulable. Storage optimization can run opportunistically when resources are 
available, be throttled during peak ingestion, prioritized for frequently 
accessed data, or even paused temporarily without affecting transactional 
correctness. Once maintenance is decoupled from writes, it becomes another 
independently managed service within the storage engine rather than a 
prerequisite for every mutation.
+
+---
+
+## Two Architectural Philosophies
+
+When transactional lakehouse formats began to emerge, they shared a common 
objective: bringing ACID guarantees to open data lakes.
+
+The architectural paths they took, however, were not identical.
+
+One school of thought naturally extended the strengths of immutable data 
lakes. Immutable files, snapshot isolation, and file replacement became the 
primary mechanisms for coordinating updates while preserving compatibility with 
cloud object storage. This approach provided a simple and elegant foundation 
for analytical workloads that were predominantly batch-oriented, append-heavy, 
and slow-moving.
+
+Apache Hudi approached the problem from a different perspective.
+
+Rather than asking how immutable files could support transactions, it asked a 
different question:
+
+**How can a data lake behave more like a database while retaining the openness 
of object storage?**
+
+That seemingly small shift in perspective led to a different set of 
architectural primitives.
+
+Merge-On-Read, introduced in 2017, established append-first mutation as the 
primary write path. Asynchronous compaction, introduced in 2019, separated 
storage optimization from transactional correctness by allowing physical layout 
optimization to proceed independently of ingestion.
+
+At the time, these capabilities were often viewed primarily as performance 
optimizations. The dominant workloads across many lakehouses were still 
batch-oriented, and continuously mutating datasets had not yet become 
commonplace.
+
+In retrospect, they represented something much more fundamental.
+
+They embodied the same architectural principle that had long existed in 
database storage engines:
+
+**Correctness should be established immediately. Optimization should happen 
independently.**
+
+Only in recent years, with the widespread adoption of CDC pipelines, streaming 
ingestion, feature stores, and AI applications, has the significance of that 
separation become much easier to appreciate.
+
+---
+
+## The Workloads Changed
+
+For many years, the dominant workloads in data lakes were largely 
append-oriented. Data was periodically ingested through scheduled ETL 
pipelines, analytical reports were refreshed in batches, and updates to 
existing records were relatively infrequent. Under these conditions, the 
primary challenge was bringing transactional guarantees to immutable data 
stored on object stores. The architectural primitives adopted by early 
lakehouse systems reflected these priorities.
+
+Over the past decade, however, the role of the lakehouse has steadily expanded.
+
+Instead of serving primarily as the final destination for analytical data, it 
has increasingly become the operational data platform itself. Change Data 
Capture (CDC) pipelines continuously synchronize operational databases into the 
lakehouse. Streaming applications produce an uninterrupted flow of events. 
Feature stores constantly update machine learning features. AI systems 
continuously generate embeddings, observations, and feedback signals that 
evolve throughout the lifecycle of a model. Rather than being refreshed 
periodically, datasets have become living systems that are expected to evolve 
continuously.
+
+This shift fundamentally changes what the storage engine must optimize for.
+
+The challenge is no longer simply storing immutable files efficiently. It is 
sustaining a continuous stream of mutations while simultaneously preserving the 
physical organization required for efficient analytics.
+
+Those two objectives often pull the storage engine in opposite directions.
+
+Applications want every update to become durable immediately. Analytical 
queries prefer well-organized, compacted, and clustered data layouts. Indexes 
need to reflect the latest state of the table. Metadata must remain 
synchronized. Statistics need to be refreshed. None of these activities can be 
ignored indefinitely, yet forcing them to occur as part of every write steadily 
increases ingestion latency and makes maintenance compete directly with 
foreground work.
+
+This is precisely the challenge that background maintenance was designed to 
solve.
+
+Rather than requiring every mutation to produce an optimal physical layout, a 
mutable storage engine can establish correctness first and improve efficiency 
later. The storage engine continues accepting writes while independent 
background services gradually reconcile the physical representation of the 
table.
+
+This architectural principle is not unique to databases, nor is it unique to 
Apache Hudi. What is noteworthy is that Merge-On-Read adopted this philosophy 
several years before continuously mutating lakehouse workloads became 
commonplace. Introduced in 2017, with asynchronous compaction following in 
2019, it treated storage optimization as work that could evolve independently 
from ingestion rather than as a prerequisite for every successful write.
+
+At the time, this distinction was easy to overlook.
+
+Today, it is becoming one of the defining characteristics of modern mutable 
lakehouse architectures.
+
+---
+
+## Separating Correctness from Optimization
+
+One of the most important consequences of continuously mutating data is that 
correctness and optimization no longer need to happen at the same time.
+
+For many years, storage engines largely treated these two objectives as 
inseparable. A successful write not only had to make new data visible, but also 
leave the physical representation of the table in a state suitable for future 
reads. As long as mutations were relatively infrequent, this coupling was a 
perfectly reasonable tradeoff. Every successful write incrementally moved the 
table toward its next optimized state.
+
+As mutation frequency increases, however, this coupling becomes increasingly 
expensive.
+
+Every write now carries two responsibilities. First, it must establish the 
correctness of the new state. Second, it must participate in maintaining an 
efficient physical layout for future reads. These responsibilities serve 
different goals, compete for the same resources, and often operate on the same 
physical data.
+
+Modern database systems solved this tension decades ago by recognizing that 
these responsibilities need not be coupled. User transactions establish 
correctness immediately. Storage optimization becomes an independent concern 
that can be performed later, when resources permit, without affecting the 
visibility or correctness of committed data.
+
+Apache Hudi's Merge-On-Read architecture adopts the same principle.
+
+<div style={{ textAlign: 'center' }}>
+  <img 
src="/assets/images/blog/2026-07-17-async-compaction-background-maintenance/mor-separates-correctness-from-optimization.png"
 alt="Merge-On-Read separates correctness from optimization" width="800"/>
+</div>
+
+Instead of treating every write as both a mutation and a storage optimization 
event, Merge-On-Read separates them into two independent stages. Incoming 
updates are durably recorded first, making them immediately visible through the 
transactional timeline. Physical layout optimization is deferred to independent 
background services that reorganize storage without becoming part of the 
critical write path.
+
+This distinction is subtle, but profound.
+
+Merge-On-Read is often described as a storage format consisting of base files 
and log files. While technically accurate, that description misses the 
architectural motivation behind the design. Log files are not merely a 
different physical representation of data; they are the mechanism that allows 
correctness and optimization to evolve independently. They provide a place 
where new mutations can accumulate while background services gradually 
reconcile them into optimized storage layouts.
+
+Once this separation exists, an entirely different storage architecture 
becomes possible.
+
+Compaction is no longer required before new writes can proceed. Clustering can 
reorganize layouts independently of ingestion. Secondary indexes can evolve 
without delaying mutations. Each service becomes responsible for improving one 
aspect of the storage engine while leaving the critical write path focused on a 
single objective: making new data correct and visible as quickly as possible.
+
+Background maintenance is therefore not a feature layered on top of 
Merge-On-Read. It is a direct consequence of the architectural separation 
between correctness and optimization.
+
+This architectural distinction is more than an implementation detail. It 
fundamentally changes how work is organized inside the storage engine. 
Foreground writes focus exclusively on establishing new transactional state, 
while background services continuously improve the physical representation of 
the table without becoming part of the critical write path.
+
+Architectural principles are ultimately judged not by their elegance, but by 
the behavior they produce under real workloads. Does separating correctness 
from optimization simply produce a cleaner design, or does it fundamentally 
change the behavior of a storage engine under continuous mutation?
+
+That question naturally leads us from architectural principles to experimental 
validation.
+
+---
+
+## From Architectural Principle to Experimental Validation
+
+Architectural ideas are ultimately valuable only if they change how a system 
behaves under real workloads.
+
+Up to this point, we've argued that separating correctness from optimization 
allows foreground writes and background maintenance to evolve independently. 
The natural question is whether that architectural separation produces a 
measurable difference once storage engines begin handling continuously mutating 
data.
+
+Answering that question requires a different kind of benchmark.
+
+Traditional storage benchmarks typically compare write latency, read 
performance, or throughput. While those metrics are useful, they don't fully 
capture the architectural property we've been discussing throughout this 
article. The more fundamental question is **whether a storage engine can 
continue making steady forward progress while background maintenance executes 
concurrently.**
+
+The benchmark is intentionally simple in concept. Foreground ingestion 
continuously mutates the table while background services optimize its physical 
layout. Rather than measuring the latency of an individual write, we observe 
whether ingestion continues progressing as maintenance runs in parallel.
+
+<div style={{ textAlign: 'center' }}>
+  <img 
src="/assets/images/blog/2026-07-17-async-compaction-background-maintenance/benchmark-conceptual-setup.png"
 alt="Conceptual illustration of the experimental setup" width="800"/>
+</div>
+
+<div style={{ textAlign: 'center', fontStyle: 'italic', fontSize: '0.95rem', 
marginTop: '-1rem', marginBottom: '1.5rem' }}>
+  Conceptual illustration of the experimental setup. The detailed benchmark 
methodology and interpretation are presented in the companion article.
+</div>
+
+The remainder of this series explores this question through a detailed 
benchmark of Apache Hudi, Apache Iceberg, and Delta Lake under identical 
continuous-ingestion workloads. Rather than focusing solely on throughput or 
latency, the study examines how different architectural choices influence a 
storage engine's ability to sustain forward progress while background 
maintenance is active.
+
+We'll cover the benchmark design, workload, methodology, and analysis in the 
next article.
+
+---
+
+## Background Maintenance Is Bigger Than Compaction
+
+The benchmark will answer an important question about asynchronous compaction. 
But compaction itself is only one manifestation of a much broader architectural 
idea. Once a storage engine separates correctness from optimization, storage 
optimization itself becomes an independent concern rather than an extension of 
every write. The architecture no longer asks every mutation to leave the table 
in its ideal physical state. Instead, it allows specialized background services 
to continuously improve different aspects of the system over time.
+
+Compaction is one such service.
+
+Clustering is another, reorganizing data layouts to improve query locality 
without interrupting foreground ingestion. Metadata maintenance can evolve 
independently as new commits arrive rather than requiring expensive 
reconstruction during reads.
+
+Seen through this lens, asynchronous compaction is not an isolated feature. It 
is one manifestation of a storage engine that has embraced background 
maintenance as a first-class primitive.
+
+This observation also explains a common theme across the previous articles in 
this series.
+
+The Merge-On-Read architecture is often introduced through individual 
capabilities: [Metadata 
Table](/blog/2026/06/05/why-metadata-has-to-be-mutation-friendly), 
[asynchronous indexing](/blog/2026/06/25/building-indexes-on-a-moving-target), 
compaction, or Non-Blocking Concurrency Control. While each solves a different 
problem, they all emerge from the same architectural philosophy.
+
+The critical write path should establish correctness and little else.
+
+Everything that improves the storage engine without affecting correctness 
should evolve independently whenever possible.
+
+This is precisely the philosophy that mature database systems have followed 
for decades. As lakehouses increasingly become continuously mutating data 
platforms rather than repositories of mostly immutable analytical datasets, the 
same architectural principles are becoming increasingly relevant.
+
+Merge-On-Read and asynchronous compaction were introduced into Apache Hudi 
years before today's CDC pipelines, streaming applications, and AI workloads 
became commonplace. At the time, these capabilities were often viewed primarily 
as implementation techniques for improving ingestion performance. Looking back, 
they represented something much more fundamental: the adoption of a 
storage-engine philosophy that separates correctness from optimization.
+
+As the industry continues to move toward continuously evolving datasets, the 
question is no longer whether background maintenance belongs in a lakehouse. 
The question is how completely the storage engine embraces it.
+
+That architectural principle is the central idea of this article. But 
architectural principles ultimately matter only if they change how a system 
behaves under real workloads. Does separating correctness from optimization 
actually allow a storage engine to sustain continuous forward progress while 
background maintenance is running, or does maintenance inevitably interfere 
with foreground ingestion?
+
+In the next article, we'll explore that question through a detailed 
benchmarking study. Rather than focusing on traditional throughput or latency 
metrics, we'll examine how different lakehouse architectures behave when 
continuous ingestion and background maintenance execute concurrently, and why 
measuring continuous forward progress reveals an important dimension of mutable 
storage systems.

Review Comment:
   Concretely, the cuts I'd make:
   
   - **2017/2019 framing once, in the intro.** Then drop: the "At the time, 
these capabilities were often viewed primarily as performance optimizations... 
Only in recent years..." paragraphs closing *Two Architectural Philosophies* 
(keep the bolded principle as the section close), the "Introduced in 2017, with 
asynchronous compaction following in 2019" sentence near the end of *The 
Workloads Changed*, and the whole "Merge-On-Read and asynchronous compaction 
were introduced into Apache Hudi years before..." paragraph in the final 
section.
   - **Workloads story once.** Let *The Workloads Changed* own it: compress the 
intro's "Today's workloads are fundamentally different" paragraph to a single 
forward-pointing sentence, and drop "The dominant workloads across many 
lakehouses were still batch-oriented..." from *Two Architectural Philosophies*.
   - **Closing question once.** Keep it where *Separating Correctness from 
Optimization* ends (it's the natural bridge into the benchmark section); drop 
"Architectural ideas are ultimately valuable only if..." (the very next line 
restates it) and the "That architectural principle is the central idea... But 
architectural principles ultimately matter only if..." paragraphs at the end -- 
the italic *Coming next* footer already carries the teaser.
   
   That's roughly 50-60 of 240 lines, and every point still gets made once.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to