This is an automated email from the ASF dual-hosted git repository.

vinothchandar pushed a commit to branch asf-site
in repository https://gitbox.apache.org/repos/asf/hudi.git


The following commit(s) were added to refs/heads/asf-site by this push:
     new 542a37e8c0fc docs(blog): XTable interop post and Parquet/Hive 
migration guides (#19271)
542a37e8c0fc is described below

commit 542a37e8c0fc29f327521fa09aaf87878833d1f6
Author: vinoth chandar <[email protected]>
AuthorDate: Tue Jul 28 11:55:24 2026 +0530

    docs(blog): XTable interop post and Parquet/Hive migration guides (#19271)
---
 ...-efficient-migration-of-large-parquet-tables.md |   4 +
 ...28-using-hudi-with-apache-iceberg-via-xtable.md | 149 +++++++++++++++
 .../2026-07-29-migrating-from-parquet-to-hudi.md   | 193 +++++++++++++++++++
 .../blog/2026-07-30-migrating-from-hive-to-hudi.md | 207 +++++++++++++++++++++
 website/src/pages/faq/general.md                   |   2 +-
 website/static/llms.txt                            |   3 +
 6 files changed, 557 insertions(+), 1 deletion(-)

diff --git 
a/website/blog/2020-08-20-efficient-migration-of-large-parquet-tables.md 
b/website/blog/2020-08-20-efficient-migration-of-large-parquet-tables.md
index 99fa067e1176..4c56bb11922d 100644
--- a/website/blog/2020-08-20-efficient-migration-of-large-parquet-tables.md
+++ b/website/blog/2020-08-20-efficient-migration-of-large-parquet-tables.md
@@ -14,6 +14,10 @@ last_update:
 
 We will look at how to migrate a large parquet table to Hudi without having to 
rewrite the entire dataset. 
 
+:::info Updated guide available
+For a current, step-by-step walkthrough of all migration paths — including 
bootstrap and full rewrite — see [Migrating from Parquet to Apache 
Hudi](/blog/2026/07/29/migrating-from-parquet-to-hudi).
+:::
+
 <!--truncate-->
 ## Motivation:
 
diff --git 
a/website/blog/2026-07-28-using-hudi-with-apache-iceberg-via-xtable.md 
b/website/blog/2026-07-28-using-hudi-with-apache-iceberg-via-xtable.md
new file mode 100644
index 000000000000..4937c7cf8f24
--- /dev/null
+++ b/website/blog/2026-07-28-using-hudi-with-apache-iceberg-via-xtable.md
@@ -0,0 +1,149 @@
+---
+title: "Using Apache Hudi with Apache Iceberg: Interoperability via Apache 
XTable"
+excerpt: "Choosing Apache Hudi does not mean giving up Apache Iceberg 
compatibility. Apache XTable translates Hudi table metadata into Iceberg in 
place, so one copy of data serves every engine."
+description: "How Apache XTable lets Iceberg engines and catalogs read Hudi 
tables as Iceberg by translating table metadata in place — no data copies, no 
rewrites."
+authors: [sivabalan]
+category: how-to
+image: /assets/images/hudi_stack/pluggable_tf.png
+tags:
+- apache xtable
+- apache iceberg
+- interoperability
+- data lakehouse
+- table format
+---
+
+Yes — Apache Iceberg engines and catalogs can read Apache Hudi tables. [Apache 
XTable](https://xtable.apache.org) (incubating) translates Hudi table metadata 
into Apache Iceberg (and Delta Lake) metadata in place, so a single copy of 
data on object storage is readable as any of the three formats. No data is 
copied or rewritten; XTable reads the Hudi table's metadata and writes out the 
equivalent Iceberg metadata alongside the same Parquet files.
+
+This matters because many teams believe they face a binary choice. Their 
streaming ingestion, CDC pipelines, and update-heavy workloads point toward 
Hudi's write-side strengths, but a query engine, BI tool, or managed service in 
their stack only speaks Iceberg — so they conclude they must give up one to 
keep the other. They don't. This post explains how XTable dissolves that 
constraint, walks through exposing a Hudi table as Iceberg step by step, and 
covers the limitations you should und [...]
+
+## The Format Lock-In Problem
+
+An [open table format](/blog/2026/07/14/what-is-an-open-table-format) is the 
metadata layer that turns Parquet files on object storage into a transactional 
table — the load-bearing component of the [data 
lakehouse](/blog/2024/07/11/what-is-a-data-lakehouse) architecture. Apache 
Hudi, Apache Iceberg, and Delta Lake all implement this idea, and all three 
ultimately describe the same thing: a set of Parquet data files plus metadata 
recording which files form the table, what schema they foll [...]
+
+The friction arises at the edges of the ecosystem. Some engines and managed 
services support only one format for external tables — most commonly Iceberg, 
given its broad catalog and vendor ecosystem. If your organization has 
standardized its serving layer on such an engine, every table you want to query 
there apparently needs to be an Iceberg table.
+
+At the same time, Hudi's design center is the write path. Teams pick Hudi for 
fast upserts and deletes backed by [pluggable, multi-modal 
indexing](/docs/indexes), streaming and CDC ingestion, incremental processing, 
and built-in [table services](/docs/hudi_stack) — compaction, clustering, 
cleaning — that keep tables optimized without separate orchestration. Giving 
those up to satisfy a read-side format requirement is a real cost, paid on 
every pipeline, every day.
+
+The choice is false because the formats differ in metadata, not data. If the 
Parquet files can stay put and only the metadata needs a second representation, 
no migration is required — just a translation. That is precisely what Apache 
XTable does.
+
+## What Is Apache XTable?
+
+[Apache XTable](https://xtable.apache.org) is an open source project 
incubating at the Apache Software Foundation (it was previously known as 
OneTable). In the project's own words, it provides "cross-table 
omni-directional interop between lakehouse table formats." Two properties 
define it:
+
+- **It is not another table format.** XTable introduces no new specification 
for engines to adopt. It provides abstractions and tools for translating 
existing table format metadata between Apache Hudi, Apache Iceberg, and Delta 
Lake.
+- **It translates metadata, not data.** XTable reads the existing metadata of 
your table and writes out metadata for one or more other table formats into the 
same table directory. The Parquet data files are never copied, moved, or 
rewritten.
+
+Any of the three formats can act as the source, and you can target one or 
several formats in a single sync. For this post's scenario, the source is Hudi 
and the target is Iceberg — but the same mechanics work Iceberg-to-Hudi, 
Delta-to-Iceberg, and every other direction.
+
+The Hudi community treats this as a first-class interoperability path: the 
[XTable sync documentation](/docs/syncing_xtable) covers it, and Hudi 1.1's 
pluggable table format work goes further by letting XTable supply format 
adapters inside Hudi's own write path (more on that below).
+
+## How It Works: Metadata Translation, Not Data Movement
+
+Conceptually, every sync run does three things:
+
+1. **Read the source metadata.** XTable reads the Hudi table's timeline and 
metadata to determine the current state of the table: which data files are 
live, the schema, partition information, and file-level column statistics.
+2. **Translate to the target model.** That state is mapped into Iceberg's 
metadata model — snapshots, manifests, and table metadata files describing the 
very same Parquet files.
+3. **Write target metadata alongside.** The Iceberg metadata is written under 
the table's base path (in the standard `metadata/` directory Iceberg readers 
expect), next to Hudi's `.hoodie` directory. One directory on storage, two 
formats' views of it.
+
+The translation carries more than the file list. Data files are synced along 
with their column-level statistics and partition metadata, so Iceberg readers 
keep the file-skipping benefits they expect from Iceberg's own statistics. 
Schema updates in the source are reflected in the target table metadata. XTable 
also performs format-appropriate metadata maintenance on the target — for 
example, snapshot expiration for Iceberg targets — so translated metadata 
doesn't grow without bound.
+
+XTable supports two sync modes. **Full sync** recomputes the target metadata 
from the source table's current state. **Incremental sync** translates only the 
changes since the last sync, which is more lightweight and performs better, 
especially on large tables; if incremental sync can't proceed for some reason, 
XTable automatically falls back to a full sync. In practice you run incremental 
sync on a schedule (or per commit), and correctness is preserved either way.
+
+## Hands-On: Exposing a Hudi Table as Iceberg
+
+Suppose you have a Hudi table of orders at `s3://warehouse/orders`, written by 
a streaming pipeline (Hudi tables created with 0.14.0 or later are supported). 
Exposing it as Iceberg takes a config file and one command.
+
+First, get the XTable utilities jar — build it from 
[source](https://github.com/apache/incubator-xtable) or download it from the 
project's GitHub packages. Then describe the translation in a YAML file:
+
+```yaml title="my_config.yaml"
+sourceFormat: HUDI
+targetFormats:
+  - ICEBERG
+datasets:
+  - tableBasePath: s3://warehouse/orders
+    tableName: orders
+    partitionSpec: order_date:VALUE
+```
+
+`sourceFormat` names the format to read, `targetFormats` lists one or more 
formats to produce (you could add `DELTA` to the list to get both at once), and 
each entry under `datasets` points at a table. `partitionSpec` tells XTable how 
the Hudi table is partitioned so it can map partitions into Iceberg's partition 
spec.
+
+Run the sync:
+
+```shell
+java -jar path/to/xtable-utilities-bundled.jar --datasetConfig my_config.yaml
+```
+
+When the run completes, the table's base path contains Iceberg metadata files 
— schema, commit history, partitions, and column statistics — describing the 
same Parquet files Hudi manages. Re-running the command picks up new Hudi 
commits incrementally. You can batch many tables into one config, and schedule 
the job with whatever orchestrator you already use.
+
+### Continuous sync from the ingestion pipeline
+
+If the table is fed by [Hudi Streamer](/docs/hoodie_streaming_ingestion), you 
can sync every commit as it lands instead of running a separate job. Add the 
XTable [extensions 
jar](https://github.com/apache/incubator-xtable/tree/main/hudi-support/extensions)
 to the classpath, add `org.apache.xtable.hudi.sync.OneTableSyncTool` to the 
pipeline's sync classes, and configure the targets:
+
+```
+hoodie.onetable.formats.to.sync=ICEBERG
+hoodie.onetable.target.metadata.retention.hr=168
+```
+
+With this in place, the Iceberg view advances in lockstep with Hudi commits, 
and the freshness gap between the two views effectively disappears.
+
+## Registering with Catalogs So Iceberg Engines Find the Table
+
+Producing Iceberg metadata is half the job; Iceberg-speaking engines discover 
tables through a catalog, so the synced table needs to be registered. XTable's 
[catalog integration docs](https://xtable.apache.org/docs/catalogs-index) cover 
registering synced target tables with Hive Metastore, AWS Glue Data Catalog, 
Unity Catalog, and BigLake Metastore — registration is an explicit step after 
the sync. XTable also supports keeping table metadata synchronized across 
catalogs such as Hive Meta [...]
+
+Once registered, the table is, from the engine's point of view, simply an 
Iceberg table. Cloud warehouses and services that can query Iceberg tables — 
Snowflake, Google BigQuery, Amazon Athena and Redshift, among others — can read 
it through their Iceberg support, subject to each vendor's own capabilities and 
requirements. Distributed SQL engines like Trino and Presto query it through 
their Iceberg connectors. None of them need to know the table is written by 
Hudi.
+
+Hudi separately ships its own [catalog sync tools](/docs/syncing_metastore) 
for the Hudi-native view of the table, so the same data can be discoverable 
both as a Hudi table (for engines with Hudi support) and as an Iceberg table 
(for everything else).
+
+## What This Architecture Unlocks
+
+Put together, the pattern looks like this: write once with Hudi, serve 
everywhere.
+
+- **Ingestion** uses Hudi's strengths — record-level indexes for fast upserts 
and deletes, streaming and CDC ingestion, non-blocking table services, 
incremental pulls for downstream pipelines. See [table 
types](/docs/table_types) for how Copy-on-Write and Merge-on-Read trade write 
latency against read cost.
+- **Storage** holds exactly one copy of the data, as Parquet files on object 
storage, with both Hudi and Iceberg metadata describing it.
+- **Serving** spans every engine in the organization: Hudi-native engines read 
the Hudi view; Iceberg-only engines and services read the Iceberg view; nothing 
is exported, duplicated, or re-ingested.
+
+There is no second pipeline to operate, no divergence between "the Hudi copy" 
and "the Iceberg copy," and no per-engine storage bill. Format choice stops 
being an organization-wide standardization battle and becomes a per-workload 
decision about write-path capabilities.
+
+This direction is also converging with Hudi itself. Starting with Hudi 1.1, a 
[pluggable table format framework](/docs/hudi_stack) decouples Hudi's storage 
engine — timeline, indexes, concurrency control, table services — from the 
metadata format written for data files, with XTable supplying format adapters 
for Iceberg and Delta Lake. The trajectory is that maintaining Iceberg metadata 
becomes part of the Hudi write path itself, rather than a companion sync.
+
+![Hudi storage engine with pluggable format adapters via Apache 
XTable](/assets/images/hudi_stack/pluggable_tf.png)
+<p align = "center">Figure: Hudi's storage engine with format adapters for 
Iceberg and Delta Lake via Apache XTable</p>
+
+## Honest Limitations
+
+XTable is a pragmatic tool, and it's worth being precise about its boundaries.
+
+- **It's read-side interoperability.** The translated Iceberg metadata gives 
Iceberg engines a read view of the table. Writes should continue to go through 
Hudi; XTable does not merge concurrent writes made independently in two formats 
to the same files.
+- **Freshness trails the sync cadence.** The Iceberg view reflects the table 
as of the last sync, so it lags the latest Hudi commit by up to the sync 
interval. Per-commit sync via the Hudi Streamer extension closes this gap; a 
nightly cron does not. Decide the cadence based on how fresh the Iceberg 
consumers need to be.
+- **Merge-on-Read log files aren't translated.** XTable syncs the underlying 
Parquet base files; Hudi log files (and, in the other directions, Delta 
deletion vectors and Iceberg delete files) are not captured. For a Hudi MoR 
table, the target format therefore sees the read-optimized view — records still 
sitting in log files become visible to Iceberg readers after compaction. 
Copy-on-Write tables don't have this caveat.
+- **Source table requirements.** XTable requires Hudi 0.14.0 or later and 
depends on Hudi's metadata table; check the [XTable 
docs](https://xtable.apache.org/docs/features-and-limitations) for current 
prerequisites and configuration.
+- **Feature-mapping edge cases exist.** The formats are not feature-identical, 
and format-specific constructs don't always have an exact counterpart on the 
other side (for example, Delta generated columns as a source have limited 
support). Each format's advanced features work fully only in that format's 
native engines.
+
+None of these undermine the core pattern — most production uses are exactly 
"Hudi writes, Iceberg engines read" — but they should inform table type, sync 
cadence, and which features you rely on across the boundary.
+
+## XTable vs Actually Migrating Formats
+
+XTable also answers the "convert Hudi to Iceberg" question, but it's worth 
distinguishing two intents:
+
+- **You need Iceberg read compatibility while keeping Hudi's write path.** Use 
XTable in continuous incremental sync mode, as described above. This is the 
common case, and nothing is migrated — both views persist indefinitely.
+- **You genuinely want to switch formats.** XTable can serve as a low-risk 
migration mechanism: sync the table, repoint readers at the Iceberg view, 
validate, and only then move writers to an Iceberg-native write path — all 
without rewriting data files. Because the translation is omni-directional, the 
door swings both ways: teams migrating an Iceberg or Delta table *to* Hudi to 
gain its ingestion and table-service capabilities follow the same steps with 
source and target swapped.
+
+The practical takeaway from the [open table format 
landscape](/blog/2026/07/14/what-is-an-open-table-format) applies here: pick 
the format whose write path fits each workload, and let interoperability handle 
the rest. Migration becomes a repointing exercise, not a data-movement project.
+
+## Conclusion
+
+The premise behind "we can't use Hudi because our engine only reads Iceberg" 
no longer holds. Hudi, Iceberg, and Delta Lake all describe Parquet files with 
metadata, and Apache XTable translates that metadata in any direction — 
incrementally, in place, without copying data. A table written with Hudi's 
indexing, streaming ingestion, and table services can be registered in a 
catalog and queried by any Iceberg-capable engine as an ordinary Iceberg table, 
while Hudi-native engines keep the f [...]
+
+To try it, start with the [Hudi XTable sync guide](/docs/syncing_xtable) and 
the [Apache XTable documentation](https://xtable.apache.org).
+
+## FAQ
+
+<PostFAQ heading={null} items={[
+  {question: 'Can Iceberg engines read Hudi tables?', answer: 'Yes. Apache 
XTable translates a Hudi table\'s metadata into Apache Iceberg metadata written 
alongside the same Parquet data files. Once that Iceberg metadata is registered 
in a catalog, any engine with Iceberg read support can query the table as an 
ordinary Iceberg table.'},
+  {question: 'Can Snowflake read Hudi tables?', answer: 'Not directly, but 
Snowflake can query Iceberg tables, and Apache XTable can expose a Hudi table 
as Iceberg by translating its metadata in place. After syncing with XTable and 
registering the Iceberg metadata, Snowflake reads the table through its Iceberg 
support, subject to Snowflake\'s own Iceberg capabilities and requirements.'},
+  {question: 'Does XTable copy my data?', answer: 'No. XTable translates only 
table metadata. It reads the source format\'s metadata and writes out the 
target format\'s metadata into the same table directory, while the Parquet data 
files stay exactly where they are. One copy of data serves all synced 
formats.'},
+  {question: 'Can I convert a Hudi table to Iceberg?', answer: 'Yes. Running 
XTable with sourceFormat HUDI and targetFormats ICEBERG produces complete 
Iceberg metadata for the table without rewriting any data files. You can keep 
both views in sync continuously, or use the translation as a migration step by 
repointing readers and writers to the Iceberg view after validating it.'},
+  {question: 'Is Apache XTable production ready?', answer: 'Apache XTable is 
an incubating project at the Apache Software Foundation, which is a statement 
about ASF governance maturity rather than code quality. It is used in real 
deployments and its metadata-only design is low risk since source data and 
metadata are never modified, but you should validate it against your own tables 
and review the documented limitations, such as Merge-on-Read log files not 
being captured, before relying o [...]
+  {question: 'Does XTable work with Hudi Merge-on-Read tables?', answer: 
'Partially. XTable syncs the Parquet base files but not Hudi log files, so the 
Iceberg view of a Merge-on-Read table corresponds to the read-optimized view. 
Records still in log files become visible to Iceberg readers after compaction. 
Copy-on-Write tables do not have this caveat.'},
+]} />
diff --git a/website/blog/2026-07-29-migrating-from-parquet-to-hudi.md 
b/website/blog/2026-07-29-migrating-from-parquet-to-hudi.md
new file mode 100644
index 000000000000..157b16586828
--- /dev/null
+++ b/website/blog/2026-07-29-migrating-from-parquet-to-hudi.md
@@ -0,0 +1,193 @@
+---
+title: "Migrating from Parquet to Apache Hudi: A Practical Guide"
+excerpt: "A step-by-step guide to migrating existing Parquet datasets to 
Apache Hudi — choosing between in-place bootstrap and full rewrite, running the 
migration, and validating the result."
+description: "How to migrate Parquet tables to Apache Hudi: in-place bootstrap 
vs full rewrite with bulk_insert, key and partitioning choices, code examples, 
validation and rollback."
+authors: [sivabalan]
+category: how-to
+image: 
/assets/images/blog/2024-01-20-Data-Engineering-Bootstrapping-Data-lake-with-Apache-Hudi.png
+tags:
+- migration
+- bootstrap
+- apache parquet
+- apache spark
+- guide
+---
+
+You can migrate existing Parquet datasets to Apache Hudi either in place — 
using Hudi's bootstrap operation, which adds Hudi metadata without rewriting 
data files — or by rewriting the data through a one-time bulk insert. Which 
path you take comes down to how large the table is, how much rewrite cost and 
downtime you can absorb, and how the table will be written to afterwards. This 
guide walks through both paths end to end: choosing a strategy, making the 
up-front design decisions that a [...]
+
+<!--truncate-->
+
+Why migrate at all? A directory of Parquet files is a perfectly good archive, 
but it is not a table. It cannot accept updates or deletes without rewriting 
whole partitions, it offers no transactional guarantees to concurrent readers 
and writers, and downstream consumers must rescan everything to find what 
changed. Moving that data under Hudi management gets you [upserts and 
deletes](/blog/2026/07/15/what-is-upsert-on-a-data-lake) keyed on individual 
records, ACID commits on the [timeline [...]
+
+## Choose Your Migration Strategy
+
+Hudi gives you three ways to bring an existing Parquet table under management, 
described in detail in the [migration guide](/docs/migration_guide). Two of 
them are variants of the *bootstrap* operation, which builds Hudi's timeline 
and metadata over data that stays where it is; the third is a plain rewrite.
+
+- **METADATA_ONLY bootstrap (in place).** Hudi generates *skeleton* files 
containing only the record-level metadata columns and key information, one 
skeleton per original Parquet file, and links them to your original data files. 
The original data is never copied, so a multi-terabyte table can be migrated in 
a fraction of the time a rewrite would take. The trade-off: Hudi continues to 
rely on the original files, so if they are deleted or modified outside Hudi, 
the table is corrupted. The  [...]
+- **FULL_RECORD bootstrap.** Hudi copies the full records into new Hudi files, 
adding the metadata columns as it goes. This is functionally equivalent to a 
bulk insert — after it completes, the table is self-contained and the original 
files can eventually be retired. You pay the full rewrite cost.
+- **Full rewrite with `bulk_insert`.** Read the Parquet data with Spark and 
write it out as a new Hudi table using the [`bulk_insert` write 
operation](/docs/write_operations#bulk_insert). Operationally this is the 
simplest path — it is just a Spark job using the same datasource API you will 
use for all subsequent writes — and it gives you a chance to re-layout the data 
(sorting, partitioning) as you write.
+
+The bootstrap modes can be mixed *within one table, per partition*: a common 
pattern is FULL_RECORD for a small set of hot, frequently-updated partitions 
and METADATA_ONLY for the long tail of cold history.
+
+| | METADATA_ONLY bootstrap | FULL_RECORD bootstrap | Full rewrite 
(`bulk_insert`) |
+|---|---|---|---|
+| Data files rewritten | No — skeleton files only | Yes | Yes |
+| Migration time / cost | Low, proportional to metadata | High, proportional 
to data size | High, proportional to data size |
+| Original Parquet files after migration | Still required — must not be 
modified or deleted | Independent; originals can be retired | Independent; 
originals can be retired |
+| Resulting table | Hudi table referencing external base files | 
Self-contained Hudi table | Self-contained Hudi table |
+| Chance to re-sort / re-layout data | No | No | Yes 
(`hoodie.bulkinsert.sort.mode`) |
+| Best for | Very large tables where rewrite is impractical | Hot partitions 
of a large table (via regex selector) | Small-to-medium tables, or when you 
want a clean re-layout |
+
+Decision rule of thumb: if the table is small enough that rewriting it is an 
overnight Spark job you can afford to run once, take the full rewrite — it 
leaves no strings attached to the old files. If the table is tens of terabytes 
or more and a rewrite is measured in days and real money, bootstrap in place 
with METADATA_ONLY, optionally upgrading hot partitions to FULL_RECORD.
+
+## Before You Start: Three Decisions That Are Hard to Change
+
+However you migrate, you are about to give this dataset a table identity. 
Three choices deserve deliberate thought *before* you run anything, because 
changing them later effectively means migrating again.
+
+1. **Record key.** The field (or comma-separated fields) that uniquely 
identifies each record — set via `hoodie.datasource.write.recordkey.field`. 
Every upsert and delete is keyed on it, and [indexes](/docs/indexes) map keys 
to file groups. Pick something genuinely unique and stable: a natural business 
key or an existing surrogate key. See [key generation](/docs/key_generation) 
for composite and timestamp-based options.
+2. **Ordering field(s).** Set via `hoodie.table.ordering.fields`. When two 
records with the same key collide — within one batch or across writes — the 
record with the larger ordering value wins. An event timestamp or a 
monotonically increasing version column is the usual choice.
+3. **Partitioning.** Set via `hoodie.datasource.write.partitionpath.field`. If 
you bootstrap in place, your existing directory layout *is* your partitioning, 
so make peace with it first. If you do a full rewrite, this is your one cheap 
opportunity to fix a bad partition scheme — too many tiny partitions, or 
partitioning on a column no query filters on. Also decide on 
`hoodie.datasource.write.hive_style_partitioning` (`city=chennai/` style paths) 
now, for catalog compatibility.
+
+You will also choose a [table type](/docs/table_types) — Copy-on-Write is the 
right default for a freshly migrated table; you can adopt Merge-on-Read where 
write latency demands it.
+
+## Path A: Full Rewrite with bulk_insert
+
+For small and medium tables, migration is a single Spark job: read Parquet, 
write Hudi. The `bulk_insert` operation exists precisely for this — unlike 
`upsert`/`insert`, it uses a disk-based, sort-oriented write path that scales 
to very large initial loads without caching input in memory (see [write 
operations](/docs/write_operations) for the full comparison).
+
+```scala
+// spark-shell with the Hudi bundle, per the quick start guide
+val df = 
spark.read.format("parquet").load("s3://my-bucket/warehouse/trips_parquet")
+
+df.write.format("hudi").
+  option("hoodie.table.name", "trips").
+  option("hoodie.datasource.write.operation", "bulk_insert").
+  option("hoodie.datasource.write.recordkey.field", "trip_id").
+  option("hoodie.datasource.write.partitionpath.field", "city").
+  option("hoodie.table.ordering.fields", "ts").
+  option("hoodie.datasource.write.hive_style_partitioning", "true").
+  mode("overwrite").
+  save("s3://my-bucket/warehouse/trips")
+```
+
+Two knobs worth knowing:
+
+- `hoodie.bulkinsert.sort.mode` controls layout of the written files. The 
default `NONE` matches plain `spark.write.parquet()` in speed and file count; 
`GLOBAL_SORT` costs a sort but produces the best file sizes and, if you sort by 
a commonly filtered column, better data skipping forever after.
+- Note that `bulk_insert` does a best-effort job at file sizing rather than 
guaranteeing it; ongoing `upsert`/`insert` writes will progressively correct 
small files.
+
+From here on, the table behaves exactly like any Hudi table in the [quick 
start guide](/docs/quick-start-guide): switch subsequent writes to `upsert` 
with `mode("append")`, and query it from Spark, Trino, Presto, or Hive.
+
+## Path B: In-Place Bootstrap for Large Tables
+
+When rewriting is off the table, use bootstrap. The two most convenient 
front-ends are the Hudi Streamer utility and the Spark SQL `CALL` procedure; 
both drive the same underlying mechanism, and both are documented in the 
[migration guide](/docs/migration_guide).
+
+### Using Hudi Streamer
+
+[Hudi Streamer](/docs/hoodie_streaming_ingestion#hudi-streamer) supports 
bootstrap via the `--run-bootstrap` flag. This example applies FULL_RECORD mode 
to all partitions matching the regex `.*` using the regex mode selector — 
change the regex to bootstrap only hot partitions as FULL_RECORD, and unmatched 
partitions get the other mode:
+
+```bash
+spark-submit \
+--conf 'spark.serializer=org.apache.spark.serializer.KryoSerializer' \
+--class org.apache.hudi.utilities.streamer.HoodieStreamer 
/path/to/hudi-utilities-bundle.jar \
+--run-bootstrap \
+--target-base-path s3://my-bucket/warehouse/trips \
+--target-table trips \
+--table-type COPY_ON_WRITE \
+--hoodie-conf 
hoodie.bootstrap.base.path=s3://my-bucket/warehouse/trips_parquet \
+--hoodie-conf hoodie.datasource.write.recordkey.field=trip_id \
+--hoodie-conf hoodie.datasource.write.partitionpath.field=city \
+--hoodie-conf hoodie.table.ordering.fields=ts \
+--hoodie-conf 
hoodie.bootstrap.mode.selector=org.apache.hudi.client.bootstrap.selector.BootstrapRegexModeSelector
 \
+--hoodie-conf hoodie.bootstrap.mode.selector.regex='.*' \
+--hoodie-conf hoodie.bootstrap.mode.selector.regex.mode=FULL_RECORD \
+--hoodie-conf hoodie.datasource.write.hive_style_partitioning=true
+```
+
+The key config is `hoodie.bootstrap.base.path` — the location of the existing 
Parquet dataset. If you supply *only* that config, Hudi defaults to 
METADATA_ONLY mode for every partition (`hoodie.bootstrap.mode.selector` 
defaults to `MetadataOnlyBootstrapModeSelector`), which is exactly the cheap 
in-place migration most large tables want.
+
+### Using the Spark SQL CALL procedure
+
+If you live in Spark SQL, the [`run_bootstrap` 
procedure](/docs/procedures#run_bootstrap) does the same job:
+
+```sql
+CALL run_bootstrap(
+  table => 'trips',
+  table_type => 'COPY_ON_WRITE',
+  bootstrap_path => 's3://my-bucket/warehouse/trips_parquet',
+  base_path => 's3://my-bucket/warehouse/trips',
+  rowKey_field => 'trip_id',
+  partition_path_field => 'city'
+);
+```
+
+`bootstrap_path` points at the existing Parquet data and `base_path` at the 
new Hudi table location. The default `selector_class` is again 
`MetadataOnlyBootstrapModeSelector`; pass `selector_class => 
'org.apache.hudi.client.bootstrap.selector.FullRecordBootstrapModeSelector'` 
for a full-record bootstrap. There is also a [Hudi CLI 
path](/docs/migration_guide#using-hudi-cli) (`bootstrap run`) if you prefer 
driving it from the CLI, and a plain Spark datasource loop for 
partition-by-partitio [...]
+
+One operational note for METADATA_ONLY tables: from this point on, the 
original Parquet location is part of your table. Lock it down — revoke write 
access, exclude it from retention/lifecycle policies — because any modification 
or deletion there corrupts the Hudi table.
+
+## Migrating New Partitions Only
+
+There is a zero-migration option worth knowing: keep historical partitions as 
plain Parquet and let Hudi manage only *new* partitions, as described in the 
[migration guide](/docs/migration_guide#use-hudi-for-new-partitions-alone). 
Hudi tolerates such mixed tables as long as each partition is entirely 
Hudi-managed or entirely not. Start writing new partitions (or convert just the 
last N) through Hudi, and leave the rest untouched.
+
+The caveat is fundamental: none of Hudi's primitives work on the unmanaged 
partitions — no upserts, no deletes, no incremental pull there. This pattern 
fits genuinely append-only tables (immutable event logs partitioned by date) 
where old partitions will never be touched again. If there is any chance of 
updates landing in history — CDC replication, GDPR deletes, late corrections — 
migrate the whole table.
+
+## Validation Checklist
+
+Before pointing production at the new table, verify it. Bootstrap and bulk 
insert are one-shot operations; catching a wrong key choice now costs minutes, 
catching it in three months costs a re-migration.
+
+1. **Row counts match.** `spark.read.format("hudi").load(basePath).count()` 
against the source Parquet count, overall and per partition.
+2. **Keys are actually unique.** Group by your record key and confirm no count 
exceeds 1 — duplicate keys silently collapse into one record on the first 
upsert.
+3. **Sample lookups.** Pick a handful of known records and confirm field-level 
equality between source and target, including partition placement.
+4. **Exercise a write.** Upsert a few records and delete one on a staging copy 
or a scratch partition; confirm the change is visible and row counts move as 
expected.
+5. **Query engines see the table.** Sync the table to your catalog (Hive 
Metastore, AWS Glue, etc. — see [syncing to catalogs](/docs/syncing_metastore)) 
and run representative queries from every engine that matters — Spark, Trino, 
Presto. This matters doubly for METADATA_ONLY tables, where engines read merged 
skeleton + original data.
+6. **Incremental query sanity.** Run an incremental query from the bootstrap 
commit forward and confirm it returns your test writes.
+
+## Rollback Plan
+
+A comforting property of both paths: the original Parquet data is never 
mutated. Bootstrap writes skeleton files and a timeline in a *new* base path; a 
full rewrite writes an entirely new copy. Your rollback plan is therefore 
simple:
+
+- Keep the source Parquet dataset intact and readable until validation 
completes and the new table has served real workloads for an agreed soak period.
+- If something is wrong — bad record key, wrong partitioning — delete the Hudi 
base path, fix the configuration, and re-run the migration. Nothing about the 
source has changed.
+- For METADATA_ONLY bootstrap, remember the inverse: you can always abandon 
the Hudi table, but you can never abandon the original files while keeping it.
+
+The one thing to avoid during the migration window is dual-writing to both the 
old Parquet location and the new Hudi table without a plan for reconciling 
them. Freeze writes to the source, migrate, validate, then cut writers over to 
Hudi.
+
+## Operational Follow-Ups
+
+Migration makes the data Hudi-managed; a few follow-ups make it fast.
+
+- **Metadata table and indexes.** Hudi's [metadata table](/docs/metadata) 
eliminates file listings, and [indexes](/docs/indexes) — column stats for data 
skipping, record level index for point lookups — determine upsert performance. 
Review which indexes fit your workload once real update traffic starts.
+- **Compaction, if you adopt Merge-on-Read.** MoR tables need 
[compaction](/docs/compaction) to fold log files into base files; make sure it 
is scheduled and running.
+- **Clustering.** If you bootstrapped in place (no chance to sort at write 
time) or bulk-inserted with `NONE` sort mode, [clustering](/docs/clustering) 
can reorganize and sort data in the background later — regaining the layout 
benefits without another migration.
+- **Cleaning and file sizing.** The defaults are sane, but confirm cleaner 
retention matches your longest-running queries, and let ongoing writes correct 
any small files the initial load produced.
+
+## Conclusion
+
+Migrating Parquet to Hudi is not a leap; it is a choice between two well-worn 
paths. Small and medium tables: one `bulk_insert` Spark job and you have a 
self-contained Hudi table, with a free chance to fix layout on the way through. 
Large tables: bootstrap in place with METADATA_ONLY (upgrading hot partitions 
to FULL_RECORD) and skip the rewrite entirely. In both cases the original data 
survives untouched, so the risk profile is a validation exercise, not a bet. 
Decide your record key, o [...]
+
+## FAQ
+
+<PostFAQ heading={null} items={[
+  {
+    question: 'Do I have to rewrite my Parquet files to use Hudi?',
+    answer: 'No. Hudi\'s bootstrap operation in METADATA_ONLY mode generates 
small skeleton files containing only record-level metadata and links them to 
your existing Parquet files, so the original data is never copied or modified. 
A FULL_RECORD bootstrap or a bulk_insert rewrite is only needed if you want the 
table to be fully self-contained or want to change its layout.',
+  },
+  {
+    question: 'How long does a Parquet to Hudi migration take?',
+    answer: 'A METADATA_ONLY bootstrap only writes metadata, so it runs in a 
small fraction of the time of a rewrite, even on multi-terabyte tables. A full 
rewrite with bulk_insert or a FULL_RECORD bootstrap is proportional to data 
size, roughly comparable to a Spark job that reads and rewrites the whole 
dataset. Many teams mix the two, fully rewriting a few hot partitions and 
metadata-bootstrapping the cold history.',
+  },
+  {
+    question: 'Can I roll back a migration to Hudi?',
+    answer: 'Yes. Neither bootstrap nor a bulk_insert rewrite modifies the 
original Parquet files, so rolling back means deleting the new Hudi base path 
and continuing to use the source data. Keep the source dataset intact until you 
have validated row counts, key uniqueness, and queries from all your engines 
against the new table.',
+  },
+  {
+    question: 'What is the difference between METADATA_ONLY and FULL_RECORD 
bootstrap?',
+    answer: 'METADATA_ONLY writes skeleton files with just the Hudi metadata 
columns and keeps relying on your original Parquet files, so it is fast but the 
originals must never be modified or deleted. FULL_RECORD copies the complete 
records into new Hudi files, which costs a full rewrite but produces a 
self-contained table. You can apply different modes to different partitions of 
the same table using a regex-based selector.',
+  },
+  {
+    question: 'Can I keep old partitions as plain Parquet and only use Hudi 
for new data?',
+    answer: 'Yes, as long as each partition is entirely Hudi-managed or 
entirely not. This works well for append-only tables where historical 
partitions never change. The catch is that upserts, deletes, and incremental 
queries only work on the Hudi-managed partitions, so if updates might ever 
touch history, migrate the whole table instead.',
+  },
+  {
+    question: 'What should I decide before migrating a table to Hudi?',
+    answer: 'Three things: the record key that uniquely identifies each 
record, the ordering field used to pick a winner when the same key appears 
twice, and the partitioning scheme. These shape every subsequent write and are 
hard to change without re-migrating. If you bootstrap in place, the existing 
directory layout becomes your partitioning, so review it before you start.',
+  },
+]} />
diff --git a/website/blog/2026-07-30-migrating-from-hive-to-hudi.md 
b/website/blog/2026-07-30-migrating-from-hive-to-hudi.md
new file mode 100644
index 000000000000..bbe74de6ecdf
--- /dev/null
+++ b/website/blog/2026-07-30-migrating-from-hive-to-hudi.md
@@ -0,0 +1,207 @@
+---
+title: "Migrating from Apache Hive Tables to Apache Hudi"
+excerpt: "A practical guide to converting existing Apache Hive tables into 
Apache Hudi tables — in place via bootstrap or by rewriting — and 
re-registering them in your metastore with Hudi's catalog sync."
+description: "Step-by-step guide to migrating Apache Hive tables to Apache 
Hudi: in-place bootstrap vs full rewrite, Hive metastore sync, validation and 
safe decommissioning."
+authors: [sivabalan]
+category: how-to
+image: 
/assets/images/blog/2024-01-20-Data-Engineering-Bootstrapping-Data-lake-with-Apache-Hudi.png
+tags:
+- migration
+- bootstrap
+- apache hive
+- guide
+---
+
+Migrating an Apache Hive table to Apache Hudi means converting its underlying 
data files into a Hudi table — either in place with Hudi's 
[bootstrap](/docs/migration_guide) mechanism or by rewriting the data with 
Spark — and re-registering it in your metastore through Hudi's [catalog 
sync](/docs/syncing_metastore). Your existing Hive, Spark, Presto and Trino 
queries keep working against the same metastore entry, and the table gains 
upserts, deletes, ACID transactions and incremental reads [...]
+
+This guide walks through the whole journey: why teams outgrow plain Hive 
tables, what actually changes on disk and in the metastore, how to plan key and 
partition mapping, the two migration paths (in-place bootstrap and full 
rewrite), re-pointing the metastore, validating with the queries you already 
run, and finally decommissioning the old table safely.
+
+## Why Teams Move Off Plain Hive Tables
+
+A classic Hive external table is a directory convention plus a metastore 
entry. That simplicity served the Hadoop era well, but it carries structural 
costs that get worse as tables grow and freshness expectations tighten:
+
+- **No transactions on the data lake.** A plain Hive table over Parquet or ORC 
has no atomic commit protocol. A failed `INSERT OVERWRITE` can leave partial 
files behind, and readers racing a writer can see half-written partitions. 
Every team ends up building `_SUCCESS`-file conventions or staging-directory 
dances around this gap.
+- **Updates mean rewriting partitions.** There is no record-level update or 
delete. Fixing one late-arriving record, applying a CDC stream, or servicing a 
GDPR deletion request means rewriting every affected partition wholesale — 
slow, expensive, and disruptive to readers.
+- **Slow, listing-bound query planning.** Query engines discover data in Hive 
tables by listing directories. On cloud object stores, listing millions of 
files across thousands of partitions dominates planning time, and historically 
the eventual consistency of object-store listings caused correctness surprises 
too.
+- **No incremental consumption.** Downstream pipelines cannot ask a Hive table 
"what changed since yesterday?" — they re-scan whole partitions on a schedule, 
multiplying compute costs.
+
+Hive ACID (transactional ORC tables) brings transactions and row-level updates 
to Hive, but it is tied to ORC, to Hive's own compactor running inside the 
metastore ecosystem, and its delta files are not first-class citizens in Spark, 
Trino and the broader lakehouse engine ecosystem the way an open table format 
is. Lakehouse formats like Hudi were built to provide transactions, mutability 
and incremental processing directly on open columnar files, queryable from 
every major engine. If you [...]
+
+## What Changes — and What Doesn't
+
+It helps to be precise about what a migration touches:
+
+**What stays the same.** Your data remains in open columnar files — Hudi 
writes Parquet base files (and can bootstrap existing Parquet in place). The 
data keeps living on the same HDFS or object storage. Analysts keep querying 
through the same metastore-backed catalog, from the same engines.
+
+**What changes.** The table gains a Hudi timeline (a commit log recording 
every action), metadata and indexes mapping record keys to files, and 
Hudi-managed file layout with automatic file sizing. The metastore entry is 
re-registered through Hudi's sync so that engines route reads through Hudi's 
integrations — Hive via the Hudi input format, Spark and Trino/Presto via their 
native Hudi connectors. From then on, writes go through Hudi (Spark, Flink, or 
[Hudi Streamer](/docs/hoodie_streami [...]
+
+If your estate also includes raw Parquet directories that were never 
registered in Hive, the companion post on [migrating from Parquet to 
Hudi](/blog/2026/07/29/migrating-from-parquet-to-hudi) covers that path; this 
post focuses on tables living in the Hive metastore.
+
+## Planning the Migration
+
+Before running anything, map three concepts from your Hive schema onto Hudi's 
table configs:
+
+**Record key.** Hudi identifies each record by a key so it can find and update 
it later. Pick the column (or comma-separated columns) that uniquely identifies 
a row — an id column, or a composite of natural keys. This becomes 
`hoodie.datasource.write.recordkey.field` (or `primaryKey` in Spark SQL table 
properties). If the Hive table genuinely has no key and is append-only, you can 
migrate without one, but you give up upserts on that table.
+
+**Ordering field.** When two versions of the same key arrive, Hudi resolves 
the winner using ordering fields (`hoodie.table.ordering.fields`). An 
`updated_at`-style timestamp is the usual choice; it prevents older records 
from overwriting newer ones.
+
+**Partition mapping.** Hudi partitioning maps directly from Hive partitioning:
+
+- *Single-level partitions* (`ds=2026-08-01`) map to a single 
`hoodie.datasource.write.partitionpath.field` with 
`hoodie.datasource.write.hive_style_partitioning=true` to preserve the 
`key=value` directory style your Hive table already uses.
+- *Multi-level partitions* (`year=2026/month=08/day=01`) map to a 
comma-separated partition path field list (e.g. `year,month,day`); on the sync 
side, the default `MultiPartKeysValueExtractor` splits partition values on `/` 
correctly.
+- *Non-partitioned tables* simply omit the partition path field; during 
metastore sync Hudi infers `NonPartitionedExtractor` automatically.
+
+Also decide the table type now: Copy-on-Write (CoW) is the simplest starting 
point for formerly-Hive analytics tables; Merge-on-Read (MoR) suits 
update-heavy or streaming write patterns. The [table types 
guide](/docs/table_types) covers the trade-off; note that MoR changes what 
appears in your metastore after sync (more below).
+
+## Path A: In-Place Bootstrap for Large Tables
+
+For big tables, rewriting terabytes of perfectly good Parquet just to adopt a 
new format is wasteful. Hudi's [bootstrap](/docs/migration_guide) converts a 
table in place, with two modes you can mix per partition:
+
+- **METADATA_ONLY** generates skeleton files containing only Hudi's metadata 
columns and record keys, alongside pointers to your original data files — 
avoiding the full cost of rewriting the dataset. Queries and upserts work 
normally. The caveat: Hudi still relies on the original files, so they must not 
be deleted or modified.
+- **FULL_RECORD** copies the full record data into Hudi-managed files, 
functionally equivalent to a bulk insert. After it completes, the Hudi table is 
fully self-contained.
+
+A common large-table strategy is METADATA_ONLY for cold historical partitions 
and FULL_RECORD for recent, actively-updated partitions — selected with a regex 
over partition paths.
+
+### With Hudi Streamer
+
+Hudi Streamer supports bootstrap via the `--run-bootstrap` flag. This example 
applies FULL_RECORD to all partitions matching the regex `.*`, keeping 
hive-style partitioning:
+
+```bash
+spark-submit \
+--conf 'spark.serializer=org.apache.spark.serializer.KryoSerializer' \
+--class org.apache.hudi.utilities.streamer.HoodieStreamer 
/path/to/hudi-utilities-bundle.jar \
+--run-bootstrap \
+--target-base-path hdfs://ns1/warehouse/hudi/trips \
+--target-table trips \
+--table-type COPY_ON_WRITE \
+--hoodie-conf 
hoodie.bootstrap.base.path=hdfs://ns1/hive/warehouse/mydb.db/trips \
+--hoodie-conf hoodie.datasource.write.recordkey.field=trip_id \
+--hoodie-conf hoodie.datasource.write.partitionpath.field=ds \
+--hoodie-conf hoodie.table.ordering.fields=updated_at \
+--hoodie-conf 
hoodie.bootstrap.mode.selector=org.apache.hudi.client.bootstrap.selector.BootstrapRegexModeSelector
 \
+--hoodie-conf hoodie.bootstrap.mode.selector.regex='.*' \
+--hoodie-conf hoodie.bootstrap.mode.selector.regex.mode=FULL_RECORD \
+--hoodie-conf hoodie.datasource.write.hive_style_partitioning=true
+```
+
+`hoodie.bootstrap.base.path` points at the existing Hive table's location — 
the warehouse directory the metastore already knows about. To split modes by 
partition, keep the `BootstrapRegexModeSelector` and set the regex to match the 
partitions that should get the mode named in 
`hoodie.bootstrap.mode.selector.regex.mode`; unmatched partitions get the other 
mode. With only `hoodie.bootstrap.base.path` provided and no selector configs, 
METADATA_ONLY is the default for everything.
+
+### With the Spark SQL CALL procedure
+
+If you prefer staying in Spark SQL, the [`run_bootstrap` 
procedure](/docs/procedures#run_bootstrap) does the same job:
+
+```sql
+CALL run_bootstrap(
+  table => 'trips',
+  table_type => 'COPY_ON_WRITE',
+  bootstrap_path => 'hdfs://ns1/hive/warehouse/mydb.db/trips',
+  base_path => 'hdfs://ns1/warehouse/hudi/trips',
+  rowKey_field => 'trip_id',
+  partition_path_field => 'ds'
+);
+```
+
+By default this uses the METADATA_ONLY selector; pass `selector_class => 
'org.apache.hudi.client.bootstrap.selector.FullRecordBootstrapModeSelector'` 
for a full-record bootstrap.
+
+A third option worth knowing: Hudi does not require converting the entire 
table at once. Because the lowest granularity Hudi manages is a Hive partition, 
an append-only table can simply start writing *new* partitions through Hudi 
while old partitions stay as-is — with the caveat that upserts and incremental 
pulls do not work on the unconverted partitions.
+
+## Path B: Rewrite via Spark
+
+For small and medium tables — or whenever you want a clean, fully Hudi-managed 
copy with per-record ordering applied — a straight rewrite is the simplest 
path. Since the source is already a metastore table, Spark SQL can read it 
directly:
+
+```sql
+-- define the Hudi table with key, ordering and partitioning mapped from the 
Hive schema
+CREATE TABLE hudi_trips (
+  trip_id STRING,
+  rider STRING,
+  fare DOUBLE,
+  updated_at BIGINT,
+  ds STRING
+) USING HUDI
+TBLPROPERTIES (
+  primaryKey = 'trip_id',
+  orderingFields = 'updated_at'
+)
+PARTITIONED BY (ds)
+LOCATION 'hdfs://ns1/warehouse/hudi/trips';
+
+-- use bulk_insert for the one-time load: fastest, skips upsert-path indexing 
work
+SET hoodie.spark.sql.insert.into.operation = bulk_insert;
+
+INSERT INTO hudi_trips
+SELECT trip_id, rider, fare, updated_at, ds FROM mydb.trips;
+```
+
+The `bulk_insert` operation is the right choice for the initial load — it is 
optimized for large one-time writes and lets Hudi apply its file-sizing configs 
so the new table starts life with well-sized files rather than inheriting 
whatever small-file sprawl the Hive table had. The equivalent DataFrame API 
flow (read the Hive table with `spark.table(...)`, write with `format("hudi")`) 
is shown in the [quick start guide](/docs/quick-start-guide). For very large 
tables where a single job is [...]
+
+## Re-Pointing the Metastore
+
+The step that makes the migration invisible to downstream users is [syncing 
the Hudi table to the Hive metastore](/docs/syncing_metastore). Hudi's Hive 
sync registers the table (schema, partitions, location, input format) in the 
metastore and keeps it current as new commits add columns or partitions.
+
+The easiest way is to enable sync on the writer itself, so every write keeps 
the catalog fresh:
+
+```
+hoodie.datasource.meta.sync.enable=true
+hoodie.datasource.hive_sync.mode=hms
+hoodie.datasource.hive_sync.metastore.uris=thrift://hive-metastore:9083
+hoodie.datasource.hive_sync.database=mydb
+hoodie.datasource.hive_sync.table=trips
+```
+
+Alternatively, run the standalone `HiveSyncTool` from the command line for a 
one-shot or externally scheduled sync:
+
+```bash
+cd hudi-hive
+./run_sync_tool.sh --jdbc-url jdbc:hive2://hiveserver:10000 \
+  --user hive --pass hive \
+  --partitioned-by ds --base-path hdfs://ns1/warehouse/hudi/trips \
+  --database mydb --table trips
+```
+
+Sync supports three modes — `hms` (metastore thrift APIs, recommended), `jdbc` 
(via HiveServer2) and `hiveql` — detailed in the [sync 
doc](/docs/syncing_metastore). A few migration-specific notes:
+
+- **Partition values** are extracted by 
`hoodie.datasource.hive_sync.partition_value_extractor`. The default 
`MultiPartKeysValueExtractor` handles multi-level partitions split on `/`; 
hive-style partitioned and non-partitioned tables get 
`HiveStylePartitionValueExtractor` and `NonPartitionedExtractor` inferred 
automatically.
+- **CoW tables** appear as a single table under the same name your users 
expect — one metastore entry, drop-in replacement.
+- **MoR tables** sync as two views: `<table>_ro` (read-optimized — queries 
only the compacted columnar base files) and `<table>_rt` (real-time/snapshot — 
merges in the latest log files for the freshest data). Point latency-sensitive 
dashboards at `_ro` and freshness-sensitive consumers at `_rt`. If you migrate 
a Hive table to MoR, plan for downstream queries to pick one of the two names.
+- If you sync to AWS Glue instead of a self-managed metastore, the flow is the 
same with a Glue-specific sync client — see [Syncing to AWS Glue Data 
Catalog](/docs/syncing_aws_glue_data_catalog).
+
+## Validating with Your Existing Queries
+
+Before flipping any traffic, verify the migrated table from every engine you 
actually use:
+
+**Row counts and spot checks.** Compare `SELECT COUNT(*)` between old and new, 
overall and per partition. Spot-check a sample of records by key. Note that 
Hudi adds meta columns (`_hoodie_commit_time`, `_hoodie_record_key`, etc.) — 
`SELECT *` outputs will include them, so audit any consumers doing positional 
column access.
+
+**Hive.** Query through beeline; ensure the `hudi-hadoop-mr-bundle` jar is 
available to Hive (e.g. in its `auxlib/` directory) and set the input format so 
splits are computed correctly:
+
+```
+beeline -u jdbc:hive2://hiveserver:10000/mydb \
+  --hiveconf hive.input.format=org.apache.hadoop.hive.ql.io.HiveInputFormat
+```
+
+**Spark and Trino/Presto.** These engines have native Hudi support and resolve 
the synced table straight from the metastore — run your representative 
dashboards and pipeline queries against the new table name. For MoR, run them 
against both `_ro` and `_rt` so you understand the freshness difference before 
choosing defaults.
+
+**Exercise the new capabilities.** Do a small `UPDATE`/`DELETE` or an upsert 
write, confirm it lands atomically, and try an incremental query — this is, 
after all, why you migrated.
+
+## Decommissioning the Old Table Safely
+
+Once validation passes and writers have been cut over to Hudi, retire the old 
table deliberately:
+
+1. **Freeze writes to the old Hive table first.** Run the final bootstrap or 
rewrite *after* the freeze so no records land in the old location and get 
missed. (For rewrites you can also do an initial bulk load, then a short 
catch-up pass for late data before cutover.)
+2. **Repoint consumers, then watch.** Keep the old table readable during a 
burn-in period while dashboards and pipelines run against the Hudi table.
+3. **Mind the METADATA_ONLY dependency.** If you bootstrapped with 
METADATA_ONLY, the Hudi table still references the original data files — 
deleting or modifying them causes data loss or corruption. Either keep the 
original files permanently (drop only the old metastore *entry*, not the data), 
or convert to fully Hudi-managed files before deleting anything.
+4. **Drop the metastore entry last.** For an external Hive table, `DROP TABLE` 
removes only metadata; delete the underlying directory separately, and only 
when rule 3 allows.
+
+## Conclusion
+
+Migrating from Hive to Hudi is less a leap than a re-registration: the files 
stay open columnar, the catalog stays the metastore, the engines stay Spark, 
Hive, Trino and Presto. What changes is the table layer in between — and with 
it, everything a plain Hive table couldn't do. Choose in-place 
[bootstrap](/docs/migration_guide) (METADATA_ONLY, FULL_RECORD, or a 
regex-selected mix) for large tables, a `bulk_insert` rewrite for smaller ones, 
wire up [metastore sync](/docs/syncing_metastore [...]
+
+## FAQ
+
+<PostFAQ heading={null} items={[
+  {question: 'Can Hive still query a table after it\'s migrated to Hudi?', 
answer: 'Yes. Hudi\'s Hive sync registers the table in the Hive metastore with 
Hudi\'s input format, and Hive queries it through the hudi-hadoop-mr bundle. 
Spark, Presto and Trino also query the synced table through their native Hudi 
integrations, so existing SQL keeps working.'},
+  {question: 'Do I need to stop writes during the migration?', answer: 'Only 
briefly. Freeze writes to the old Hive table, run the final bootstrap or 
catch-up rewrite pass, then cut writers over to the Hudi table. For rewrite 
migrations you can bulk load most of the data ahead of time and keep the write 
freeze down to a short catch-up window.'},
+  {question: 'What happens to my Hive partitions?', answer: 'They map 
directly. Hudi preserves hive style key=value partition directories when 
hive_style_partitioning is enabled, multi level partitions map to a comma 
separated partition path field list, and Hive sync re-registers all partitions 
in the metastore using a partition value extractor that is inferred 
automatically in common cases.'},
+  {question: 'Should I use METADATA_ONLY or FULL_RECORD bootstrap?', answer: 
'METADATA_ONLY writes only skeleton files with record keys and avoids rewriting 
data, making it ideal for large cold partitions, but the original files must 
never be deleted or modified. FULL_RECORD copies data into fully Hudi managed 
files, equivalent to a bulk insert. A common pattern applies FULL_RECORD to 
recent hot partitions and METADATA_ONLY to the rest using a regex mode 
selector.'},
+  {question: 'What are the _ro and _rt tables that appear after migrating to 
Merge-on-Read?', answer: 'For a Merge-on-Read table, Hive sync registers two 
views in the metastore: a read optimized view suffixed _ro that queries only 
compacted columnar base files, and a real time view suffixed _rt that merges in 
the latest log files for the freshest data. Copy-on-Write tables sync as a 
single table under the original name.'},
+  {question: 'Can I migrate only part of a Hive table to Hudi?', answer: 'Yes. 
Because Hudi manages data at Hive partition granularity, an append only table 
can start writing new partitions through Hudi while historical partitions stay 
untouched. The caveat is that upserts and incremental queries only work on the 
Hudi managed partitions, so update heavy tables should be converted fully.'},
+]} />
diff --git a/website/src/pages/faq/general.md b/website/src/pages/faq/general.md
index fe19916b825d..98c06fac9584 100644
--- a/website/src/pages/faq/general.md
+++ b/website/src/pages/faq/general.md
@@ -27,7 +27,7 @@ Combined with a storage format that balances write speed and 
query performance,
 
 The two projects were engineered around different workloads. Iceberg's design 
centers on the traditional batch, scan-oriented workloads that Apache Hive 
served — large periodic rewrites and full-table scans. Hudi was engineered for 
fast-moving, mutable data: streaming ingestion, CDC, record-level upserts and 
deletes, and incremental pipelines that process only what changed. Choosing 
between them is a question of workload fit, not either/or on data access.
 
-That is because both formats store data as Parquet files, and [Apache 
XTable](/docs/syncing_xtable) (incubating) translates Hudi table metadata into 
Iceberg metadata in place — no data is copied or rewritten — making Hudi 
copy-on-write tables fully format-compatible with Iceberg readers: a single 
copy of data on cloud storage is readable as both Hudi and Iceberg. 
(Merge-on-read tables expose their compacted read-optimized view to Iceberg 
readers.) You can ingest and manage tables with Hu [...]
+That is because both formats store data as Parquet files, and [Apache 
XTable](/docs/syncing_xtable) (incubating) translates Hudi table metadata into 
Iceberg metadata in place — no data is copied or rewritten — making Hudi 
copy-on-write tables fully format-compatible with Iceberg readers: a single 
copy of data on cloud storage is readable as both Hudi and Iceberg. 
(Merge-on-read tables expose their compacted read-optimized view to Iceberg 
readers.) You can ingest and manage tables with Hu [...]
 
 ### What are some non-goals for Hudi?
 
diff --git a/website/static/llms.txt b/website/static/llms.txt
index 33fc4c0fc4bd..5177506057f8 100644
--- a/website/static/llms.txt
+++ b/website/static/llms.txt
@@ -47,9 +47,12 @@ It can also synchronize your data to half dozen data 
catalogs to keep table cons
 - [What is CDC on a Data 
Lake?](https://hudi.apache.org/blog/2026/07/22/what-is-cdc-on-a-data-lake): 
Change data capture from operational databases into lakehouse tables, explained 
from first principles.
 - [Lakehouse vs Data Warehouse vs Data 
Lake](https://hudi.apache.org/blog/2026/07/23/lakehouse-vs-data-warehouse-vs-data-lake):
 The three architectures compared — strengths, costs and when to use each.
 - [Open Table Format vs Data 
Lakehouse](https://hudi.apache.org/blog/2026/07/24/open-table-format-vs-data-lakehouse):
 Untangling the table layer from the architecture, and where file formats, 
catalogs and engines fit.
+- [Using Hudi with Apache Iceberg via 
XTable](https://hudi.apache.org/blog/2026/07/28/using-hudi-with-apache-iceberg-via-xtable):
 How Iceberg-only engines and catalogs can read Hudi tables through Apache 
XTable metadata sync.
 
 ## Blog — Migration guides
 
+- [Migrating from Parquet to 
Hudi](https://hudi.apache.org/blog/2026/07/29/migrating-from-parquet-to-hudi): 
In-place bootstrap vs full rewrite for converting raw Parquet datasets into 
Hudi tables.
+- [Migrating from Hive to 
Hudi](https://hudi.apache.org/blog/2026/07/30/migrating-from-hive-to-hudi): 
Moving Hive tables to Hudi with bootstrap and catalog sync.
 
 ## Blog — Comparisons
 

Reply via email to