Hi Zhe, Thanks for the detailed questions. They highlight several limitations and operational assumptions that would benefit from clearer documentation. Here are my thoughts on each point.
**1. Write availability during migration** Yes, the initial version intentionally uses an offline migration approach that requires a maintenance window. The write outage covers the entire initialization process, including Bulk Load, initial snapshot registration, validation, and datalake enablement. Its duration depends on the amount of data being loaded and the available resources. I will clarify this in the FIP. Your understanding of the partition scope is also correct. Validation compares the table-level Paimon snapshot ID, so writes to unselected partitions that advance the snapshot would also cause validation to fail. The requirement to stop native Paimon writers therefore applies to the entire source table. The baseline-load-plus-incremental-catch-up approach you outlined is a useful direction for future work. It would require defining incremental replay, ordering, deduplication, delete handling, writer fencing, and the exact handoff boundary. Online migration is outside the scope of the initial version. The FIP should also describe recovery from incomplete initialization. As discussed in the earlier recovery question, the proposed initial approach is to resolve any remaining Bulk Load work before dropping the Fluss table created by the promotion and retrying, while preserving the original Paimon table and its data. A timeout alone should not trigger cleanup, since the underlying work may have succeeded. **2. Partially initialized regular partitions** By default, a regular partitioned primary-key table will load all existing partitions from the source snapshot. Explicit partition selection is intended for cases where users already know which existing partitions may receive subsequent writes. For example, loading only recent partitions can reduce both Bulk Load time and the required maintenance window. When choosing this optimization, users must ensure that unloaded existing partitions do not receive writes through Fluss. Fluss primary-key point lookups are also unsupported for those partitions. The initial version relies on this operational prerequisite and does not provide additional checks to reject such requests automatically. I agree that an accidental write to an unloaded partition could encounter missing historical KV state and produce incorrect update, delete, or changelog behavior. I will make this risk and the responsibility explicit in the FIP. Users who cannot guarantee the access scope should use the default initialization of all existing partitions. The current procedure also does not define a way to initialize additional partitions by repeating `CALL`; an existing Fluss table causes the procedure to skip Bulk Load. Loading the remaining partitions later would require a separately defined extension. **3. Unknown Paimon properties** I have also spent quite some time considering this tradeoff. Internally, we have many Paimon tables with custom options, including application metadata. Rejecting every unknown property would prevent many of these tables from using the feature directly. Requiring users to acknowledge each property or maintain an allowlist would also add operational overhead. Because application metadata and behavior-related options share the same property map, an unrecognized key alone does not tell us which category it belongs to. The current proposal validates recognized options against the supported mappings and rejects known incompatibilities. Unknown properties remain in the original Paimon table, but they do not define additional behavior in Fluss. Given these limitations and the usability cost, I think retaining the current default of allowing unknown properties is a reasonable choice for the initial version. This still leaves a compatibility risk when an unknown property controls behavior that the source table depends on. One improvement would be to explicitly report which properties were not validated and document the supported Paimon versions and mappings. This would make the validation coverage visible without requiring an additional acknowledgement step for every table. Successful promotion should not be interpreted as a compatibility guarantee for arbitrary custom features or behavior introduced by newer Paimon versions. Best regards, Yuxia ----- 原始邮件 ----- 发件人: "yuxia" <[email protected]> 收件人: "dev" <[email protected]> 发送时间: 星期五, 2026年 9 月 11日 下午 1:41:51 主题: Re: FIP-25: Support In-Place Promotion of Existing Paimon Tables to Datalake-Enabled Fluss Tables Hi, Liting. Thanks for reviewing FIP-25 and raising these questions. They highlight two areas that need clearer explanation: how callers observe a promotion that takes a long time, and how they recover when initialization is only partially completed. > Your first question: could the caller time out while promotion continues, and > should the procedure > return a promotion operation ID for status tracking? The reason for keeping the procedure synchronous is to provide a clear completion guarantee: when `CALL` returns successfully, Bulk Load, initial snapshot registration, and datalake enablement have all completed, and the table is ready for use through Fluss. For Flink SQL Gateway's REST endpoint, SQL submission already returns an `OperationHandle`, which clients use to query status and fetch results. The Flink SQL Client also sends session heartbeats independently while waiting. Therefore, synchronous execution inside the procedure does not require keeping a single HTTP request open for the entire Bulk Load duration. See the [SQL Gateway REST documentation][1]. A separate asynchronous promotion API would require us to define how promotion stages are tracked, how the remaining steps continue after returning to the caller, and how that execution recovers across failures. For the initial version, I would prefer to retain the synchronous procedure and reuse the Gateway's existing SQL operation handling. A client disconnect alone does not establish that promotion failed, and an interrupted procedure may already have completed some steps. I agree that these cases need clarification, together with the recovery and retry semantics in your second point. > Your second question: if table creation succeeds but Bulk Load fails, how can > a retry distinguish > incomplete initialization from a successfully initialized table and avoid > enabling datalake > prematurely? For a primary-key table requiring Bulk Load, the proposal registers the initial lake snapshot only after the required loading has completed successfully. When enabling datalake, `alterTable()` validates the current Paimon snapshot against the snapshot registered in Fluss. If initialization has not reached snapshot registration, this validation rejects enablement. Finding an existing Fluss table and skipping Bulk Load would therefore not bypass this check. However, you are right that the FIP does not currently explain how users recover from incomplete initialization. For the initial version, I propose a manual recovery path for incomplete initialization: first stop any remaining Bulk Load job and confirm that its transactions have reached a terminal state, then drop the Fluss table created by the promotion and rerun the procedure. This recovery path must preserve the original Paimon table and its data. A timeout or cancellation alone should not trigger cleanup; users should first establish the actual outcome. If Bulk Load and initial snapshot registration have both completed, and only datalake enablement failed, users can address the failure and repeat the procedure. The existing snapshot and schema checks would then determine whether enablement can proceed, without reloading the data. I will clarify these cases in the FIP, including the scope of idempotent retries. Persisting additional promotion metadata to support automatic resumption of incomplete initialization is a useful enhancement, but I would prefer to defer that capability beyond the initial version. [1]: https://nightlies.apache.org/flink/flink-docs-release-2.2/docs/dev/table/sql-gateway/rest/#overview-of-sql-processing Best regards, Yuxia ----- 原始邮件 ----- 发件人: "Zhe Wang" <[email protected]> 收件人: "dev" <[email protected]> 发送时间: 星期四, 2026年 9 月 10日 上午 12:36:48 主题: Re: FIP-25: Support In-Place Promotion of Existing Paimon Tables to Datalake-Enabled Fluss Tables Hi yuxia, Thanks for the detailed proposal. I have a few additional questions, mainly around production migration and data correctness. 1. Write availability during migration The current proposal requires users to stop native Paimon writers before invoking the procedure, while new writes through Fluss can only start after the Bulk Load, snapshot registration, validation, and datalake enablement have all completed. For a large primary-key table, the Bulk Load may take a long time, so the business write outage could potentially last for hours. Since the final validation compares the table-level Paimon snapshot ID, it also seems that writes to partitions outside the selected Bulk Load scope would advance the snapshot and cause validation to fail. Is an offline, maintenance-window-style migration an intentional limitation of this FIP? For production migration, would it be possible to separate the long-running baseline load from the final write ownership cutover? One possible flow would be: 1. capture a baseline Paimon snapshot; 2. Bulk Load that snapshot while Paimon writers continue running; 3. catch up changes committed after the baseline; 4. stop or fence the Paimon writers briefly; 5. apply the remaining changes, verify consistency, and enable Fluss; 6. switch application writes to Fluss. This would require defining the incremental replay, ordering, deduplication, fencing, rollback, and exact handoff boundary. If online migration is outside the scope of FIP-25, I think it would still be useful to document the expected write outage and the recommended recovery procedure when a long-running migration fails. 2. Enforcement for partially initialized regular partitions For a regular partitioned primary-key table, the proposal allows users to Bulk Load only selected partitions. It states that unloaded partitions do not support Fluss lookups or writes and that users must ensure no writes are issued to them. How is the set of successfully initialized partitions persisted and exposed after the procedure completes? Should Fluss reject lookup and write requests to an unloaded partition, instead of relying only on an operational requirement? Without such enforcement, an accidental write to an unloaded partition may treat the historical KV state as empty and produce incorrect upsert, delete, or changelog behavior. It would also be helpful to clarify whether and how the remaining partitions can be initialized later. 3. Handling of unknown Paimon properties The compatibility section explains that properties unknown to the Paimon version bundled with Fluss are allowed, because they may be application metadata. It also acknowledges that such a property may actually control behavior introduced by a newer Paimon version, in which case promotion could succeed even though the resulting Fluss semantics are different. For a correctness-sensitive operation such as in-place promotion, is silently allowing these properties the right default? Would it be safer to report all unknown properties and require an explicit acknowledgement or allowlist before proceeding? A strict mode that rejects unknown properties by default could also make the compatibility guarantee easier for users to understand. Best regards, Zhe Wang Liting Liu (litiliu) via dev <[email protected]> 于2026年9月9日周三 16:52写道: > Hi Yuxia and Fluss community, > > Thanks for sharing FIP-25. It is a very interesting proposal. While > reading it and comparing it with the current `apache/main` branch, I had a > few questions that may be worth clarifying. > > First, the proposal says that `CALL sys.enable_fluss_on_lake_table(...)` > waits for the `load_lake_data_to_fluss` Bulk Load job, snapshot > registration, and datalake enablement to complete before returning. > > For a large Paimon table, this operation could take a considerable amount > of time. Depending on the SQL Gateway, client, or HTTP/proxy configuration, > the caller might time out while the underlying operation is still running. > In that situation, it may be difficult for the caller to determine the > final outcome. > > Would it make sense for the procedure to return a promotion operation ID > and provide a separate way to query its status? Alternatively, it would be > helpful to document how timeout and cancellation are expected to work. > > Second, I was wondering about failure recovery and retry behavior. > > If Fluss table creation succeeds but the Bulk Load job fails, the proposal > says that the table remains present with datalake disabled. On a subsequent > call, however, the existing table may cause the procedure to skip table > creation and Bulk Load. It would be useful to clarify how the procedure can > distinguish a successfully initialized table from one whose Bulk Load > failed or is still incomplete. > > Could the design consider persisting some information such as the > following to make retry and recovery easier to understand? > > - promotion operation ID; > - source Paimon snapshot ID; > - selected partitions; > - Bulk Load transaction ID. > > It may also be helpful to describe the expected retry, abort, timeout, and > cancellation semantics, and to make sure that a retry cannot enable > datalake before the Bulk Load result has been successfully verified. > > Best regards, > > Liting Liu > > From: yuxia <[email protected]> > Date: Tuesday, September 8, 2026 at 15:23 > To: dev <[email protected]> > Subject: [DISCUSS] FIP-25: Support In-Place Promotion of Existing Paimon > Tables to Datalake-Enabled Fluss Tables > > Hi Fluss community, > > I'd like to start a discussion on FIP-25: Support In-Place Promotion of > Existing Paimon Tables to Datalake-Enabled Fluss Tables[1]. > > This FIP proposes promoting an existing Paimon table to a datalake-enabled > Fluss table in place through: > > CALL sys.enable_fluss_on_lake_table(...); > > "In-place" means reusing the existing Paimon table and historical data > without creating a replacement table or rewriting the data to Paimon. Fluss > creates the corresponding metadata, initializes historical primary-key > state through Bulk Load when necessary, and validates schema and snapshot > consistency before enabling datalake. > > Feedback and suggestions are welcome. > > [1]: > https://cwiki.apache.org/confluence/spaces/FLUSS/pages/406623572/FIP-25+Support+In-Place+Promotion+of+Existing+Paimon+Tables+to+Datalake-Enabled+Fluss+Tables > > Best regards, > Yuxia >
