You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xtable.apache.org by ti...@apache.org on 2024/04/01 04:56:11 UTC

(incubator-xtable) 01/01: rename and replace 'client'

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

timbrown pushed a commit to branch 406-client-rename
in repository https://gitbox.apache.org/repos/asf/incubator-xtable.git

commit 5df53d8ca14e42fd73a252b023239b64e6a086aa
Author: Timothy Brown <ti...@onehouse.ai>
AuthorDate: Sun Mar 31 23:56:01 2024 -0500

    rename and replace 'client'
---
 README.md                                          |  26 +--
 .../{client => conversion}/CatalogConfig.java      |   2 +-
 .../{client => conversion}/HudiSourceConfig.java   |   2 +-
 .../{client => conversion}/PerTableConfig.java     |   2 +-
 .../{SourceClient.java => ConversionSource.java}   |   2 +-
 .../xtable/spi/extractor/ExtractFromSource.java    |   8 +-
 .../{TargetClient.java => ConversionTarget.java}   |   4 +-
 .../apache/xtable/spi/sync/TableFormatSync.java    |  32 ++--
 .../spi/extractor/TestExtractFromSource.java       |  14 +-
 .../xtable/spi/sync/TestTableFormatSync.java       | 114 ++++++------
 .../ConversionController.java}                     |  76 ++++----
 .../ConversionSourceProvider.java}                 |  33 ++--
 .../ConversionTargetFactory.java}                  |  37 ++--
 .../{client => conversion}/PerTableConfigImpl.java |   2 +-
 ...ourceClient.java => DeltaConversionSource.java} |   6 +-
 ...der.java => DeltaConversionSourceProvider.java} |  28 ++-
 ...DeltaClient.java => DeltaConversionTarget.java} |  14 +-
 ...aClientUtils.java => DeltaConversionUtils.java} |   6 +-
 .../xtable/delta/DeltaIncrementalChangesState.java |   4 +-
 .../{HudiClient.java => HudiConversionSource.java} |   6 +-
 ...ider.java => HudiConversionSourceProvider.java} |  12 +-
 ...TargetClient.java => HudiConversionTarget.java} |  12 +-
 .../apache/xtable/hudi/HudiSourceConfigImpl.java   |   2 +-
 .../xtable/iceberg/IcebergCatalogConfig.java       |   2 +-
 ...rceClient.java => IcebergConversionSource.java} |   6 +-
 ...r.java => IcebergConversionSourceProvider.java} |  12 +-
 ...ergClient.java => IcebergConversionTarget.java} |  12 +-
 ...=> org.apache.xtable.spi.sync.ConversionTarget} |   6 +-
 ...ableClient.java => ITConversionController.java} | 153 ++++++++-------
 .../TestConversionController.java}                 | 205 +++++++++++----------
 .../TestConversionTargetFactory.java}              |  34 ++--
 .../{client => conversion}/TestPerTableConfig.java |   2 +-
 ...ent.java => ITDeltaConversionTargetSource.java} |  93 +++++-----
 .../org/apache/xtable/delta/TestDeltaSync.java     |  23 ++-
 ...ient.java => ITHudiConversionSourceSource.java} |  22 +--
 ...ient.java => ITHudiConversionSourceTarget.java} |  26 +--
 ...nt.java => TestHudiConversionSourceTarget.java} |  54 +++---
 ...t.java => ITIcebergConversionTargetSource.java} |  58 +++---
 ...java => TestIcebergConversionTargetSource.java} |  47 ++---
 .../org/apache/xtable/iceberg/TestIcebergSync.java |  48 +++--
 .../java/org/apache/xtable/loadtest/LoadTest.java  |  26 +--
 demo/notebook/demo.ipynb                           |  32 ++--
 hudi-support/extensions/README.md                  |   2 +-
 ...eTableSyncConfig.java => XTableSyncConfig.java} |   4 +-
 .../{OneTableSyncTool.java => XTableSyncTool.java} |  28 +--
 ...eTableSyncTool.java => TestXTableSyncTool.java} |   8 +-
 .../java/org/apache/xtable/utilities/RunSync.java  |  80 ++++----
 ...ults.yaml => onetable-conversion-defaults.yaml} |  30 +--
 .../org/apache/xtable/utilities/TestRunSync.java   |  62 ++++---
 49 files changed, 793 insertions(+), 726 deletions(-)

diff --git a/README.md b/README.md
index 0f78f750..08bb33a5 100644
--- a/README.md
+++ b/README.md
@@ -66,23 +66,23 @@ datasets:
     - `DAY`: same as `YEAR` but with day granularity
     - `HOUR`: same as `YEAR` but with hour granularity
   - `format`: if your partition type is `YEAR`, `MONTH`, `DAY`, or `HOUR` specify the format for the date string as it appears in your file paths
-3. The default implementations of table format clients can be replaced with custom implementations by specifying a client configs yaml file in the format below:
+3. The default implementations of table format converters can be replaced with custom implementations by specifying a converter configs yaml file in the format below:
 ```yaml
-# sourceClientProviderClass: The class name of a table format's client factory, where the client is
+# conversionSourceProviderClass: The class name of a table format's converter factory, where the converter is
 #     used for reading from a table of this format. All user configurations, including hadoop config
-#     and client specific configuration, will be available to the factory for instantiation of the
-#     client.
-# targetClientProviderClass: The class name of a table format's client factory, where the client is
+#     and converter specific configuration, will be available to the factory for instantiation of the
+#     converter.
+# conversionTargetProviderClass: The class name of a table format's converter factory, where the converter is
 #     used for writing to a table of this format.
-# configuration: A map of configuration values specific to this client.
-tableFormatsClients:
+# configuration: A map of configuration values specific to this converter.
+tableFormatConverters:
     HUDI:
-      sourceClientProviderClass: org.apache.xtable.hudi.HudiSourceClientProvider
+      conversionSourceProviderClass: org.apache.xtable.hudi.HudiConversionSourceProvider
     DELTA:
-      targetClientProviderClass: org.apache.xtable.delta.DeltaClient
+      conversionTargetProviderClass: org.apache.xtable.delta.DeltaConversionTarget
       configuration:
         spark.master: local[2]
-        spark.app.name: onetableclient
+        spark.app.name: xtable
 ```
 4. A catalog can be used when reading and updating Iceberg tables. The catalog can be specified in a yaml file and passed in with the `--icebergCatalogConfig` option. The format of the catalog config file is:
 ```yaml
@@ -92,8 +92,8 @@ catalogOptions: # all other options are passed through in a map
   key1: value1
   key2: value2
 ```
-5. run with `java -jar utilities/target/utilities-0.1.0-SNAPSHOT-bundled.jar --datasetConfig my_config.yaml [--hadoopConfig hdfs-site.xml] [--clientsConfig clients.yaml] [--icebergCatalogConfig catalog.yaml]`
-The bundled jar includes hadoop dependencies for AWS, Azure, and GCP. Sample hadoop configurations for configuring the clients 
+5. run with `java -jar utilities/target/utilities-0.1.0-SNAPSHOT-bundled.jar --datasetConfig my_config.yaml [--hadoopConfig hdfs-site.xml] [--convertersConfig converters.yaml] [--icebergCatalogConfig catalog.yaml]`
+The bundled jar includes hadoop dependencies for AWS, Azure, and GCP. Sample hadoop configurations for configuring the converters 
 can be found in the [onetable-hadoop-defaults.xml](https://github.com/apache/incubator-xtable/blob/main/utilities/src/main/resources/onetable-hadoop-defaults.xml) file.
 The custom hadoop configurations can be passed in with the `--hadoopConfig [custom-hadoop-config-file]` option.
 The config in custom hadoop config file will override the default hadoop configurations. For an example
@@ -107,7 +107,7 @@ For setting up the repo on IntelliJ, open the project and change the java versio
 You have found a bug, or have a cool idea you that want to contribute to the project ? Please file a GitHub issue [here](https://github.com/apache/incubator-xtable/issues)
 
 ## Adding a new target format
-Adding a new target format requires a developer implement [TargetClient](./api/src/main/java/org/apache/xtable/spi/sync/TargetClient.java). Once you have implemented that interface, you can integrate it into the [OneTableClient](./core/src/main/java/org/apache/xtable/client/OneTableClient.java). If you think others may find that target useful, please raise a Pull Request to add it to the project.
+Adding a new target format requires a developer implement [ConversionTarget](./api/src/main/java/org/apache/xtable/spi/sync/ConversionTarget.java). Once you have implemented that interface, you can integrate it into the [OneTableClient](./core/src/main/java/org/apache/xtable/client/OneTableClient.java). If you think others may find that target useful, please raise a Pull Request to add it to the project.
 
 ## Overview of the sync process
 ![img.png](assets/images/sync_flow.jpg)
diff --git a/api/src/main/java/org/apache/xtable/client/CatalogConfig.java b/api/src/main/java/org/apache/xtable/conversion/CatalogConfig.java
similarity index 97%
rename from api/src/main/java/org/apache/xtable/client/CatalogConfig.java
rename to api/src/main/java/org/apache/xtable/conversion/CatalogConfig.java
index 4184b4c8..a432b749 100644
--- a/api/src/main/java/org/apache/xtable/client/CatalogConfig.java
+++ b/api/src/main/java/org/apache/xtable/conversion/CatalogConfig.java
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
  
-package org.apache.xtable.client;
+package org.apache.xtable.conversion;
 
 import java.util.Map;
 
diff --git a/api/src/main/java/org/apache/xtable/client/HudiSourceConfig.java b/api/src/main/java/org/apache/xtable/conversion/HudiSourceConfig.java
similarity index 96%
rename from api/src/main/java/org/apache/xtable/client/HudiSourceConfig.java
rename to api/src/main/java/org/apache/xtable/conversion/HudiSourceConfig.java
index 113fcb75..1d59466a 100644
--- a/api/src/main/java/org/apache/xtable/client/HudiSourceConfig.java
+++ b/api/src/main/java/org/apache/xtable/conversion/HudiSourceConfig.java
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
  
-package org.apache.xtable.client;
+package org.apache.xtable.conversion;
 
 import org.apache.xtable.spi.extractor.SourcePartitionSpecExtractor;
 
diff --git a/api/src/main/java/org/apache/xtable/client/PerTableConfig.java b/api/src/main/java/org/apache/xtable/conversion/PerTableConfig.java
similarity index 97%
rename from api/src/main/java/org/apache/xtable/client/PerTableConfig.java
rename to api/src/main/java/org/apache/xtable/conversion/PerTableConfig.java
index f9179439..612fc9b3 100644
--- a/api/src/main/java/org/apache/xtable/client/PerTableConfig.java
+++ b/api/src/main/java/org/apache/xtable/conversion/PerTableConfig.java
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
  
-package org.apache.xtable.client;
+package org.apache.xtable.conversion;
 
 import java.util.List;
 
diff --git a/api/src/main/java/org/apache/xtable/spi/extractor/SourceClient.java b/api/src/main/java/org/apache/xtable/spi/extractor/ConversionSource.java
similarity index 98%
rename from api/src/main/java/org/apache/xtable/spi/extractor/SourceClient.java
rename to api/src/main/java/org/apache/xtable/spi/extractor/ConversionSource.java
index 40bd0f0d..ed1486b9 100644
--- a/api/src/main/java/org/apache/xtable/spi/extractor/SourceClient.java
+++ b/api/src/main/java/org/apache/xtable/spi/extractor/ConversionSource.java
@@ -33,7 +33,7 @@ import org.apache.xtable.model.schema.SchemaCatalog;
  * source system. The client uses {@link Instant} to represent the point in time a commit was made
  * to be as generic as possible across source table formats.
  */
-public interface SourceClient<COMMIT> extends Closeable {
+public interface ConversionSource<COMMIT> extends Closeable {
   /**
    * Extracts the {@link InternalTable} definition as of the provided commit.
    *
diff --git a/api/src/main/java/org/apache/xtable/spi/extractor/ExtractFromSource.java b/api/src/main/java/org/apache/xtable/spi/extractor/ExtractFromSource.java
index f09462b9..e1604435 100644
--- a/api/src/main/java/org/apache/xtable/spi/extractor/ExtractFromSource.java
+++ b/api/src/main/java/org/apache/xtable/spi/extractor/ExtractFromSource.java
@@ -32,20 +32,20 @@ import org.apache.xtable.model.TableChange;
 @AllArgsConstructor(staticName = "of")
 @Getter
 public class ExtractFromSource<COMMIT> {
-  private final SourceClient<COMMIT> sourceClient;
+  private final ConversionSource<COMMIT> conversionSource;
 
   public InternalSnapshot extractSnapshot() {
-    return sourceClient.getCurrentSnapshot();
+    return conversionSource.getCurrentSnapshot();
   }
 
   public IncrementalTableChanges extractTableChanges(
       InstantsForIncrementalSync instantsForIncrementalSync) {
     CommitsBacklog<COMMIT> commitsBacklog =
-        sourceClient.getCommitsBacklog(instantsForIncrementalSync);
+        conversionSource.getCommitsBacklog(instantsForIncrementalSync);
     // No overlap between updatedPendingCommits and commitList, process separately.
     Iterator<TableChange> tableChangeIterator =
         commitsBacklog.getCommitsToProcess().stream()
-            .map(sourceClient::getTableChangeForCommit)
+            .map(conversionSource::getTableChangeForCommit)
             .iterator();
     return IncrementalTableChanges.builder()
         .tableChanges(tableChangeIterator)
diff --git a/api/src/main/java/org/apache/xtable/spi/sync/TargetClient.java b/api/src/main/java/org/apache/xtable/spi/sync/ConversionTarget.java
similarity index 97%
rename from api/src/main/java/org/apache/xtable/spi/sync/TargetClient.java
rename to api/src/main/java/org/apache/xtable/spi/sync/ConversionTarget.java
index d8132182..37eb25f1 100644
--- a/api/src/main/java/org/apache/xtable/spi/sync/TargetClient.java
+++ b/api/src/main/java/org/apache/xtable/spi/sync/ConversionTarget.java
@@ -23,7 +23,7 @@ import java.util.Optional;
 
 import org.apache.hadoop.conf.Configuration;
 
-import org.apache.xtable.client.PerTableConfig;
+import org.apache.xtable.conversion.PerTableConfig;
 import org.apache.xtable.model.InternalTable;
 import org.apache.xtable.model.TableSyncMetadata;
 import org.apache.xtable.model.schema.InternalPartitionField;
@@ -32,7 +32,7 @@ import org.apache.xtable.model.storage.DataFilesDiff;
 import org.apache.xtable.model.storage.PartitionFileGroup;
 
 /** A client that provides the major functionality for syncing changes to a target system. */
-public interface TargetClient {
+public interface ConversionTarget {
 
   /**
    * Syncs the current schema state.
diff --git a/api/src/main/java/org/apache/xtable/spi/sync/TableFormatSync.java b/api/src/main/java/org/apache/xtable/spi/sync/TableFormatSync.java
index 7285ea28..cd4de0ff 100644
--- a/api/src/main/java/org/apache/xtable/spi/sync/TableFormatSync.java
+++ b/api/src/main/java/org/apache/xtable/spi/sync/TableFormatSync.java
@@ -54,21 +54,21 @@ public class TableFormatSync {
   /**
    * Syncs the provided snapshot to the target table formats.
    *
-   * @param targetClients the targets to sync with the snapshot
+   * @param conversionTargets the targets to sync with the snapshot
    * @param snapshot the snapshot to sync
    * @return the result of the sync process
    */
   public Map<String, SyncResult> syncSnapshot(
-      Collection<TargetClient> targetClients, InternalSnapshot snapshot) {
+      Collection<ConversionTarget> conversionTargets, InternalSnapshot snapshot) {
     Instant startTime = Instant.now();
     Map<String, SyncResult> results = new HashMap<>();
-    for (TargetClient targetClient : targetClients) {
+    for (ConversionTarget conversionTarget : conversionTargets) {
       try {
         InternalTable internalTable = snapshot.getTable();
         results.put(
-            targetClient.getTableFormat(),
+            conversionTarget.getTableFormat(),
             getSyncResult(
-                targetClient,
+                conversionTarget,
                 SyncMode.FULL,
                 internalTable,
                 client -> client.syncFilesForSnapshot(snapshot.getPartitionedDataFiles()),
@@ -77,7 +77,7 @@ public class TableFormatSync {
       } catch (Exception e) {
         log.error("Failed to sync snapshot", e);
         results.put(
-            targetClient.getTableFormat(), buildResultForError(SyncMode.FULL, startTime, e));
+            conversionTarget.getTableFormat(), buildResultForError(SyncMode.FULL, startTime, e));
       }
     }
     return results;
@@ -91,13 +91,13 @@ public class TableFormatSync {
    * @return the results of trying to sync each change
    */
   public Map<String, List<SyncResult>> syncChanges(
-      Map<TargetClient, TableSyncMetadata> targetClientWithMetadata,
+      Map<ConversionTarget, TableSyncMetadata> targetClientWithMetadata,
       IncrementalTableChanges changes) {
     Map<String, List<SyncResult>> results = new HashMap<>();
-    Set<TargetClient> clientsWithFailures = new HashSet<>();
+    Set<ConversionTarget> clientsWithFailures = new HashSet<>();
     while (changes.getTableChanges().hasNext()) {
       TableChange change = changes.getTableChanges().next();
-      Collection<TargetClient> clientsToSync =
+      Collection<ConversionTarget> clientsToSync =
           targetClientWithMetadata.entrySet().stream()
               .filter(
                   entry -> {
@@ -106,17 +106,17 @@ public class TableFormatSync {
                   })
               .map(Map.Entry::getKey)
               .collect(Collectors.toList());
-      for (TargetClient targetClient : clientsToSync) {
-        if (clientsWithFailures.contains(targetClient)) {
+      for (ConversionTarget conversionTarget : clientsToSync) {
+        if (clientsWithFailures.contains(conversionTarget)) {
           continue;
         }
         Instant startTime = Instant.now();
         List<SyncResult> resultsForFormat =
-            results.computeIfAbsent(targetClient.getTableFormat(), key -> new ArrayList<>());
+            results.computeIfAbsent(conversionTarget.getTableFormat(), key -> new ArrayList<>());
         try {
           resultsForFormat.add(
               getSyncResult(
-                  targetClient,
+                  conversionTarget,
                   SyncMode.INCREMENTAL,
                   change.getTableAsOfChange(),
                   client -> client.syncFilesForDiff(change.getFilesDiff()),
@@ -125,7 +125,7 @@ public class TableFormatSync {
         } catch (Exception e) {
           log.error("Failed to sync table changes", e);
           resultsForFormat.add(buildResultForError(SyncMode.INCREMENTAL, startTime, e));
-          clientsWithFailures.add(targetClient);
+          clientsWithFailures.add(conversionTarget);
         }
       }
     }
@@ -144,7 +144,7 @@ public class TableFormatSync {
   }
 
   private SyncResult getSyncResult(
-      TargetClient client,
+      ConversionTarget client,
       SyncMode mode,
       InternalTable tableState,
       SyncFiles fileSyncMethod,
@@ -175,7 +175,7 @@ public class TableFormatSync {
 
   @FunctionalInterface
   private interface SyncFiles {
-    void sync(TargetClient client);
+    void sync(ConversionTarget client);
   }
 
   private SyncResult buildResultForError(SyncMode mode, Instant startTime, Exception e) {
diff --git a/api/src/test/java/org/apache/xtable/spi/extractor/TestExtractFromSource.java b/api/src/test/java/org/apache/xtable/spi/extractor/TestExtractFromSource.java
index de77fad7..82b61609 100644
--- a/api/src/test/java/org/apache/xtable/spi/extractor/TestExtractFromSource.java
+++ b/api/src/test/java/org/apache/xtable/spi/extractor/TestExtractFromSource.java
@@ -47,7 +47,7 @@ import org.apache.xtable.model.storage.InternalDataFile;
 import org.apache.xtable.model.storage.PartitionFileGroup;
 
 public class TestExtractFromSource {
-  private final SourceClient<TestCommit> mockSourceClient = mock(SourceClient.class);
+  private final ConversionSource<TestCommit> mockConversionSource = mock(ConversionSource.class);
 
   @Test
   public void extractSnapshot() {
@@ -60,8 +60,8 @@ public class TestExtractFromSource {
             .table(table)
             .partitionedDataFiles(dataFiles)
             .build();
-    when(mockSourceClient.getCurrentSnapshot()).thenReturn(internalSnapshot);
-    assertEquals(internalSnapshot, ExtractFromSource.of(mockSourceClient).extractSnapshot());
+    when(mockConversionSource.getCurrentSnapshot()).thenReturn(internalSnapshot);
+    assertEquals(internalSnapshot, ExtractFromSource.of(mockConversionSource).extractSnapshot());
   }
 
   @Test
@@ -80,7 +80,7 @@ public class TestExtractFromSource {
             .commitsToProcess(Arrays.asList(firstCommitToSync, secondCommitToSync))
             .inFlightInstants(Collections.singletonList(inflightInstant))
             .build();
-    when(mockSourceClient.getCommitsBacklog(instantsForIncrementalSync))
+    when(mockConversionSource.getCommitsBacklog(instantsForIncrementalSync))
         .thenReturn(commitsBacklogToReturn);
 
     // drop a file and add a file
@@ -93,7 +93,7 @@ public class TestExtractFromSource {
             .filesDiff(
                 DataFilesDiff.builder().fileAdded(newFile1).fileRemoved(initialFile2).build())
             .build();
-    when(mockSourceClient.getTableChangeForCommit(firstCommitToSync))
+    when(mockConversionSource.getTableChangeForCommit(firstCommitToSync))
         .thenReturn(tableChangeToReturnAtFirstInstant);
     TableChange expectedFirstTableChange =
         TableChange.builder()
@@ -117,7 +117,7 @@ public class TestExtractFromSource {
                     .filesRemoved(Arrays.asList(initialFile3, newFile1))
                     .build())
             .build();
-    when(mockSourceClient.getTableChangeForCommit(secondCommitToSync))
+    when(mockConversionSource.getTableChangeForCommit(secondCommitToSync))
         .thenReturn(tableChangeToReturnAtSecondInstant);
     TableChange expectedSecondTableChange =
         TableChange.builder()
@@ -130,7 +130,7 @@ public class TestExtractFromSource {
             .build();
 
     IncrementalTableChanges actual =
-        ExtractFromSource.of(mockSourceClient).extractTableChanges(instantsForIncrementalSync);
+        ExtractFromSource.of(mockConversionSource).extractTableChanges(instantsForIncrementalSync);
     assertEquals(Collections.singletonList(inflightInstant), actual.getPendingCommits());
     List<TableChange> actualTableChanges = new ArrayList<>();
     actual.getTableChanges().forEachRemaining(actualTableChanges::add);
diff --git a/api/src/test/java/org/apache/xtable/spi/sync/TestTableFormatSync.java b/api/src/test/java/org/apache/xtable/spi/sync/TestTableFormatSync.java
index fbbacfba..4160bc17 100644
--- a/api/src/test/java/org/apache/xtable/spi/sync/TestTableFormatSync.java
+++ b/api/src/test/java/org/apache/xtable/spi/sync/TestTableFormatSync.java
@@ -56,8 +56,8 @@ import org.apache.xtable.model.sync.SyncMode;
 import org.apache.xtable.model.sync.SyncResult;
 
 public class TestTableFormatSync {
-  private final TargetClient mockTargetClient1 = mock(TargetClient.class);
-  private final TargetClient mockTargetClient2 = mock(TargetClient.class);
+  private final ConversionTarget mockConversionTarget1 = mock(ConversionTarget.class);
+  private final ConversionTarget mockConversionTarget2 = mock(ConversionTarget.class);
 
   @Test
   void syncSnapshotWithFailureForOneFormat() {
@@ -77,12 +77,14 @@ public class TestTableFormatSync {
             .partitionedDataFiles(fileGroups)
             .pendingCommits(pendingCommitInstants)
             .build();
-    when(mockTargetClient1.getTableFormat()).thenReturn(TableFormat.ICEBERG);
-    when(mockTargetClient2.getTableFormat()).thenReturn(TableFormat.DELTA);
-    doThrow(new RuntimeException("Failure")).when(mockTargetClient1).beginSync(startingTableState);
+    when(mockConversionTarget1.getTableFormat()).thenReturn(TableFormat.ICEBERG);
+    when(mockConversionTarget2.getTableFormat()).thenReturn(TableFormat.DELTA);
+    doThrow(new RuntimeException("Failure"))
+        .when(mockConversionTarget1)
+        .beginSync(startingTableState);
     Map<String, SyncResult> result =
         TableFormatSync.getInstance()
-            .syncSnapshot(Arrays.asList(mockTargetClient1, mockTargetClient2), snapshot);
+            .syncSnapshot(Arrays.asList(mockConversionTarget1, mockConversionTarget2), snapshot);
 
     assertEquals(2, result.size());
     SyncResult successResult = result.get(TableFormat.DELTA);
@@ -103,10 +105,10 @@ public class TestTableFormatSync {
             .build(),
         failureResult.getStatus());
 
-    verifyBaseClientCalls(mockTargetClient2, startingTableState, pendingCommitInstants);
-    verify(mockTargetClient2).syncFilesForSnapshot(fileGroups);
-    verify(mockTargetClient2).completeSync();
-    verify(mockTargetClient1, never()).completeSync();
+    verifyBaseClientCalls(mockConversionTarget2, startingTableState, pendingCommitInstants);
+    verify(mockConversionTarget2).syncFilesForSnapshot(fileGroups);
+    verify(mockConversionTarget2).completeSync();
+    verify(mockConversionTarget1, never()).completeSync();
   }
 
   private static void assertSyncResultTimes(SyncResult syncResult, Instant start) {
@@ -132,11 +134,11 @@ public class TestTableFormatSync {
         TableChange.builder().tableAsOfChange(tableState3).filesDiff(dataFilesDiff3).build();
 
     List<Instant> pendingCommitInstants = Collections.singletonList(Instant.now());
-    when(mockTargetClient1.getTableFormat()).thenReturn(TableFormat.ICEBERG);
-    when(mockTargetClient2.getTableFormat()).thenReturn(TableFormat.DELTA);
+    when(mockConversionTarget1.getTableFormat()).thenReturn(TableFormat.ICEBERG);
+    when(mockConversionTarget2.getTableFormat()).thenReturn(TableFormat.DELTA);
     // throw exception on second change and show that first change is still returned for this format
     // and other client is not affected
-    doThrow(new RuntimeException("Failure")).when(mockTargetClient1).beginSync(tableState2);
+    doThrow(new RuntimeException("Failure")).when(mockConversionTarget1).beginSync(tableState2);
 
     List<TableChange> tableChanges = Arrays.asList(tableChange1, tableChange2, tableChange3);
     IncrementalTableChanges incrementalTableChanges =
@@ -145,12 +147,12 @@ public class TestTableFormatSync {
             .tableChanges(tableChanges.iterator())
             .build();
 
-    Map<TargetClient, TableSyncMetadata> clientWithMetadata = new HashMap<>();
+    Map<ConversionTarget, TableSyncMetadata> clientWithMetadata = new HashMap<>();
     clientWithMetadata.put(
-        mockTargetClient1,
+        mockConversionTarget1,
         TableSyncMetadata.of(Instant.now().minus(1, ChronoUnit.HOURS), Collections.emptyList()));
     clientWithMetadata.put(
-        mockTargetClient2,
+        mockConversionTarget2,
         TableSyncMetadata.of(Instant.now().minus(1, ChronoUnit.HOURS), Collections.emptyList()));
 
     Map<String, List<SyncResult>> result =
@@ -190,16 +192,16 @@ public class TestTableFormatSync {
       assertSyncResultTimes(successResults.get(i), start);
     }
 
-    verifyBaseClientCalls(mockTargetClient1, tableState1, pendingCommitInstants);
-    verify(mockTargetClient1).syncFilesForDiff(dataFilesDiff1);
-    verifyBaseClientCalls(mockTargetClient2, tableState1, pendingCommitInstants);
-    verify(mockTargetClient2).syncFilesForDiff(dataFilesDiff1);
-    verifyBaseClientCalls(mockTargetClient2, tableState2, pendingCommitInstants);
-    verify(mockTargetClient2).syncFilesForDiff(dataFilesDiff2);
-    verifyBaseClientCalls(mockTargetClient2, tableState3, pendingCommitInstants);
-    verify(mockTargetClient2).syncFilesForDiff(dataFilesDiff3);
-    verify(mockTargetClient1, times(1)).completeSync();
-    verify(mockTargetClient2, times(3)).completeSync();
+    verifyBaseClientCalls(mockConversionTarget1, tableState1, pendingCommitInstants);
+    verify(mockConversionTarget1).syncFilesForDiff(dataFilesDiff1);
+    verifyBaseClientCalls(mockConversionTarget2, tableState1, pendingCommitInstants);
+    verify(mockConversionTarget2).syncFilesForDiff(dataFilesDiff1);
+    verifyBaseClientCalls(mockConversionTarget2, tableState2, pendingCommitInstants);
+    verify(mockConversionTarget2).syncFilesForDiff(dataFilesDiff2);
+    verifyBaseClientCalls(mockConversionTarget2, tableState3, pendingCommitInstants);
+    verify(mockConversionTarget2).syncFilesForDiff(dataFilesDiff3);
+    verify(mockConversionTarget1, times(1)).completeSync();
+    verify(mockConversionTarget2, times(3)).completeSync();
   }
 
   @Test
@@ -219,8 +221,8 @@ public class TestTableFormatSync {
         TableChange.builder().tableAsOfChange(tableState3).filesDiff(dataFilesDiff3).build();
 
     List<Instant> pendingCommitInstants = Collections.singletonList(Instant.now());
-    when(mockTargetClient1.getTableFormat()).thenReturn(TableFormat.ICEBERG);
-    when(mockTargetClient2.getTableFormat()).thenReturn(TableFormat.DELTA);
+    when(mockConversionTarget1.getTableFormat()).thenReturn(TableFormat.ICEBERG);
+    when(mockConversionTarget2.getTableFormat()).thenReturn(TableFormat.DELTA);
 
     List<TableChange> tableChanges = Arrays.asList(tableChange1, tableChange2, tableChange3);
     IncrementalTableChanges incrementalTableChanges =
@@ -229,17 +231,17 @@ public class TestTableFormatSync {
             .tableChanges(tableChanges.iterator())
             .build();
 
-    Map<TargetClient, TableSyncMetadata> clientWithMetadata = new HashMap<>();
-    // mockTargetClient1 will have the first table change as a previously pending instant and
+    Map<ConversionTarget, TableSyncMetadata> clientWithMetadata = new HashMap<>();
+    // mockConversionTarget1 will have the first table change as a previously pending instant and
     // otherwise be synced up to the 2nd change
     clientWithMetadata.put(
-        mockTargetClient1,
+        mockConversionTarget1,
         TableSyncMetadata.of(
             tableChange2.getTableAsOfChange().getLatestCommitTime(),
             Collections.singletonList(tableChange1.getTableAsOfChange().getLatestCommitTime())));
-    // mockTargetClient2 will have synced the first table change previously
+    // mockConversionTarget2 will have synced the first table change previously
     clientWithMetadata.put(
-        mockTargetClient2,
+        mockConversionTarget2,
         TableSyncMetadata.of(
             tableChange1.getTableAsOfChange().getLatestCommitTime(), Collections.emptyList()));
 
@@ -275,17 +277,17 @@ public class TestTableFormatSync {
     }
 
     // client1 syncs table changes 1 and 3
-    verifyBaseClientCalls(mockTargetClient1, tableState1, pendingCommitInstants);
-    verify(mockTargetClient1).syncFilesForDiff(dataFilesDiff1);
-    verifyBaseClientCalls(mockTargetClient1, tableState3, pendingCommitInstants);
-    verify(mockTargetClient1).syncFilesForDiff(dataFilesDiff3);
-    verify(mockTargetClient1, times(2)).completeSync();
+    verifyBaseClientCalls(mockConversionTarget1, tableState1, pendingCommitInstants);
+    verify(mockConversionTarget1).syncFilesForDiff(dataFilesDiff1);
+    verifyBaseClientCalls(mockConversionTarget1, tableState3, pendingCommitInstants);
+    verify(mockConversionTarget1).syncFilesForDiff(dataFilesDiff3);
+    verify(mockConversionTarget1, times(2)).completeSync();
     // client2 syncs table changes 2 and 3
-    verifyBaseClientCalls(mockTargetClient2, tableState2, pendingCommitInstants);
-    verify(mockTargetClient2).syncFilesForDiff(dataFilesDiff2);
-    verifyBaseClientCalls(mockTargetClient2, tableState3, pendingCommitInstants);
-    verify(mockTargetClient2).syncFilesForDiff(dataFilesDiff3);
-    verify(mockTargetClient2, times(2)).completeSync();
+    verifyBaseClientCalls(mockConversionTarget2, tableState2, pendingCommitInstants);
+    verify(mockConversionTarget2).syncFilesForDiff(dataFilesDiff2);
+    verifyBaseClientCalls(mockConversionTarget2, tableState3, pendingCommitInstants);
+    verify(mockConversionTarget2).syncFilesForDiff(dataFilesDiff3);
+    verify(mockConversionTarget2, times(2)).completeSync();
   }
 
   @Test
@@ -297,8 +299,8 @@ public class TestTableFormatSync {
         TableChange.builder().tableAsOfChange(tableState1).filesDiff(dataFilesDiff1).build();
 
     List<Instant> pendingCommitInstants = Collections.emptyList();
-    when(mockTargetClient1.getTableFormat()).thenReturn(TableFormat.ICEBERG);
-    when(mockTargetClient2.getTableFormat()).thenReturn(TableFormat.DELTA);
+    when(mockConversionTarget1.getTableFormat()).thenReturn(TableFormat.ICEBERG);
+    when(mockConversionTarget2.getTableFormat()).thenReturn(TableFormat.DELTA);
 
     List<TableChange> tableChanges = Collections.singletonList(tableChange1);
     IncrementalTableChanges incrementalTableChanges =
@@ -307,13 +309,13 @@ public class TestTableFormatSync {
             .tableChanges(tableChanges.iterator())
             .build();
 
-    Map<TargetClient, TableSyncMetadata> clientWithMetadata = new HashMap<>();
-    // mockTargetClient1 will have nothing to sync
+    Map<ConversionTarget, TableSyncMetadata> clientWithMetadata = new HashMap<>();
+    // mockConversionTarget1 will have nothing to sync
     clientWithMetadata.put(
-        mockTargetClient1, TableSyncMetadata.of(Instant.now(), Collections.emptyList()));
-    // mockTargetClient2 will have synced the first table change previously
+        mockConversionTarget1, TableSyncMetadata.of(Instant.now(), Collections.emptyList()));
+    // mockConversionTarget2 will have synced the first table change previously
     clientWithMetadata.put(
-        mockTargetClient2,
+        mockConversionTarget2,
         TableSyncMetadata.of(Instant.now().minus(1, ChronoUnit.HOURS), Collections.emptyList()));
 
     Map<String, List<SyncResult>> result =
@@ -328,12 +330,12 @@ public class TestTableFormatSync {
           assertSyncResultTimes(syncResult, start);
         });
 
-    verify(mockTargetClient1, never()).beginSync(any());
-    verify(mockTargetClient1, never()).syncFilesForDiff(any());
-    verify(mockTargetClient1, never()).completeSync();
+    verify(mockConversionTarget1, never()).beginSync(any());
+    verify(mockConversionTarget1, never()).syncFilesForDiff(any());
+    verify(mockConversionTarget1, never()).completeSync();
 
-    verifyBaseClientCalls(mockTargetClient2, tableState1, pendingCommitInstants);
-    verify(mockTargetClient2).syncFilesForDiff(dataFilesDiff1);
+    verifyBaseClientCalls(mockConversionTarget2, tableState1, pendingCommitInstants);
+    verify(mockConversionTarget2).syncFilesForDiff(dataFilesDiff1);
   }
 
   /**
@@ -371,7 +373,7 @@ public class TestTableFormatSync {
   }
 
   private void verifyBaseClientCalls(
-      TargetClient mockClient,
+      ConversionTarget mockClient,
       InternalTable startingTableState,
       List<Instant> pendingCommitInstants) {
     verify(mockClient).beginSync(startingTableState);
diff --git a/core/src/main/java/org/apache/xtable/client/OneTableClient.java b/core/src/main/java/org/apache/xtable/conversion/ConversionController.java
similarity index 79%
rename from core/src/main/java/org/apache/xtable/client/OneTableClient.java
rename to core/src/main/java/org/apache/xtable/conversion/ConversionController.java
index 280bf6b4..1d356e6e 100644
--- a/core/src/main/java/org/apache/xtable/client/OneTableClient.java
+++ b/core/src/main/java/org/apache/xtable/conversion/ConversionController.java
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
  
-package org.apache.xtable.client;
+package org.apache.xtable.conversion;
 
 import java.io.IOException;
 import java.time.Instant;
@@ -45,10 +45,10 @@ import org.apache.xtable.model.InternalSnapshot;
 import org.apache.xtable.model.TableSyncMetadata;
 import org.apache.xtable.model.sync.SyncMode;
 import org.apache.xtable.model.sync.SyncResult;
+import org.apache.xtable.spi.extractor.ConversionSource;
 import org.apache.xtable.spi.extractor.ExtractFromSource;
-import org.apache.xtable.spi.extractor.SourceClient;
+import org.apache.xtable.spi.sync.ConversionTarget;
 import org.apache.xtable.spi.sync.TableFormatSync;
-import org.apache.xtable.spi.sync.TargetClient;
 
 /**
  * Responsible for completing the entire lifecycle of the sync process given {@link
@@ -62,13 +62,13 @@ import org.apache.xtable.spi.sync.TargetClient;
  */
 @Log4j2
 @RequiredArgsConstructor(access = AccessLevel.PACKAGE)
-public class OneTableClient {
+public class ConversionController {
   private final Configuration conf;
-  private final TableFormatClientFactory tableFormatClientFactory;
+  private final ConversionTargetFactory conversionTargetFactory;
   private final TableFormatSync tableFormatSync;
 
-  public OneTableClient(Configuration conf) {
-    this(conf, TableFormatClientFactory.getInstance(), TableFormatSync.getInstance());
+  public ConversionController(Configuration conf) {
+    this(conf, ConversionTargetFactory.getInstance(), TableFormatSync.getInstance());
   }
 
   /**
@@ -76,38 +76,43 @@ public class OneTableClient {
    *
    * @param config A per table level config containing tableBasePath, partitionFieldSpecConfig,
    *     targetTableFormats and syncMode
-   * @param sourceClientProvider A provider for the source client instance, {@link
-   *     SourceClientProvider#init(Configuration, Map)} must be called before calling this method.
+   * @param conversionSourceProvider A provider for the {@link ConversionSource} instance, {@link
+   *     ConversionSourceProvider#init(Configuration, Map)} must be called before calling this
+   *     method.
    * @return Returns a map containing the table format, and it's sync result. Run sync for a table
    *     with the provided per table level configuration.
    */
   public <COMMIT> Map<String, SyncResult> sync(
-      PerTableConfig config, SourceClientProvider<COMMIT> sourceClientProvider) {
+      PerTableConfig config, ConversionSourceProvider<COMMIT> conversionSourceProvider) {
     if (config.getTargetTableFormats() == null || config.getTargetTableFormats().isEmpty()) {
       throw new IllegalArgumentException("Please provide at-least one format to sync");
     }
 
-    try (SourceClient<COMMIT> sourceClient = sourceClientProvider.getSourceClientInstance(config)) {
-      ExtractFromSource<COMMIT> source = ExtractFromSource.of(sourceClient);
+    try (ConversionSource<COMMIT> conversionSource =
+        conversionSourceProvider.getConversionSourceInstance(config)) {
+      ExtractFromSource<COMMIT> source = ExtractFromSource.of(conversionSource);
 
-      Map<String, TargetClient> syncClientByFormat =
+      Map<String, ConversionTarget> conversionTargetByFormat =
           config.getTargetTableFormats().stream()
               .collect(
                   Collectors.toMap(
                       Function.identity(),
                       tableFormat ->
-                          tableFormatClientFactory.createForFormat(tableFormat, config, conf)));
+                          conversionTargetFactory.createForFormat(tableFormat, config, conf)));
       // State for each TableFormat
       Map<String, Optional<TableSyncMetadata>> lastSyncMetadataByFormat =
-          syncClientByFormat.entrySet().stream()
+          conversionTargetByFormat.entrySet().stream()
               .collect(
                   Collectors.toMap(
                       Map.Entry::getKey, entry -> entry.getValue().getTableMetadata()));
-      Map<String, TargetClient> formatsToSyncIncrementally =
+      Map<String, ConversionTarget> formatsToSyncIncrementally =
           getFormatsToSyncIncrementally(
-              config, syncClientByFormat, lastSyncMetadataByFormat, source.getSourceClient());
-      Map<String, TargetClient> formatsToSyncBySnapshot =
-          syncClientByFormat.entrySet().stream()
+              config,
+              conversionTargetByFormat,
+              lastSyncMetadataByFormat,
+              source.getConversionSource());
+      Map<String, ConversionTarget> formatsToSyncBySnapshot =
+          conversionTargetByFormat.entrySet().stream()
               .filter(entry -> !formatsToSyncIncrementally.containsKey(entry.getKey()))
               .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
       SyncResultForTableFormats syncResultForSnapshotSync =
@@ -134,7 +139,7 @@ public class OneTableClient {
       }
       return syncResultsMerged;
     } catch (IOException ioException) {
-      throw new OneIOException("Failed to close source client", ioException);
+      throw new OneIOException("Failed to close source converter", ioException);
     }
   }
 
@@ -146,16 +151,16 @@ public class OneTableClient {
         .collect(Collectors.joining(","));
   }
 
-  private <COMMIT> Map<String, TargetClient> getFormatsToSyncIncrementally(
+  private <COMMIT> Map<String, ConversionTarget> getFormatsToSyncIncrementally(
       PerTableConfig perTableConfig,
-      Map<String, TargetClient> syncClientByFormat,
+      Map<String, ConversionTarget> conversionTargetByFormat,
       Map<String, Optional<TableSyncMetadata>> lastSyncMetadataByFormat,
-      SourceClient<COMMIT> sourceClient) {
+      ConversionSource<COMMIT> conversionSource) {
     if (perTableConfig.getSyncMode() == SyncMode.FULL) {
       // Full sync requested by config, hence no incremental sync.
       return Collections.emptyMap();
     }
-    return syncClientByFormat.entrySet().stream()
+    return conversionTargetByFormat.entrySet().stream()
         .filter(
             entry -> {
               Optional<Instant> lastSyncInstant =
@@ -167,30 +172,31 @@ public class OneTableClient {
                       .get(entry.getKey())
                       .map(TableSyncMetadata::getInstantsToConsiderForNextSync)
                       .orElse(Collections.emptyList());
-              return isIncrementalSyncSufficient(sourceClient, lastSyncInstant, pendingInstants);
+              return isIncrementalSyncSufficient(
+                  conversionSource, lastSyncInstant, pendingInstants);
             })
         .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
   }
 
   private <COMMIT> SyncResultForTableFormats syncSnapshot(
-      Map<String, TargetClient> syncClientByFormat, ExtractFromSource<COMMIT> source) {
+      Map<String, ConversionTarget> conversionTargetByFormat, ExtractFromSource<COMMIT> source) {
     InternalSnapshot snapshot = source.extractSnapshot();
     Map<String, SyncResult> syncResultsByFormat =
-        tableFormatSync.syncSnapshot(syncClientByFormat.values(), snapshot);
+        tableFormatSync.syncSnapshot(conversionTargetByFormat.values(), snapshot);
     return SyncResultForTableFormats.builder().lastSyncResult(syncResultsByFormat).build();
   }
 
   private <COMMIT> SyncResultForTableFormats syncIncrementalChanges(
-      Map<String, TargetClient> syncClientByFormat,
+      Map<String, ConversionTarget> conversionTargetByFormat,
       Map<String, Optional<TableSyncMetadata>> lastSyncMetadataByFormat,
       ExtractFromSource<COMMIT> source) {
     Map<String, SyncResult> syncResultsByFormat = Collections.emptyMap();
-    Map<TargetClient, TableSyncMetadata> filteredSyncMetadataByFormat =
+    Map<ConversionTarget, TableSyncMetadata> filteredSyncMetadataByFormat =
         lastSyncMetadataByFormat.entrySet().stream()
-            .filter(entry -> syncClientByFormat.containsKey(entry.getKey()))
+            .filter(entry -> conversionTargetByFormat.containsKey(entry.getKey()))
             .collect(
                 Collectors.toMap(
-                    entry -> syncClientByFormat.get(entry.getKey()),
+                    entry -> conversionTargetByFormat.get(entry.getKey()),
                     entry -> entry.getValue().get()));
 
     InstantsForIncrementalSync instantsForIncrementalSync =
@@ -211,14 +217,14 @@ public class OneTableClient {
   /**
    * Checks if incremental sync is sufficient for a target table format.
    *
-   * @param sourceClient {@link SourceClient}
+   * @param conversionSource {@link ConversionSource}
    * @param lastSyncInstant the last instant at which the target table format was synced
    * @param pendingInstants the list of pending instants for the target table format to consider for
    *     next sync
    * @return true if incremental sync is sufficient, false otherwise.
    */
   private <COMMIT> boolean isIncrementalSyncSufficient(
-      SourceClient<COMMIT> sourceClient,
+      ConversionSource<COMMIT> conversionSource,
       Optional<Instant> lastSyncInstant,
       List<Instant> pendingInstants) {
     Stream<Instant> pendingInstantsStream =
@@ -235,7 +241,7 @@ public class OneTableClient {
       return false;
     }
     boolean isIncrementalSafeFromInstant =
-        sourceClient.isIncrementalSyncSafeFrom(earliestInstant.get());
+        conversionSource.isIncrementalSyncSafeFrom(earliestInstant.get());
     if (!isIncrementalSafeFromInstant) {
       log.info(
           "Incremental sync is not safe from instant {}. Falling back to snapshot sync.",
@@ -246,7 +252,7 @@ public class OneTableClient {
   }
 
   private InstantsForIncrementalSync getMostOutOfSyncCommitAndPendingCommits(
-      Map<TargetClient, TableSyncMetadata> lastSyncMetadataByFormat) {
+      Map<ConversionTarget, TableSyncMetadata> lastSyncMetadataByFormat) {
     Optional<Instant> mostOutOfSyncCommit =
         lastSyncMetadataByFormat.values().stream()
             .map(TableSyncMetadata::getLastInstantSynced)
diff --git a/core/src/main/java/org/apache/xtable/client/SourceClientProvider.java b/core/src/main/java/org/apache/xtable/conversion/ConversionSourceProvider.java
similarity index 58%
rename from core/src/main/java/org/apache/xtable/client/SourceClientProvider.java
rename to core/src/main/java/org/apache/xtable/conversion/ConversionSourceProvider.java
index 9c4c91bb..09cad6db 100644
--- a/core/src/main/java/org/apache/xtable/client/SourceClientProvider.java
+++ b/core/src/main/java/org/apache/xtable/conversion/ConversionSourceProvider.java
@@ -16,42 +16,43 @@
  * limitations under the License.
  */
  
-package org.apache.xtable.client;
+package org.apache.xtable.conversion;
 
 import java.util.Map;
 
 import org.apache.hadoop.conf.Configuration;
 
-import org.apache.xtable.spi.extractor.SourceClient;
+import org.apache.xtable.spi.extractor.ConversionSource;
 
 /**
- * Provides the functionality to provide an instance of the {@link SourceClient} for a given table
- * format. The provider can create a new instance of the client for each table format or reuse the
- * same instance.
+ * Provides the functionality to provide an instance of the {@link ConversionSource} for a given
+ * table format. The provider can create a new instance of the conversion source for each table
+ * format or reuse the same instance.
  */
-public abstract class SourceClientProvider<COMMIT> {
+public abstract class ConversionSourceProvider<COMMIT> {
   /** The Hadoop configuration to use when reading from the source table. */
   protected Configuration hadoopConf;
 
-  /** The configuration for the client. */
-  protected Map<String, String> clientConf;
+  /** The configuration for the source. */
+  protected Map<String, String> sourceConf;
 
   /** The configuration for the table to read from. */
   protected PerTableConfig sourceTableConfig;
 
-  /** Initializes the provider various client specific configurations. */
-  public void init(Configuration hadoopConf, Map<String, String> clientConf) {
+  /** Initializes the provider various source specific configurations. */
+  public void init(Configuration hadoopConf, Map<String, String> sourceConf) {
     this.hadoopConf = hadoopConf;
-    this.clientConf = clientConf;
+    this.sourceConf = sourceConf;
   }
 
   /**
-   * Returns an instance of the {@link SourceClient} for the given table format. The {@link
-   * SourceClient} is source table aware. A source table may require creation of a new instance of
-   * the client. In some cases reusing the same instance across table configurations may be
+   * Returns an instance of the {@link ConversionSource} for the given table format. The {@link
+   * ConversionSource} is source table aware. A source table may require creation of a new instance
+   * of the source. In some cases reusing the same instance across table configurations may be
    * efficient. The provider can decide how to manage this.
    *
-   * @return the source client
+   * @return the conversion source
    */
-  public abstract SourceClient<COMMIT> getSourceClientInstance(PerTableConfig sourceTableConfig);
+  public abstract ConversionSource<COMMIT> getConversionSourceInstance(
+      PerTableConfig sourceTableConfig);
 }
diff --git a/core/src/main/java/org/apache/xtable/client/TableFormatClientFactory.java b/core/src/main/java/org/apache/xtable/conversion/ConversionTargetFactory.java
similarity index 55%
rename from core/src/main/java/org/apache/xtable/client/TableFormatClientFactory.java
rename to core/src/main/java/org/apache/xtable/conversion/ConversionTargetFactory.java
index 6b6a8796..68e85b4d 100644
--- a/core/src/main/java/org/apache/xtable/client/TableFormatClientFactory.java
+++ b/core/src/main/java/org/apache/xtable/conversion/ConversionTargetFactory.java
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
  
-package org.apache.xtable.client;
+package org.apache.xtable.conversion;
 
 import java.util.ServiceLoader;
 
@@ -26,45 +26,46 @@ import lombok.NoArgsConstructor;
 import org.apache.hadoop.conf.Configuration;
 
 import org.apache.xtable.exception.NotSupportedException;
-import org.apache.xtable.spi.sync.TargetClient;
+import org.apache.xtable.spi.sync.ConversionTarget;
 
 @NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class TableFormatClientFactory {
-  private static final TableFormatClientFactory INSTANCE = new TableFormatClientFactory();
+public class ConversionTargetFactory {
+  private static final ConversionTargetFactory INSTANCE = new ConversionTargetFactory();
 
-  public static TableFormatClientFactory getInstance() {
+  public static ConversionTargetFactory getInstance() {
     return INSTANCE;
   }
 
   /**
-   * Create a fully initialized instance of the TargetClient represented by the given Table Format
-   * name. Initialization is done with the config provideed through PerTableConfig and Conifuration
-   * params.
+   * Create a fully initialized instance of the ConversionTarget represented by the given Table
+   * Format name. Initialization is done with the config provided through PerTableConfig and
+   * Configuration params.
    *
    * @param tableFormat
    * @param perTableConfig
    * @param configuration
    * @return
    */
-  public TargetClient createForFormat(
+  public ConversionTarget createForFormat(
       String tableFormat, PerTableConfig perTableConfig, Configuration configuration) {
-    TargetClient targetClient = createTargetClientForName(tableFormat);
+    ConversionTarget conversionTarget = createConversionTargetForName(tableFormat);
 
-    targetClient.init(perTableConfig, configuration);
-    return targetClient;
+    conversionTarget.init(perTableConfig, configuration);
+    return conversionTarget;
   }
 
   /**
-   * Create an instance of the TargetClient via the default no-arg constructor. Expectation is that
-   * target client specific settings may be provided prior to the calling of TargetClient.init()
-   * which must be called prior to actual use of the target client returned by this factory method.
+   * Create an instance of the ConversionTarget via the default no-arg constructor. Expectation is
+   * that target conversion specific settings may be provided prior to the calling of
+   * ConversionTarget.init() which must be called prior to actual use of the conversion target
+   * returned by this factory method.
    *
    * @param tableFormatName
    * @return
    */
-  public TargetClient createTargetClientForName(String tableFormatName) {
-    ServiceLoader<TargetClient> loader = ServiceLoader.load(TargetClient.class);
-    for (TargetClient target : loader) {
+  public ConversionTarget createConversionTargetForName(String tableFormatName) {
+    ServiceLoader<ConversionTarget> loader = ServiceLoader.load(ConversionTarget.class);
+    for (ConversionTarget target : loader) {
       if (target.getTableFormat().equalsIgnoreCase(tableFormatName)) {
         return target;
       }
diff --git a/core/src/main/java/org/apache/xtable/client/PerTableConfigImpl.java b/core/src/main/java/org/apache/xtable/conversion/PerTableConfigImpl.java
similarity index 99%
rename from core/src/main/java/org/apache/xtable/client/PerTableConfigImpl.java
rename to core/src/main/java/org/apache/xtable/conversion/PerTableConfigImpl.java
index 37bacd4d..f34402b1 100644
--- a/core/src/main/java/org/apache/xtable/client/PerTableConfigImpl.java
+++ b/core/src/main/java/org/apache/xtable/conversion/PerTableConfigImpl.java
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
  
-package org.apache.xtable.client;
+package org.apache.xtable.conversion;
 
 import java.util.List;
 
diff --git a/core/src/main/java/org/apache/xtable/delta/DeltaSourceClient.java b/core/src/main/java/org/apache/xtable/delta/DeltaConversionSource.java
similarity index 97%
rename from core/src/main/java/org/apache/xtable/delta/DeltaSourceClient.java
rename to core/src/main/java/org/apache/xtable/delta/DeltaConversionSource.java
index c33db77d..ae572ca1 100644
--- a/core/src/main/java/org/apache/xtable/delta/DeltaSourceClient.java
+++ b/core/src/main/java/org/apache/xtable/delta/DeltaConversionSource.java
@@ -57,12 +57,12 @@ import org.apache.xtable.model.storage.DataFilesDiff;
 import org.apache.xtable.model.storage.FileFormat;
 import org.apache.xtable.model.storage.InternalDataFile;
 import org.apache.xtable.model.storage.PartitionFileGroup;
+import org.apache.xtable.spi.extractor.ConversionSource;
 import org.apache.xtable.spi.extractor.DataFileIterator;
-import org.apache.xtable.spi.extractor.SourceClient;
 
 @Log4j2
 @Builder
-public class DeltaSourceClient implements SourceClient<Long> {
+public class DeltaConversionSource implements ConversionSource<Long> {
   @Builder.Default
   private final DeltaDataFileExtractor dataFileExtractor = DeltaDataFileExtractor.builder().build();
 
@@ -109,7 +109,7 @@ public class DeltaSourceClient implements SourceClient<Long> {
   @Override
   public TableChange getTableChangeForCommit(Long versionNumber) {
     InternalTable tableAtVersion = tableExtractor.table(deltaLog, tableName, versionNumber);
-    // Client to call getCommitsBacklog and call this method.
+    // Source to call getCommitsBacklog and call this method.
     List<Action> actionsForVersion = getChangesState().getActionsForVersion(versionNumber);
     Snapshot snapshotAtVersion = deltaLog.getSnapshotAt(versionNumber, Option.empty());
     FileFormat fileFormat =
diff --git a/core/src/main/java/org/apache/xtable/delta/DeltaSourceClientProvider.java b/core/src/main/java/org/apache/xtable/delta/DeltaConversionSourceProvider.java
similarity index 56%
rename from core/src/main/java/org/apache/xtable/delta/DeltaSourceClientProvider.java
rename to core/src/main/java/org/apache/xtable/delta/DeltaConversionSourceProvider.java
index c885efba..f42425db 100644
--- a/core/src/main/java/org/apache/xtable/delta/DeltaSourceClientProvider.java
+++ b/core/src/main/java/org/apache/xtable/delta/DeltaConversionSourceProvider.java
@@ -22,23 +22,21 @@ import org.apache.spark.sql.SparkSession;
 
 import io.delta.tables.DeltaTable;
 
-import org.apache.xtable.client.PerTableConfig;
-import org.apache.xtable.client.SourceClientProvider;
+import org.apache.xtable.conversion.ConversionSourceProvider;
+import org.apache.xtable.conversion.PerTableConfig;
 
-/** A concrete implementation of {@link SourceClientProvider} for Delta Lake table format. */
-public class DeltaSourceClientProvider extends SourceClientProvider<Long> {
+/** A concrete implementation of {@link ConversionSourceProvider} for Delta Lake table format. */
+public class DeltaConversionSourceProvider extends ConversionSourceProvider<Long> {
   @Override
-  public DeltaSourceClient getSourceClientInstance(PerTableConfig perTableConfig) {
-    SparkSession sparkSession = DeltaClientUtils.buildSparkSession(hadoopConf);
+  public DeltaConversionSource getConversionSourceInstance(PerTableConfig perTableConfig) {
+    SparkSession sparkSession = DeltaConversionUtils.buildSparkSession(hadoopConf);
     DeltaTable deltaTable = DeltaTable.forPath(sparkSession, perTableConfig.getTableBasePath());
-    DeltaSourceClient deltaSourceClient =
-        DeltaSourceClient.builder()
-            .sparkSession(sparkSession)
-            .tableName(perTableConfig.getTableName())
-            .basePath(perTableConfig.getTableBasePath())
-            .deltaTable(deltaTable)
-            .deltaLog(deltaTable.deltaLog())
-            .build();
-    return deltaSourceClient;
+    return DeltaConversionSource.builder()
+        .sparkSession(sparkSession)
+        .tableName(perTableConfig.getTableName())
+        .basePath(perTableConfig.getTableBasePath())
+        .deltaTable(deltaTable)
+        .deltaLog(deltaTable.deltaLog())
+        .build();
   }
 }
diff --git a/core/src/main/java/org/apache/xtable/delta/DeltaClient.java b/core/src/main/java/org/apache/xtable/delta/DeltaConversionTarget.java
similarity index 96%
rename from core/src/main/java/org/apache/xtable/delta/DeltaClient.java
rename to core/src/main/java/org/apache/xtable/delta/DeltaConversionTarget.java
index 9d54e2e7..798c3907 100644
--- a/core/src/main/java/org/apache/xtable/delta/DeltaClient.java
+++ b/core/src/main/java/org/apache/xtable/delta/DeltaConversionTarget.java
@@ -54,7 +54,7 @@ import scala.collection.Seq;
 
 import com.google.common.annotations.VisibleForTesting;
 
-import org.apache.xtable.client.PerTableConfig;
+import org.apache.xtable.conversion.PerTableConfig;
 import org.apache.xtable.exception.NotSupportedException;
 import org.apache.xtable.model.InternalTable;
 import org.apache.xtable.model.TableSyncMetadata;
@@ -63,9 +63,9 @@ import org.apache.xtable.model.schema.InternalSchema;
 import org.apache.xtable.model.storage.DataFilesDiff;
 import org.apache.xtable.model.storage.PartitionFileGroup;
 import org.apache.xtable.model.storage.TableFormat;
-import org.apache.xtable.spi.sync.TargetClient;
+import org.apache.xtable.spi.sync.ConversionTarget;
 
-public class DeltaClient implements TargetClient {
+public class DeltaConversionTarget implements ConversionTarget {
   private static final String MIN_READER_VERSION = String.valueOf(1);
   // gets access to generated columns.
   private static final String MIN_WRITER_VERSION = String.valueOf(4);
@@ -79,9 +79,9 @@ public class DeltaClient implements TargetClient {
   private int logRetentionInHours;
   private TransactionState transactionState;
 
-  public DeltaClient() {}
+  public DeltaConversionTarget() {}
 
-  public DeltaClient(PerTableConfig perTableConfig, SparkSession sparkSession) {
+  public DeltaConversionTarget(PerTableConfig perTableConfig, SparkSession sparkSession) {
     this(
         perTableConfig.getTableDataPath(),
         perTableConfig.getTableName(),
@@ -93,7 +93,7 @@ public class DeltaClient implements TargetClient {
   }
 
   @VisibleForTesting
-  DeltaClient(
+  DeltaConversionTarget(
       String tableDataPath,
       String tableName,
       int logRetentionInHours,
@@ -135,7 +135,7 @@ public class DeltaClient implements TargetClient {
 
   @Override
   public void init(PerTableConfig perTableConfig, Configuration configuration) {
-    SparkSession sparkSession = DeltaClientUtils.buildSparkSession(configuration);
+    SparkSession sparkSession = DeltaConversionUtils.buildSparkSession(configuration);
 
     _init(
         perTableConfig.getTableDataPath(),
diff --git a/core/src/main/java/org/apache/xtable/delta/DeltaClientUtils.java b/core/src/main/java/org/apache/xtable/delta/DeltaConversionUtils.java
similarity index 94%
rename from core/src/main/java/org/apache/xtable/delta/DeltaClientUtils.java
rename to core/src/main/java/org/apache/xtable/delta/DeltaConversionUtils.java
index fb5817bb..3401df84 100644
--- a/core/src/main/java/org/apache/xtable/delta/DeltaClientUtils.java
+++ b/core/src/main/java/org/apache/xtable/delta/DeltaConversionUtils.java
@@ -26,14 +26,14 @@ import org.apache.spark.SparkConf;
 import org.apache.spark.serializer.KryoSerializer;
 import org.apache.spark.sql.SparkSession;
 
-/** A utility class for Delta client. */
+/** A utility class for Delta conversion. */
 @NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class DeltaClientUtils {
+public class DeltaConversionUtils {
 
   static SparkSession buildSparkSession(Configuration conf) {
     SparkConf sparkConf =
         new SparkConf()
-            .setAppName("onetableclient")
+            .setAppName("xtable")
             .set("spark.serializer", KryoSerializer.class.getName())
             .set("spark.sql.extensions", "io.delta.sql.DeltaSparkSessionExtension")
             .set(
diff --git a/core/src/main/java/org/apache/xtable/delta/DeltaIncrementalChangesState.java b/core/src/main/java/org/apache/xtable/delta/DeltaIncrementalChangesState.java
index 70b4aaaa..4642e818 100644
--- a/core/src/main/java/org/apache/xtable/delta/DeltaIncrementalChangesState.java
+++ b/core/src/main/java/org/apache/xtable/delta/DeltaIncrementalChangesState.java
@@ -67,8 +67,8 @@ public class DeltaIncrementalChangesState {
 
   /**
    * Returns the versions in sorted order. The start version is the next one after the last sync
-   * version to the target client. The end version is the latest version in the Delta table at the
-   * time of initialization.
+   * version to the target. The end version is the latest version in the Delta table at the time of
+   * initialization.
    *
    * @return
    */
diff --git a/core/src/main/java/org/apache/xtable/hudi/HudiClient.java b/core/src/main/java/org/apache/xtable/hudi/HudiConversionSource.java
similarity index 98%
rename from core/src/main/java/org/apache/xtable/hudi/HudiClient.java
rename to core/src/main/java/org/apache/xtable/hudi/HudiConversionSource.java
index 2cdc4015..9e0a8d88 100644
--- a/core/src/main/java/org/apache/xtable/hudi/HudiClient.java
+++ b/core/src/main/java/org/apache/xtable/hudi/HudiConversionSource.java
@@ -50,15 +50,15 @@ import org.apache.xtable.model.InternalSnapshot;
 import org.apache.xtable.model.InternalTable;
 import org.apache.xtable.model.TableChange;
 import org.apache.xtable.model.schema.SchemaCatalog;
-import org.apache.xtable.spi.extractor.SourceClient;
+import org.apache.xtable.spi.extractor.ConversionSource;
 
-public class HudiClient implements SourceClient<HoodieInstant> {
+public class HudiConversionSource implements ConversionSource<HoodieInstant> {
 
   private final HoodieTableMetaClient metaClient;
   private final HudiTableExtractor tableExtractor;
   private final HudiDataFileExtractor dataFileExtractor;
 
-  public HudiClient(
+  public HudiConversionSource(
       HoodieTableMetaClient metaClient,
       HudiSourcePartitionSpecExtractor sourcePartitionSpecExtractor) {
     this.metaClient = metaClient;
diff --git a/core/src/main/java/org/apache/xtable/hudi/HudiSourceClientProvider.java b/core/src/main/java/org/apache/xtable/hudi/HudiConversionSourceProvider.java
similarity index 78%
rename from core/src/main/java/org/apache/xtable/hudi/HudiSourceClientProvider.java
rename to core/src/main/java/org/apache/xtable/hudi/HudiConversionSourceProvider.java
index 2c49f60e..f6e5e28d 100644
--- a/core/src/main/java/org/apache/xtable/hudi/HudiSourceClientProvider.java
+++ b/core/src/main/java/org/apache/xtable/hudi/HudiConversionSourceProvider.java
@@ -24,15 +24,15 @@ import org.apache.hudi.common.model.HoodieTableType;
 import org.apache.hudi.common.table.HoodieTableMetaClient;
 import org.apache.hudi.common.table.timeline.HoodieInstant;
 
-import org.apache.xtable.client.PerTableConfig;
-import org.apache.xtable.client.SourceClientProvider;
+import org.apache.xtable.conversion.ConversionSourceProvider;
+import org.apache.xtable.conversion.PerTableConfig;
 
-/** A concrete implementation of {@link SourceClientProvider} for Hudi table format. */
+/** A concrete implementation of {@link ConversionSourceProvider} for Hudi table format. */
 @Log4j2
-public class HudiSourceClientProvider extends SourceClientProvider<HoodieInstant> {
+public class HudiConversionSourceProvider extends ConversionSourceProvider<HoodieInstant> {
 
   @Override
-  public HudiClient getSourceClientInstance(PerTableConfig sourceTableConfig) {
+  public HudiConversionSource getConversionSourceInstance(PerTableConfig sourceTableConfig) {
     this.sourceTableConfig = sourceTableConfig;
     HoodieTableMetaClient metaClient =
         HoodieTableMetaClient.builder()
@@ -48,6 +48,6 @@ public class HudiSourceClientProvider extends SourceClientProvider<HoodieInstant
         (HudiSourcePartitionSpecExtractor)
             sourceTableConfig.getHudiSourceConfig().loadSourcePartitionSpecExtractor();
 
-    return new HudiClient(metaClient, sourcePartitionSpecExtractor);
+    return new HudiConversionSource(metaClient, sourcePartitionSpecExtractor);
   }
 }
diff --git a/core/src/main/java/org/apache/xtable/hudi/HudiTargetClient.java b/core/src/main/java/org/apache/xtable/hudi/HudiConversionTarget.java
similarity index 99%
rename from core/src/main/java/org/apache/xtable/hudi/HudiTargetClient.java
rename to core/src/main/java/org/apache/xtable/hudi/HudiConversionTarget.java
index 0168ae5b..424d8228 100644
--- a/core/src/main/java/org/apache/xtable/hudi/HudiTargetClient.java
+++ b/core/src/main/java/org/apache/xtable/hudi/HudiConversionTarget.java
@@ -79,7 +79,7 @@ import org.apache.hudi.table.action.clean.CleanPlanner;
 import com.google.common.annotations.VisibleForTesting;
 
 import org.apache.xtable.avro.AvroSchemaConverter;
-import org.apache.xtable.client.PerTableConfig;
+import org.apache.xtable.conversion.PerTableConfig;
 import org.apache.xtable.exception.NotSupportedException;
 import org.apache.xtable.exception.OneIOException;
 import org.apache.xtable.model.InternalTable;
@@ -90,10 +90,10 @@ import org.apache.xtable.model.schema.InternalSchema;
 import org.apache.xtable.model.storage.DataFilesDiff;
 import org.apache.xtable.model.storage.PartitionFileGroup;
 import org.apache.xtable.model.storage.TableFormat;
-import org.apache.xtable.spi.sync.TargetClient;
+import org.apache.xtable.spi.sync.ConversionTarget;
 
 @Log4j2
-public class HudiTargetClient implements TargetClient {
+public class HudiConversionTarget implements ConversionTarget {
   private BaseFileUpdatesExtractor baseFileUpdatesExtractor;
   private AvroSchemaConverter avroSchemaConverter;
   private HudiTableManager hudiTableManager;
@@ -104,10 +104,10 @@ public class HudiTargetClient implements TargetClient {
   private Optional<HoodieTableMetaClient> metaClient;
   private CommitState commitState;
 
-  public HudiTargetClient() {}
+  public HudiConversionTarget() {}
 
   @VisibleForTesting
-  HudiTargetClient(
+  HudiConversionTarget(
       PerTableConfig perTableConfig,
       Configuration configuration,
       int maxNumDeltaCommitsBeforeCompaction) {
@@ -124,7 +124,7 @@ public class HudiTargetClient implements TargetClient {
   }
 
   @VisibleForTesting
-  HudiTargetClient(
+  HudiConversionTarget(
       String tableDataPath,
       int timelineRetentionInHours,
       int maxNumDeltaCommitsBeforeCompaction,
diff --git a/core/src/main/java/org/apache/xtable/hudi/HudiSourceConfigImpl.java b/core/src/main/java/org/apache/xtable/hudi/HudiSourceConfigImpl.java
index e5fcf820..0fa8b529 100644
--- a/core/src/main/java/org/apache/xtable/hudi/HudiSourceConfigImpl.java
+++ b/core/src/main/java/org/apache/xtable/hudi/HudiSourceConfigImpl.java
@@ -28,7 +28,7 @@ import lombok.Value;
 
 import com.google.common.base.Preconditions;
 
-import org.apache.xtable.client.HudiSourceConfig;
+import org.apache.xtable.conversion.HudiSourceConfig;
 import org.apache.xtable.model.schema.PartitionTransformType;
 import org.apache.xtable.reflection.ReflectionUtils;
 
diff --git a/core/src/main/java/org/apache/xtable/iceberg/IcebergCatalogConfig.java b/core/src/main/java/org/apache/xtable/iceberg/IcebergCatalogConfig.java
index 317ddc0e..d5d7a3c5 100644
--- a/core/src/main/java/org/apache/xtable/iceberg/IcebergCatalogConfig.java
+++ b/core/src/main/java/org/apache/xtable/iceberg/IcebergCatalogConfig.java
@@ -25,7 +25,7 @@ import lombok.Builder;
 import lombok.NonNull;
 import lombok.Value;
 
-import org.apache.xtable.client.CatalogConfig;
+import org.apache.xtable.conversion.CatalogConfig;
 
 @Value
 @Builder
diff --git a/core/src/main/java/org/apache/xtable/iceberg/IcebergSourceClient.java b/core/src/main/java/org/apache/xtable/iceberg/IcebergConversionSource.java
similarity index 98%
rename from core/src/main/java/org/apache/xtable/iceberg/IcebergSourceClient.java
rename to core/src/main/java/org/apache/xtable/iceberg/IcebergConversionSource.java
index 415356c7..76775b49 100644
--- a/core/src/main/java/org/apache/xtable/iceberg/IcebergSourceClient.java
+++ b/core/src/main/java/org/apache/xtable/iceberg/IcebergConversionSource.java
@@ -36,7 +36,7 @@ import org.apache.iceberg.hadoop.HadoopFileIO;
 import org.apache.iceberg.io.CloseableIterable;
 import org.apache.iceberg.io.FileIO;
 
-import org.apache.xtable.client.PerTableConfig;
+import org.apache.xtable.conversion.PerTableConfig;
 import org.apache.xtable.exception.OneIOException;
 import org.apache.xtable.model.CommitsBacklog;
 import org.apache.xtable.model.InstantsForIncrementalSync;
@@ -50,11 +50,11 @@ import org.apache.xtable.model.schema.SchemaVersion;
 import org.apache.xtable.model.stat.PartitionValue;
 import org.apache.xtable.model.storage.*;
 import org.apache.xtable.model.storage.InternalDataFile;
-import org.apache.xtable.spi.extractor.SourceClient;
+import org.apache.xtable.spi.extractor.ConversionSource;
 
 @Log4j2
 @Builder
-public class IcebergSourceClient implements SourceClient<Snapshot> {
+public class IcebergConversionSource implements ConversionSource<Snapshot> {
   @NonNull private final Configuration hadoopConf;
   @NonNull private final PerTableConfig sourceTableConfig;
 
diff --git a/core/src/main/java/org/apache/xtable/iceberg/IcebergSourceClientProvider.java b/core/src/main/java/org/apache/xtable/iceberg/IcebergConversionSourceProvider.java
similarity index 69%
rename from core/src/main/java/org/apache/xtable/iceberg/IcebergSourceClientProvider.java
rename to core/src/main/java/org/apache/xtable/iceberg/IcebergConversionSourceProvider.java
index d3abf238..9a2bb840 100644
--- a/core/src/main/java/org/apache/xtable/iceberg/IcebergSourceClientProvider.java
+++ b/core/src/main/java/org/apache/xtable/iceberg/IcebergConversionSourceProvider.java
@@ -20,14 +20,14 @@ package org.apache.xtable.iceberg;
 
 import org.apache.iceberg.Snapshot;
 
-import org.apache.xtable.client.PerTableConfig;
-import org.apache.xtable.client.SourceClientProvider;
+import org.apache.xtable.conversion.ConversionSourceProvider;
+import org.apache.xtable.conversion.PerTableConfig;
 
-/** A concrete implementation of {@link SourceClientProvider} for Hudi table format. */
-public class IcebergSourceClientProvider extends SourceClientProvider<Snapshot> {
+/** A concrete implementation of {@link ConversionSourceProvider} for Hudi table format. */
+public class IcebergConversionSourceProvider extends ConversionSourceProvider<Snapshot> {
   @Override
-  public IcebergSourceClient getSourceClientInstance(PerTableConfig sourceTableConfig) {
-    return IcebergSourceClient.builder()
+  public IcebergConversionSource getConversionSourceInstance(PerTableConfig sourceTableConfig) {
+    return IcebergConversionSource.builder()
         .sourceTableConfig(sourceTableConfig)
         .hadoopConf(hadoopConf)
         .build();
diff --git a/core/src/main/java/org/apache/xtable/iceberg/IcebergClient.java b/core/src/main/java/org/apache/xtable/iceberg/IcebergConversionTarget.java
similarity index 97%
rename from core/src/main/java/org/apache/xtable/iceberg/IcebergClient.java
rename to core/src/main/java/org/apache/xtable/iceberg/IcebergConversionTarget.java
index 83957d44..f04b3419 100644
--- a/core/src/main/java/org/apache/xtable/iceberg/IcebergClient.java
+++ b/core/src/main/java/org/apache/xtable/iceberg/IcebergConversionTarget.java
@@ -43,7 +43,7 @@ import org.apache.iceberg.catalog.Namespace;
 import org.apache.iceberg.catalog.TableIdentifier;
 import org.apache.iceberg.exceptions.NotFoundException;
 
-import org.apache.xtable.client.PerTableConfig;
+import org.apache.xtable.conversion.PerTableConfig;
 import org.apache.xtable.model.InternalTable;
 import org.apache.xtable.model.TableSyncMetadata;
 import org.apache.xtable.model.schema.InternalPartitionField;
@@ -51,10 +51,10 @@ import org.apache.xtable.model.schema.InternalSchema;
 import org.apache.xtable.model.storage.DataFilesDiff;
 import org.apache.xtable.model.storage.PartitionFileGroup;
 import org.apache.xtable.model.storage.TableFormat;
-import org.apache.xtable.spi.sync.TargetClient;
+import org.apache.xtable.spi.sync.ConversionTarget;
 
 @Log4j2
-public class IcebergClient implements TargetClient {
+public class IcebergConversionTarget implements ConversionTarget {
   private static final String METADATA_DIR_PATH = "/metadata/";
   private IcebergSchemaExtractor schemaExtractor;
   private IcebergSchemaSync schemaSync;
@@ -71,9 +71,9 @@ public class IcebergClient implements TargetClient {
   private Table table;
   private InternalTable internalTableState;
 
-  public IcebergClient() {}
+  public IcebergConversionTarget() {}
 
-  IcebergClient(
+  IcebergConversionTarget(
       PerTableConfig perTableConfig,
       Configuration configuration,
       IcebergSchemaExtractor schemaExtractor,
@@ -123,7 +123,7 @@ public class IcebergClient implements TargetClient {
       // Load the table state if it already exists
       this.table = tableManager.getTable(catalogConfig, tableIdentifier, basePath);
     }
-    // Clear any corrupted state before using the target client
+    // Clear any corrupted state before using the conversion target
     rollbackCorruptCommits();
   }
 
diff --git a/core/src/main/resources/META-INF/services/org.apache.xtable.spi.sync.TargetClient b/core/src/main/resources/META-INF/services/org.apache.xtable.spi.sync.ConversionTarget
similarity index 86%
rename from core/src/main/resources/META-INF/services/org.apache.xtable.spi.sync.TargetClient
rename to core/src/main/resources/META-INF/services/org.apache.xtable.spi.sync.ConversionTarget
index 07eda44e..a00b41e0 100644
--- a/core/src/main/resources/META-INF/services/org.apache.xtable.spi.sync.TargetClient
+++ b/core/src/main/resources/META-INF/services/org.apache.xtable.spi.sync.ConversionTarget
@@ -16,6 +16,6 @@
 # limitations under the License.
 ##########################################################################
 
-org.apache.xtable.hudi.HudiTargetClient
-org.apache.xtable.delta.DeltaClient
-org.apache.xtable.iceberg.IcebergClient
+org.apache.xtable.hudi.HudiConversionTarget
+org.apache.xtable.delta.DeltaConversionTarget
+org.apache.xtable.iceberg.IcebergConversionTarget
diff --git a/core/src/test/java/org/apache/xtable/ITOneTableClient.java b/core/src/test/java/org/apache/xtable/ITConversionController.java
similarity index 84%
rename from core/src/test/java/org/apache/xtable/ITOneTableClient.java
rename to core/src/test/java/org/apache/xtable/ITConversionController.java
index 6f59e676..fda52d9c 100644
--- a/core/src/test/java/org/apache/xtable/ITOneTableClient.java
+++ b/core/src/test/java/org/apache/xtable/ITConversionController.java
@@ -81,19 +81,19 @@ import org.apache.spark.sql.delta.DeltaLog;
 
 import com.google.common.collect.ImmutableList;
 
-import org.apache.xtable.client.OneTableClient;
-import org.apache.xtable.client.PerTableConfig;
-import org.apache.xtable.client.PerTableConfigImpl;
-import org.apache.xtable.client.SourceClientProvider;
-import org.apache.xtable.delta.DeltaSourceClientProvider;
-import org.apache.xtable.hudi.HudiSourceClientProvider;
+import org.apache.xtable.conversion.ConversionController;
+import org.apache.xtable.conversion.ConversionSourceProvider;
+import org.apache.xtable.conversion.PerTableConfig;
+import org.apache.xtable.conversion.PerTableConfigImpl;
+import org.apache.xtable.delta.DeltaConversionSourceProvider;
+import org.apache.xtable.hudi.HudiConversionSourceProvider;
 import org.apache.xtable.hudi.HudiSourceConfigImpl;
 import org.apache.xtable.hudi.HudiTestUtil;
-import org.apache.xtable.iceberg.IcebergSourceClientProvider;
+import org.apache.xtable.iceberg.IcebergConversionSourceProvider;
 import org.apache.xtable.model.storage.TableFormat;
 import org.apache.xtable.model.sync.SyncMode;
 
-public class ITOneTableClient {
+public class ITConversionController {
   @TempDir public static Path tempDir;
   private static final DateTimeFormatter DATE_FORMAT =
       DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS").withZone(ZoneId.of("UTC"));
@@ -143,20 +143,22 @@ public class ITOneTableClient {
     return Stream.of(Arguments.of(SyncMode.INCREMENTAL), Arguments.of(SyncMode.FULL));
   }
 
-  private SourceClientProvider<?> getSourceClientProvider(String sourceTableFormat) {
+  private ConversionSourceProvider<?> getConversionSourceProvider(String sourceTableFormat) {
     if (sourceTableFormat.equalsIgnoreCase(HUDI)) {
-      SourceClientProvider<HoodieInstant> hudiSourceClientProvider = new HudiSourceClientProvider();
-      hudiSourceClientProvider.init(jsc.hadoopConfiguration(), Collections.emptyMap());
-      return hudiSourceClientProvider;
+      ConversionSourceProvider<HoodieInstant> hudiConversionSourceProvider =
+          new HudiConversionSourceProvider();
+      hudiConversionSourceProvider.init(jsc.hadoopConfiguration(), Collections.emptyMap());
+      return hudiConversionSourceProvider;
     } else if (sourceTableFormat.equalsIgnoreCase(DELTA)) {
-      SourceClientProvider<Long> deltaSourceClientProvider = new DeltaSourceClientProvider();
-      deltaSourceClientProvider.init(jsc.hadoopConfiguration(), Collections.emptyMap());
-      return deltaSourceClientProvider;
+      ConversionSourceProvider<Long> deltaConversionSourceProvider =
+          new DeltaConversionSourceProvider();
+      deltaConversionSourceProvider.init(jsc.hadoopConfiguration(), Collections.emptyMap());
+      return deltaConversionSourceProvider;
     } else if (sourceTableFormat.equalsIgnoreCase(ICEBERG)) {
-      SourceClientProvider<Snapshot> icebergSourceClientProvider =
-          new IcebergSourceClientProvider();
-      icebergSourceClientProvider.init(jsc.hadoopConfiguration(), Collections.emptyMap());
-      return icebergSourceClientProvider;
+      ConversionSourceProvider<Snapshot> icebergConversionSourceProvider =
+          new IcebergConversionSourceProvider();
+      icebergConversionSourceProvider.init(jsc.hadoopConfiguration(), Collections.emptyMap());
+      return icebergConversionSourceProvider;
     } else {
       throw new IllegalArgumentException("Unsupported source format: " + sourceTableFormat);
     }
@@ -177,13 +179,14 @@ public class ITOneTableClient {
   public void testVariousOperations(
       String sourceTableFormat, SyncMode syncMode, boolean isPartitioned) {
     String tableName = getTableName();
-    OneTableClient oneTableClient = new OneTableClient(jsc.hadoopConfiguration());
+    ConversionController conversionController = new ConversionController(jsc.hadoopConfiguration());
     List<String> targetTableFormats = getOtherFormats(sourceTableFormat);
     String oneTablePartitionConfig = null;
     if (isPartitioned) {
       oneTablePartitionConfig = "level:VALUE";
     }
-    SourceClientProvider<?> sourceClientProvider = getSourceClientProvider(sourceTableFormat);
+    ConversionSourceProvider<?> conversionSourceProvider =
+        getConversionSourceProvider(sourceTableFormat);
     List<?> insertRecords;
     try (GenericTable table =
         GenericTable.getInstance(
@@ -202,17 +205,17 @@ public class ITOneTableClient {
                       .build())
               .syncMode(syncMode)
               .build();
-      oneTableClient.sync(perTableConfig, sourceClientProvider);
+      conversionController.sync(perTableConfig, conversionSourceProvider);
       checkDatasetEquivalence(sourceTableFormat, table, targetTableFormats, 100);
 
       // make multiple commits and then sync
       table.insertRows(100);
       table.upsertRows(insertRecords.subList(0, 20));
-      oneTableClient.sync(perTableConfig, sourceClientProvider);
+      conversionController.sync(perTableConfig, conversionSourceProvider);
       checkDatasetEquivalence(sourceTableFormat, table, targetTableFormats, 200);
 
       table.deleteRows(insertRecords.subList(30, 50));
-      oneTableClient.sync(perTableConfig, sourceClientProvider);
+      conversionController.sync(perTableConfig, conversionSourceProvider);
       checkDatasetEquivalence(sourceTableFormat, table, targetTableFormats, 180);
       checkDatasetEquivalenceWithFilter(
           sourceTableFormat, table, targetTableFormats, table.getFilterQuery());
@@ -235,27 +238,27 @@ public class ITOneTableClient {
               .build();
       List<Row> insertsAfterSchemaUpdate = tableWithUpdatedSchema.insertRows(100);
       tableWithUpdatedSchema.reload();
-      oneTableClient.sync(perTableConfig, sourceClientProvider);
+      conversionController.sync(perTableConfig, conversionSourceProvider);
       checkDatasetEquivalence(sourceTableFormat, tableWithUpdatedSchema, targetTableFormats, 280);
 
       tableWithUpdatedSchema.deleteRows(insertsAfterSchemaUpdate.subList(60, 90));
-      oneTableClient.sync(perTableConfig, sourceClientProvider);
+      conversionController.sync(perTableConfig, conversionSourceProvider);
       checkDatasetEquivalence(sourceTableFormat, tableWithUpdatedSchema, targetTableFormats, 250);
 
       if (isPartitioned) {
         // Adds new partition.
         tableWithUpdatedSchema.insertRecordsForSpecialPartition(50);
-        oneTableClient.sync(perTableConfig, sourceClientProvider);
+        conversionController.sync(perTableConfig, conversionSourceProvider);
         checkDatasetEquivalence(sourceTableFormat, tableWithUpdatedSchema, targetTableFormats, 300);
 
         // Drops partition.
         tableWithUpdatedSchema.deleteSpecialPartition();
-        oneTableClient.sync(perTableConfig, sourceClientProvider);
+        conversionController.sync(perTableConfig, conversionSourceProvider);
         checkDatasetEquivalence(sourceTableFormat, tableWithUpdatedSchema, targetTableFormats, 250);
 
         // Insert records to the dropped partition again.
         tableWithUpdatedSchema.insertRecordsForSpecialPartition(50);
-        oneTableClient.sync(perTableConfig, sourceClientProvider);
+        conversionController.sync(perTableConfig, conversionSourceProvider);
         checkDatasetEquivalence(sourceTableFormat, tableWithUpdatedSchema, targetTableFormats, 300);
       }
     }
@@ -266,7 +269,7 @@ public class ITOneTableClient {
   public void testConcurrentInsertWritesInSource(
       SyncMode syncMode, PartitionConfig partitionConfig) {
     String tableName = getTableName();
-    SourceClientProvider<?> sourceClientProvider = getSourceClientProvider(HUDI);
+    ConversionSourceProvider<?> conversionSourceProvider = getConversionSourceProvider(HUDI);
     List<String> targetTableFormats = getOtherFormats(HUDI);
     try (TestJavaHudiTable table =
         TestJavaHudiTable.forStandardSchema(
@@ -291,12 +294,13 @@ public class ITOneTableClient {
                       .build())
               .syncMode(syncMode)
               .build();
-      OneTableClient oneTableClient = new OneTableClient(jsc.hadoopConfiguration());
-      oneTableClient.sync(perTableConfig, sourceClientProvider);
+      ConversionController conversionController =
+          new ConversionController(jsc.hadoopConfiguration());
+      conversionController.sync(perTableConfig, conversionSourceProvider);
 
       checkDatasetEquivalence(HUDI, table, targetTableFormats, 50);
       table.insertRecordsWithCommitAlreadyStarted(insertsForCommit1, commitInstant1, true);
-      oneTableClient.sync(perTableConfig, sourceClientProvider);
+      conversionController.sync(perTableConfig, conversionSourceProvider);
       checkDatasetEquivalence(HUDI, table, targetTableFormats, 100);
     }
   }
@@ -306,7 +310,7 @@ public class ITOneTableClient {
   public void testConcurrentInsertsAndTableServiceWrites(
       SyncMode syncMode, PartitionConfig partitionConfig) {
     HoodieTableType tableType = HoodieTableType.MERGE_ON_READ;
-    SourceClientProvider<?> sourceClientProvider = getSourceClientProvider(HUDI);
+    ConversionSourceProvider<?> conversionSourceProvider = getConversionSourceProvider(HUDI);
     List<String> targetTableFormats = getOtherFormats(HUDI);
     String tableName = getTableName();
     try (TestSparkHudiTable table =
@@ -325,8 +329,9 @@ public class ITOneTableClient {
                       .build())
               .syncMode(syncMode)
               .build();
-      OneTableClient oneTableClient = new OneTableClient(jsc.hadoopConfiguration());
-      oneTableClient.sync(perTableConfig, sourceClientProvider);
+      ConversionController conversionController =
+          new ConversionController(jsc.hadoopConfiguration());
+      conversionController.sync(perTableConfig, conversionSourceProvider);
       checkDatasetEquivalence(HUDI, table, targetTableFormats, 50);
 
       table.deleteRecords(insertedRecords1.subList(0, 20), true);
@@ -334,7 +339,7 @@ public class ITOneTableClient {
       String scheduledCompactionInstant = table.onlyScheduleCompaction();
 
       table.insertRecords(50, true);
-      oneTableClient.sync(perTableConfig, sourceClientProvider);
+      conversionController.sync(perTableConfig, conversionSourceProvider);
       Map<String, String> sourceHudiOptions =
           Collections.singletonMap("hoodie.datasource.query.type", "read_optimized");
       // Because compaction is not completed yet and read optimized query, there are 100 records.
@@ -342,13 +347,13 @@ public class ITOneTableClient {
           HUDI, table, sourceHudiOptions, targetTableFormats, Collections.emptyMap(), 100);
 
       table.insertRecords(50, true);
-      oneTableClient.sync(perTableConfig, sourceClientProvider);
+      conversionController.sync(perTableConfig, conversionSourceProvider);
       // Because compaction is not completed yet and read optimized query, there are 150 records.
       checkDatasetEquivalence(
           HUDI, table, sourceHudiOptions, targetTableFormats, Collections.emptyMap(), 150);
 
       table.completeScheduledCompaction(scheduledCompactionInstant);
-      oneTableClient.sync(perTableConfig, sourceClientProvider);
+      conversionController.sync(perTableConfig, conversionSourceProvider);
       checkDatasetEquivalence(HUDI, table, targetTableFormats, 130);
     }
   }
@@ -369,21 +374,23 @@ public class ITOneTableClient {
               .tableDataPath(table.getDataPath())
               .syncMode(SyncMode.INCREMENTAL)
               .build();
-      SourceClientProvider<?> sourceClientProvider = getSourceClientProvider(sourceTableFormat);
-      OneTableClient oneTableClient = new OneTableClient(jsc.hadoopConfiguration());
-      oneTableClient.sync(perTableConfig, sourceClientProvider);
+      ConversionSourceProvider<?> conversionSourceProvider =
+          getConversionSourceProvider(sourceTableFormat);
+      ConversionController conversionController =
+          new ConversionController(jsc.hadoopConfiguration());
+      conversionController.sync(perTableConfig, conversionSourceProvider);
       Instant instantAfterFirstSync = Instant.now();
       // sleep before starting the next commit to avoid any rounding issues
       Thread.sleep(1000);
 
       table.insertRows(50);
-      oneTableClient.sync(perTableConfig, sourceClientProvider);
+      conversionController.sync(perTableConfig, conversionSourceProvider);
       Instant instantAfterSecondSync = Instant.now();
       // sleep before starting the next commit to avoid any rounding issues
       Thread.sleep(1000);
 
       table.insertRows(50);
-      oneTableClient.sync(perTableConfig, sourceClientProvider);
+      conversionController.sync(perTableConfig, conversionSourceProvider);
 
       checkDatasetEquivalence(
           sourceTableFormat,
@@ -470,7 +477,8 @@ public class ITOneTableClient {
     Optional<String> hudiPartitionConfig = tableFormatPartitionDataHolder.getHudiSourceConfig();
     String oneTablePartitionConfig = tableFormatPartitionDataHolder.getOneTablePartitionConfig();
     String filter = tableFormatPartitionDataHolder.getFilter();
-    SourceClientProvider<?> sourceClientProvider = getSourceClientProvider(sourceTableFormat);
+    ConversionSourceProvider<?> conversionSourceProvider =
+        getConversionSourceProvider(sourceTableFormat);
     GenericTable table;
     if (hudiPartitionConfig.isPresent()) {
       table =
@@ -494,11 +502,12 @@ public class ITOneTableClient {
               .syncMode(SyncMode.INCREMENTAL)
               .build();
       tableToClose.insertRows(100);
-      OneTableClient oneTableClient = new OneTableClient(jsc.hadoopConfiguration());
-      oneTableClient.sync(perTableConfig, sourceClientProvider);
+      ConversionController conversionController =
+          new ConversionController(jsc.hadoopConfiguration());
+      conversionController.sync(perTableConfig, conversionSourceProvider);
       // Do a second sync to force the test to read back the metadata it wrote earlier
       tableToClose.insertRows(100);
-      oneTableClient.sync(perTableConfig, sourceClientProvider);
+      conversionController.sync(perTableConfig, conversionSourceProvider);
 
       checkDatasetEquivalenceWithFilter(
           sourceTableFormat, tableToClose, targetTableFormats, filter);
@@ -509,7 +518,7 @@ public class ITOneTableClient {
   @EnumSource(value = SyncMode.class)
   public void testSyncWithSingleFormat(SyncMode syncMode) {
     String tableName = getTableName();
-    SourceClientProvider<?> sourceClientProvider = getSourceClientProvider(HUDI);
+    ConversionSourceProvider<?> conversionSourceProvider = getConversionSourceProvider(HUDI);
     try (TestJavaHudiTable table =
         TestJavaHudiTable.forStandardSchema(
             tableName, tempDir, null, HoodieTableType.COPY_ON_WRITE)) {
@@ -531,16 +540,17 @@ public class ITOneTableClient {
               .syncMode(syncMode)
               .build();
 
-      OneTableClient oneTableClient = new OneTableClient(jsc.hadoopConfiguration());
-      oneTableClient.sync(perTableConfigIceberg, sourceClientProvider);
+      ConversionController conversionController =
+          new ConversionController(jsc.hadoopConfiguration());
+      conversionController.sync(perTableConfigIceberg, conversionSourceProvider);
       checkDatasetEquivalence(HUDI, table, Collections.singletonList(ICEBERG), 100);
-      oneTableClient.sync(perTableConfigDelta, sourceClientProvider);
+      conversionController.sync(perTableConfigDelta, conversionSourceProvider);
       checkDatasetEquivalence(HUDI, table, Collections.singletonList(DELTA), 100);
 
       table.insertRecords(100, true);
-      oneTableClient.sync(perTableConfigIceberg, sourceClientProvider);
+      conversionController.sync(perTableConfigIceberg, conversionSourceProvider);
       checkDatasetEquivalence(HUDI, table, Collections.singletonList(ICEBERG), 200);
-      oneTableClient.sync(perTableConfigDelta, sourceClientProvider);
+      conversionController.sync(perTableConfigDelta, conversionSourceProvider);
       checkDatasetEquivalence(HUDI, table, Collections.singletonList(DELTA), 200);
     }
   }
@@ -548,7 +558,7 @@ public class ITOneTableClient {
   @Test
   public void testOutOfSyncIncrementalSyncs() {
     String tableName = getTableName();
-    SourceClientProvider<?> sourceClientProvider = getSourceClientProvider(HUDI);
+    ConversionSourceProvider<?> conversionSourceProvider = getConversionSourceProvider(HUDI);
     try (TestJavaHudiTable table =
         TestJavaHudiTable.forStandardSchema(
             tableName, tempDir, null, HoodieTableType.COPY_ON_WRITE)) {
@@ -569,14 +579,15 @@ public class ITOneTableClient {
               .build();
 
       table.insertRecords(50, true);
-      OneTableClient oneTableClient = new OneTableClient(jsc.hadoopConfiguration());
+      ConversionController conversionController =
+          new ConversionController(jsc.hadoopConfiguration());
       // sync iceberg only
-      oneTableClient.sync(singleTableConfig, sourceClientProvider);
+      conversionController.sync(singleTableConfig, conversionSourceProvider);
       checkDatasetEquivalence(HUDI, table, Collections.singletonList(ICEBERG), 50);
       // insert more records
       table.insertRecords(50, true);
       // iceberg will be an incremental sync and delta will need to bootstrap with snapshot sync
-      oneTableClient.sync(dualTableConfig, sourceClientProvider);
+      conversionController.sync(dualTableConfig, conversionSourceProvider);
       checkDatasetEquivalence(HUDI, table, Arrays.asList(ICEBERG, DELTA), 100);
 
       // insert more records
@@ -584,13 +595,13 @@ public class ITOneTableClient {
       // insert more records
       table.insertRecords(50, true);
       // incremental sync for two commits for iceberg only
-      oneTableClient.sync(singleTableConfig, sourceClientProvider);
+      conversionController.sync(singleTableConfig, conversionSourceProvider);
       checkDatasetEquivalence(HUDI, table, Collections.singletonList(ICEBERG), 200);
 
       // insert more records
       table.insertRecords(50, true);
       // incremental sync for one commit for iceberg and three commits for delta
-      oneTableClient.sync(dualTableConfig, sourceClientProvider);
+      conversionController.sync(dualTableConfig, conversionSourceProvider);
       checkDatasetEquivalence(HUDI, table, Arrays.asList(ICEBERG, DELTA), 250);
     }
   }
@@ -598,12 +609,13 @@ public class ITOneTableClient {
   @Test
   public void testIcebergCorruptedSnapshotRecovery() throws Exception {
     String tableName = getTableName();
-    SourceClientProvider<?> sourceClientProvider = getSourceClientProvider(HUDI);
+    ConversionSourceProvider<?> conversionSourceProvider = getConversionSourceProvider(HUDI);
     try (TestJavaHudiTable table =
         TestJavaHudiTable.forStandardSchema(
             tableName, tempDir, null, HoodieTableType.COPY_ON_WRITE)) {
       table.insertRows(20);
-      OneTableClient oneTableClient = new OneTableClient(jsc.hadoopConfiguration());
+      ConversionController conversionController =
+          new ConversionController(jsc.hadoopConfiguration());
       PerTableConfig perTableConfig =
           PerTableConfigImpl.builder()
               .tableName(tableName)
@@ -611,11 +623,11 @@ public class ITOneTableClient {
               .tableBasePath(table.getBasePath())
               .syncMode(SyncMode.INCREMENTAL)
               .build();
-      oneTableClient.sync(perTableConfig, sourceClientProvider);
+      conversionController.sync(perTableConfig, conversionSourceProvider);
       table.insertRows(10);
-      oneTableClient.sync(perTableConfig, sourceClientProvider);
+      conversionController.sync(perTableConfig, conversionSourceProvider);
       table.insertRows(10);
-      oneTableClient.sync(perTableConfig, sourceClientProvider);
+      conversionController.sync(perTableConfig, conversionSourceProvider);
       // corrupt last two snapshots
       Table icebergTable = new HadoopTables(jsc.hadoopConfiguration()).load(table.getBasePath());
       long currentSnapshotId = icebergTable.currentSnapshot().snapshotId();
@@ -625,7 +637,7 @@ public class ITOneTableClient {
       Files.delete(
           Paths.get(URI.create(icebergTable.snapshot(previousSnapshotId).manifestListLocation())));
       table.insertRows(10);
-      oneTableClient.sync(perTableConfig, sourceClientProvider);
+      conversionController.sync(perTableConfig, conversionSourceProvider);
       checkDatasetEquivalence(HUDI, table, Collections.singletonList(ICEBERG), 50);
     }
   }
@@ -633,7 +645,7 @@ public class ITOneTableClient {
   @Test
   public void testMetadataRetention() throws Exception {
     String tableName = getTableName();
-    SourceClientProvider<?> sourceClientProvider = getSourceClientProvider(HUDI);
+    ConversionSourceProvider<?> conversionSourceProvider = getConversionSourceProvider(HUDI);
     try (TestJavaHudiTable table =
         TestJavaHudiTable.forStandardSchema(
             tableName, tempDir, null, HoodieTableType.COPY_ON_WRITE)) {
@@ -645,9 +657,10 @@ public class ITOneTableClient {
               .syncMode(SyncMode.INCREMENTAL)
               .targetMetadataRetentionInHours(0) // force cleanup
               .build();
-      OneTableClient oneTableClient = new OneTableClient(jsc.hadoopConfiguration());
+      ConversionController conversionController =
+          new ConversionController(jsc.hadoopConfiguration());
       table.insertRecords(10, true);
-      oneTableClient.sync(perTableConfig, sourceClientProvider);
+      conversionController.sync(perTableConfig, conversionSourceProvider);
       // later we will ensure we can still read the source table at this instant to ensure that
       // neither target cleaned up the underlying parquet files in the table
       Instant instantAfterFirstCommit = Instant.now();
@@ -658,7 +671,7 @@ public class ITOneTableClient {
           .forEach(
               unused -> {
                 table.insertRecords(10, true);
-                oneTableClient.sync(perTableConfig, sourceClientProvider);
+                conversionController.sync(perTableConfig, conversionSourceProvider);
               });
       // ensure that hudi rows can still be read and underlying files were not removed
       List<Row> rows =
diff --git a/core/src/test/java/org/apache/xtable/client/TestOneTableClient.java b/core/src/test/java/org/apache/xtable/conversion/TestConversionController.java
similarity index 67%
rename from core/src/test/java/org/apache/xtable/client/TestOneTableClient.java
rename to core/src/test/java/org/apache/xtable/conversion/TestConversionController.java
index 263013c7..c30d0878 100644
--- a/core/src/test/java/org/apache/xtable/client/TestOneTableClient.java
+++ b/core/src/test/java/org/apache/xtable/conversion/TestConversionController.java
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
  
-package org.apache.xtable.client;
+package org.apache.xtable.conversion;
 
 import static org.apache.xtable.GenericTable.getTableName;
 import static org.junit.jupiter.api.Assertions.*;
@@ -53,21 +53,21 @@ import org.apache.xtable.model.TableSyncMetadata;
 import org.apache.xtable.model.storage.TableFormat;
 import org.apache.xtable.model.sync.SyncMode;
 import org.apache.xtable.model.sync.SyncResult;
-import org.apache.xtable.spi.extractor.SourceClient;
+import org.apache.xtable.spi.extractor.ConversionSource;
+import org.apache.xtable.spi.sync.ConversionTarget;
 import org.apache.xtable.spi.sync.TableFormatSync;
-import org.apache.xtable.spi.sync.TargetClient;
 
-public class TestOneTableClient {
+public class TestConversionController {
 
   private final Configuration mockConf = mock(Configuration.class);
-  private final SourceClientProvider<Instant> mockSourceClientProvider =
-      mock(SourceClientProvider.class);
-  private final SourceClient<Instant> mockSourceClient = mock(SourceClient.class);
-  private final TableFormatClientFactory mockTableFormatClientFactory =
-      mock(TableFormatClientFactory.class);
+  private final ConversionSourceProvider<Instant> mockConversionSourceProvider =
+      mock(ConversionSourceProvider.class);
+  private final ConversionSource<Instant> mockConversionSource = mock(ConversionSource.class);
+  private final ConversionTargetFactory mockConversionTargetFactory =
+      mock(ConversionTargetFactory.class);
   private final TableFormatSync tableFormatSync = mock(TableFormatSync.class);
-  private final TargetClient mockTargetClient1 = mock(TargetClient.class);
-  private final TargetClient mockTargetClient2 = mock(TargetClient.class);
+  private final ConversionTarget mockConversionTarget1 = mock(ConversionTarget.class);
+  private final ConversionTarget mockConversionTarget2 = mock(ConversionTarget.class);
 
   @Test
   void testAllSnapshotSyncAsPerConfig() {
@@ -81,21 +81,21 @@ public class TestOneTableClient {
     perTableResults.put(TableFormat.DELTA, syncResult);
     PerTableConfig perTableConfig =
         getPerTableConfig(Arrays.asList(TableFormat.ICEBERG, TableFormat.DELTA), syncMode);
-    when(mockSourceClientProvider.getSourceClientInstance(perTableConfig))
-        .thenReturn(mockSourceClient);
-    when(mockTableFormatClientFactory.createForFormat(
-            TableFormat.ICEBERG, perTableConfig, mockConf))
-        .thenReturn(mockTargetClient1);
-    when(mockTableFormatClientFactory.createForFormat(TableFormat.DELTA, perTableConfig, mockConf))
-        .thenReturn(mockTargetClient2);
-    when(mockSourceClient.getCurrentSnapshot()).thenReturn(internalSnapshot);
+    when(mockConversionSourceProvider.getConversionSourceInstance(perTableConfig))
+        .thenReturn(mockConversionSource);
+    when(mockConversionTargetFactory.createForFormat(TableFormat.ICEBERG, perTableConfig, mockConf))
+        .thenReturn(mockConversionTarget1);
+    when(mockConversionTargetFactory.createForFormat(TableFormat.DELTA, perTableConfig, mockConf))
+        .thenReturn(mockConversionTarget2);
+    when(mockConversionSource.getCurrentSnapshot()).thenReturn(internalSnapshot);
     when(tableFormatSync.syncSnapshot(
-            argThat(containsAll(Arrays.asList(mockTargetClient1, mockTargetClient2))),
+            argThat(containsAll(Arrays.asList(mockConversionTarget1, mockConversionTarget2))),
             eq(internalSnapshot)))
         .thenReturn(perTableResults);
-    OneTableClient oneTableClient =
-        new OneTableClient(mockConf, mockTableFormatClientFactory, tableFormatSync);
-    Map<String, SyncResult> result = oneTableClient.sync(perTableConfig, mockSourceClientProvider);
+    ConversionController conversionController =
+        new ConversionController(mockConf, mockConversionTargetFactory, tableFormatSync);
+    Map<String, SyncResult> result =
+        conversionController.sync(perTableConfig, mockConversionSourceProvider);
     assertEquals(perTableResults, result);
   }
 
@@ -104,13 +104,12 @@ public class TestOneTableClient {
     SyncMode syncMode = SyncMode.INCREMENTAL;
     PerTableConfig perTableConfig =
         getPerTableConfig(Arrays.asList(TableFormat.ICEBERG, TableFormat.DELTA), syncMode);
-    when(mockSourceClientProvider.getSourceClientInstance(perTableConfig))
-        .thenReturn(mockSourceClient);
-    when(mockTableFormatClientFactory.createForFormat(
-            TableFormat.ICEBERG, perTableConfig, mockConf))
-        .thenReturn(mockTargetClient1);
-    when(mockTableFormatClientFactory.createForFormat(TableFormat.DELTA, perTableConfig, mockConf))
-        .thenReturn(mockTargetClient2);
+    when(mockConversionSourceProvider.getConversionSourceInstance(perTableConfig))
+        .thenReturn(mockConversionSource);
+    when(mockConversionTargetFactory.createForFormat(TableFormat.ICEBERG, perTableConfig, mockConf))
+        .thenReturn(mockConversionTarget1);
+    when(mockConversionTargetFactory.createForFormat(TableFormat.DELTA, perTableConfig, mockConf))
+        .thenReturn(mockConversionTarget2);
 
     Instant instantAsOfNow = Instant.now();
     Instant instantAt15 = getInstantAtLastNMinutes(instantAsOfNow, 15);
@@ -119,8 +118,8 @@ public class TestOneTableClient {
     Instant instantAt8 = getInstantAtLastNMinutes(instantAsOfNow, 8);
     Instant instantAt5 = getInstantAtLastNMinutes(instantAsOfNow, 5);
     Instant instantAt2 = getInstantAtLastNMinutes(instantAsOfNow, 2);
-    when(mockSourceClient.isIncrementalSyncSafeFrom(eq(instantAt15))).thenReturn(true);
-    when(mockSourceClient.isIncrementalSyncSafeFrom(eq(instantAt8))).thenReturn(true);
+    when(mockConversionSource.isIncrementalSyncSafeFrom(eq(instantAt15))).thenReturn(true);
+    when(mockConversionSource.isIncrementalSyncSafeFrom(eq(instantAt8))).thenReturn(true);
 
     // Iceberg last synced at instantAt10 and has pending instants at instantAt15.
     Instant icebergLastSyncInstant = instantAt10;
@@ -140,18 +139,19 @@ public class TestOneTableClient {
         Arrays.asList(instantAt15, instantAt14, instantAt10, instantAt8, instantAt5, instantAt2);
     CommitsBacklog<Instant> commitsBacklog =
         CommitsBacklog.<Instant>builder().commitsToProcess(instantsToProcess).build();
-    Optional<TableSyncMetadata> targetClient1Metadata =
+    Optional<TableSyncMetadata> conversionTarget1Metadata =
         Optional.of(TableSyncMetadata.of(icebergLastSyncInstant, pendingInstantsForIceberg));
-    when(mockTargetClient1.getTableMetadata()).thenReturn(targetClient1Metadata);
-    Optional<TableSyncMetadata> targetClient2Metadata =
+    when(mockConversionTarget1.getTableMetadata()).thenReturn(conversionTarget1Metadata);
+    Optional<TableSyncMetadata> conversionTarget2Metadata =
         Optional.of(TableSyncMetadata.of(deltaLastSyncInstant, pendingInstantsForDelta));
-    when(mockTargetClient2.getTableMetadata()).thenReturn(targetClient2Metadata);
-    when(mockSourceClient.getCommitsBacklog(instantsForIncrementalSync)).thenReturn(commitsBacklog);
+    when(mockConversionTarget2.getTableMetadata()).thenReturn(conversionTarget2Metadata);
+    when(mockConversionSource.getCommitsBacklog(instantsForIncrementalSync))
+        .thenReturn(commitsBacklog);
     List<TableChange> tableChanges = new ArrayList<>();
     for (Instant instant : instantsToProcess) {
       TableChange tableChange = getTableChange(instant);
       tableChanges.add(tableChange);
-      when(mockSourceClient.getTableChangeForCommit(instant)).thenReturn(tableChange);
+      when(mockConversionSource.getTableChangeForCommit(instant)).thenReturn(tableChange);
     }
     // Iceberg needs to sync last pending instant at instantAt15 and instants after last sync
     // instant
@@ -166,18 +166,19 @@ public class TestOneTableClient {
     Map<String, List<SyncResult>> allResults = new HashMap<>();
     allResults.put(TableFormat.ICEBERG, icebergSyncResults);
     allResults.put(TableFormat.DELTA, deltaSyncResults);
-    Map<TargetClient, TableSyncMetadata> clientToMetadata = new HashMap<>();
-    clientToMetadata.put(mockTargetClient1, targetClient1Metadata.get());
-    clientToMetadata.put(mockTargetClient2, targetClient2Metadata.get());
+    Map<ConversionTarget, TableSyncMetadata> conversionTargetToMetadata = new HashMap<>();
+    conversionTargetToMetadata.put(mockConversionTarget1, conversionTarget1Metadata.get());
+    conversionTargetToMetadata.put(mockConversionTarget2, conversionTarget2Metadata.get());
     when(tableFormatSync.syncChanges(
-            eq(clientToMetadata), argThat(matches(incrementalTableChanges))))
+            eq(conversionTargetToMetadata), argThat(matches(incrementalTableChanges))))
         .thenReturn(allResults);
     Map<String, SyncResult> expectedSyncResult = new HashMap<>();
     expectedSyncResult.put(TableFormat.ICEBERG, getLastSyncResult(icebergSyncResults));
     expectedSyncResult.put(TableFormat.DELTA, getLastSyncResult(deltaSyncResults));
-    OneTableClient oneTableClient =
-        new OneTableClient(mockConf, mockTableFormatClientFactory, tableFormatSync);
-    Map<String, SyncResult> result = oneTableClient.sync(perTableConfig, mockSourceClientProvider);
+    ConversionController conversionController =
+        new ConversionController(mockConf, mockConversionTargetFactory, tableFormatSync);
+    Map<String, SyncResult> result =
+        conversionController.sync(perTableConfig, mockConversionSourceProvider);
     assertEquals(expectedSyncResult, result);
   }
 
@@ -193,32 +194,32 @@ public class TestOneTableClient {
     syncResults.put(TableFormat.DELTA, syncResult);
     PerTableConfig perTableConfig =
         getPerTableConfig(Arrays.asList(TableFormat.ICEBERG, TableFormat.DELTA), syncMode);
-    when(mockSourceClientProvider.getSourceClientInstance(perTableConfig))
-        .thenReturn(mockSourceClient);
-    when(mockTableFormatClientFactory.createForFormat(
-            TableFormat.ICEBERG, perTableConfig, mockConf))
-        .thenReturn(mockTargetClient1);
-    when(mockTableFormatClientFactory.createForFormat(TableFormat.DELTA, perTableConfig, mockConf))
-        .thenReturn(mockTargetClient2);
+    when(mockConversionSourceProvider.getConversionSourceInstance(perTableConfig))
+        .thenReturn(mockConversionSource);
+    when(mockConversionTargetFactory.createForFormat(TableFormat.ICEBERG, perTableConfig, mockConf))
+        .thenReturn(mockConversionTarget1);
+    when(mockConversionTargetFactory.createForFormat(TableFormat.DELTA, perTableConfig, mockConf))
+        .thenReturn(mockConversionTarget2);
 
     Instant instantAsOfNow = Instant.now();
     Instant instantAt5 = getInstantAtLastNMinutes(instantAsOfNow, 5);
-    when(mockSourceClient.isIncrementalSyncSafeFrom(eq(instantAt5))).thenReturn(false);
+    when(mockConversionSource.isIncrementalSyncSafeFrom(eq(instantAt5))).thenReturn(false);
 
     // Both Iceberg and Delta last synced at instantAt5 and have no pending instants.
-    when(mockTargetClient1.getTableMetadata())
+    when(mockConversionTarget1.getTableMetadata())
         .thenReturn(Optional.of(TableSyncMetadata.of(instantAt5, Collections.emptyList())));
-    when(mockTargetClient2.getTableMetadata())
+    when(mockConversionTarget2.getTableMetadata())
         .thenReturn(Optional.of(TableSyncMetadata.of(instantAt5, Collections.emptyList())));
 
-    when(mockSourceClient.getCurrentSnapshot()).thenReturn(internalSnapshot);
+    when(mockConversionSource.getCurrentSnapshot()).thenReturn(internalSnapshot);
     when(tableFormatSync.syncSnapshot(
-            argThat(containsAll(Arrays.asList(mockTargetClient1, mockTargetClient2))),
+            argThat(containsAll(Arrays.asList(mockConversionTarget1, mockConversionTarget2))),
             eq(internalSnapshot)))
         .thenReturn(syncResults);
-    OneTableClient oneTableClient =
-        new OneTableClient(mockConf, mockTableFormatClientFactory, tableFormatSync);
-    Map<String, SyncResult> result = oneTableClient.sync(perTableConfig, mockSourceClientProvider);
+    ConversionController conversionController =
+        new ConversionController(mockConf, mockConversionTargetFactory, tableFormatSync);
+    Map<String, SyncResult> result =
+        conversionController.sync(perTableConfig, mockConversionSourceProvider);
     assertEquals(syncResults, result);
   }
 
@@ -227,13 +228,12 @@ public class TestOneTableClient {
     SyncMode syncMode = SyncMode.INCREMENTAL;
     PerTableConfig perTableConfig =
         getPerTableConfig(Arrays.asList(TableFormat.ICEBERG, TableFormat.DELTA), syncMode);
-    when(mockSourceClientProvider.getSourceClientInstance(perTableConfig))
-        .thenReturn(mockSourceClient);
-    when(mockTableFormatClientFactory.createForFormat(
-            TableFormat.ICEBERG, perTableConfig, mockConf))
-        .thenReturn(mockTargetClient1);
-    when(mockTableFormatClientFactory.createForFormat(TableFormat.DELTA, perTableConfig, mockConf))
-        .thenReturn(mockTargetClient2);
+    when(mockConversionSourceProvider.getConversionSourceInstance(perTableConfig))
+        .thenReturn(mockConversionSource);
+    when(mockConversionTargetFactory.createForFormat(TableFormat.ICEBERG, perTableConfig, mockConf))
+        .thenReturn(mockConversionTarget1);
+    when(mockConversionTargetFactory.createForFormat(TableFormat.DELTA, perTableConfig, mockConf))
+        .thenReturn(mockConversionTarget2);
 
     Instant instantAsOfNow = Instant.now();
     Instant instantAt15 = getInstantAtLastNMinutes(instantAsOfNow, 15);
@@ -242,8 +242,8 @@ public class TestOneTableClient {
     Instant instantAt5 = getInstantAtLastNMinutes(instantAsOfNow, 5);
     Instant instantAt2 = getInstantAtLastNMinutes(instantAsOfNow, 2);
 
-    when(mockSourceClient.isIncrementalSyncSafeFrom(eq(instantAt8))).thenReturn(true);
-    when(mockSourceClient.isIncrementalSyncSafeFrom(eq(instantAt15))).thenReturn(false);
+    when(mockConversionSource.isIncrementalSyncSafeFrom(eq(instantAt8))).thenReturn(true);
+    when(mockConversionSource.isIncrementalSyncSafeFrom(eq(instantAt15))).thenReturn(false);
 
     // Iceberg last synced at instantAt10 and has pending instants at instantAt15.
     Instant icebergLastSyncInstant = instantAt10;
@@ -259,18 +259,19 @@ public class TestOneTableClient {
     List<Instant> instantsToProcess = Arrays.asList(instantAt8, instantAt2);
     CommitsBacklog<Instant> commitsBacklog =
         CommitsBacklog.<Instant>builder().commitsToProcess(instantsToProcess).build();
-    when(mockTargetClient1.getTableMetadata())
+    when(mockConversionTarget1.getTableMetadata())
         .thenReturn(
             Optional.of(TableSyncMetadata.of(icebergLastSyncInstant, pendingInstantsForIceberg)));
-    Optional<TableSyncMetadata> targetClient2Metadata =
+    Optional<TableSyncMetadata> conversionTarget2Metadata =
         Optional.of(TableSyncMetadata.of(deltaLastSyncInstant, pendingInstantsForDelta));
-    when(mockTargetClient2.getTableMetadata()).thenReturn(targetClient2Metadata);
-    when(mockSourceClient.getCommitsBacklog(instantsForIncrementalSync)).thenReturn(commitsBacklog);
+    when(mockConversionTarget2.getTableMetadata()).thenReturn(conversionTarget2Metadata);
+    when(mockConversionSource.getCommitsBacklog(instantsForIncrementalSync))
+        .thenReturn(commitsBacklog);
     List<TableChange> tableChanges = new ArrayList<>();
     for (Instant instant : instantsToProcess) {
       TableChange tableChange = getTableChange(instant);
       tableChanges.add(tableChange);
-      when(mockSourceClient.getTableChangeForCommit(instant)).thenReturn(tableChange);
+      when(mockConversionSource.getTableChangeForCommit(instant)).thenReturn(tableChange);
     }
     // Iceberg needs to sync by snapshot since instant15 is affected by table clean-up.
     InternalTable internalTable = getOneTable();
@@ -279,9 +280,9 @@ public class TestOneTableClient {
     SyncResult syncResult = buildSyncResult(syncMode, instantBeforeHour);
     Map<String, SyncResult> snapshotResult =
         Collections.singletonMap(TableFormat.ICEBERG, syncResult);
-    when(mockSourceClient.getCurrentSnapshot()).thenReturn(internalSnapshot);
+    when(mockConversionSource.getCurrentSnapshot()).thenReturn(internalSnapshot);
     when(tableFormatSync.syncSnapshot(
-            argThat(containsAll(Collections.singletonList(mockTargetClient1))),
+            argThat(containsAll(Collections.singletonList(mockConversionTarget1))),
             eq(internalSnapshot)))
         .thenReturn(snapshotResult);
     // Delta needs to sync last pending instant at instantAt8 and instants after last sync instant
@@ -290,15 +291,16 @@ public class TestOneTableClient {
     IncrementalTableChanges incrementalTableChanges =
         IncrementalTableChanges.builder().tableChanges(tableChanges.iterator()).build();
     when(tableFormatSync.syncChanges(
-            eq(Collections.singletonMap(mockTargetClient2, targetClient2Metadata.get())),
+            eq(Collections.singletonMap(mockConversionTarget2, conversionTarget2Metadata.get())),
             argThat(matches(incrementalTableChanges))))
         .thenReturn(Collections.singletonMap(TableFormat.DELTA, deltaSyncResults));
     Map<String, SyncResult> expectedSyncResult = new HashMap<>();
     expectedSyncResult.put(TableFormat.ICEBERG, syncResult);
     expectedSyncResult.put(TableFormat.DELTA, getLastSyncResult(deltaSyncResults));
-    OneTableClient oneTableClient =
-        new OneTableClient(mockConf, mockTableFormatClientFactory, tableFormatSync);
-    Map<String, SyncResult> result = oneTableClient.sync(perTableConfig, mockSourceClientProvider);
+    ConversionController conversionController =
+        new ConversionController(mockConf, mockConversionTargetFactory, tableFormatSync);
+    Map<String, SyncResult> result =
+        conversionController.sync(perTableConfig, mockConversionSourceProvider);
     assertEquals(expectedSyncResult, result);
   }
 
@@ -307,19 +309,18 @@ public class TestOneTableClient {
     SyncMode syncMode = SyncMode.INCREMENTAL;
     PerTableConfig perTableConfig =
         getPerTableConfig(Arrays.asList(TableFormat.ICEBERG, TableFormat.DELTA), syncMode);
-    when(mockSourceClientProvider.getSourceClientInstance(perTableConfig))
-        .thenReturn(mockSourceClient);
-    when(mockTableFormatClientFactory.createForFormat(
-            TableFormat.ICEBERG, perTableConfig, mockConf))
-        .thenReturn(mockTargetClient1);
-    when(mockTableFormatClientFactory.createForFormat(TableFormat.DELTA, perTableConfig, mockConf))
-        .thenReturn(mockTargetClient2);
+    when(mockConversionSourceProvider.getConversionSourceInstance(perTableConfig))
+        .thenReturn(mockConversionSource);
+    when(mockConversionTargetFactory.createForFormat(TableFormat.ICEBERG, perTableConfig, mockConf))
+        .thenReturn(mockConversionTarget1);
+    when(mockConversionTargetFactory.createForFormat(TableFormat.DELTA, perTableConfig, mockConf))
+        .thenReturn(mockConversionTarget2);
 
     Instant instantAsOfNow = Instant.now();
     Instant instantAt5 = getInstantAtLastNMinutes(instantAsOfNow, 5);
 
-    when(mockSourceClient.isIncrementalSyncSafeFrom(eq(instantAt5))).thenReturn(true);
-    when(mockSourceClient.isIncrementalSyncSafeFrom(eq(instantAt5))).thenReturn(true);
+    when(mockConversionSource.isIncrementalSyncSafeFrom(eq(instantAt5))).thenReturn(true);
+    when(mockConversionSource.isIncrementalSyncSafeFrom(eq(instantAt5))).thenReturn(true);
 
     // Iceberg last synced at instantAt5, the last instant in the source
     Instant icebergLastSyncInstant = instantAt5;
@@ -330,18 +331,19 @@ public class TestOneTableClient {
     List<Instant> instantsToProcess = Collections.emptyList();
     CommitsBacklog<Instant> commitsBacklog =
         CommitsBacklog.<Instant>builder().commitsToProcess(instantsToProcess).build();
-    Optional<TableSyncMetadata> targetClient1Metadata =
+    Optional<TableSyncMetadata> conversionTarget1Metadata =
         Optional.of(TableSyncMetadata.of(icebergLastSyncInstant, Collections.emptyList()));
-    when(mockTargetClient1.getTableMetadata()).thenReturn(targetClient1Metadata);
-    Optional<TableSyncMetadata> targetClient2Metadata =
+    when(mockConversionTarget1.getTableMetadata()).thenReturn(conversionTarget1Metadata);
+    Optional<TableSyncMetadata> conversionTarget2Metadata =
         Optional.of(TableSyncMetadata.of(deltaLastSyncInstant, Collections.emptyList()));
-    when(mockTargetClient2.getTableMetadata()).thenReturn(targetClient2Metadata);
-    when(mockSourceClient.getCommitsBacklog(instantsForIncrementalSync)).thenReturn(commitsBacklog);
-    Map<TargetClient, TableSyncMetadata> clientsWithMetadata = new HashMap<>();
-    clientsWithMetadata.put(mockTargetClient1, targetClient1Metadata.get());
-    clientsWithMetadata.put(mockTargetClient2, targetClient2Metadata.get());
+    when(mockConversionTarget2.getTableMetadata()).thenReturn(conversionTarget2Metadata);
+    when(mockConversionSource.getCommitsBacklog(instantsForIncrementalSync))
+        .thenReturn(commitsBacklog);
+    Map<ConversionTarget, TableSyncMetadata> conversionTargetWithMetadata = new HashMap<>();
+    conversionTargetWithMetadata.put(mockConversionTarget1, conversionTarget1Metadata.get());
+    conversionTargetWithMetadata.put(mockConversionTarget2, conversionTarget2Metadata.get());
     when(tableFormatSync.syncChanges(
-            eq(clientsWithMetadata),
+            eq(conversionTargetWithMetadata),
             argThat(
                 matches(
                     IncrementalTableChanges.builder()
@@ -350,9 +352,10 @@ public class TestOneTableClient {
         .thenReturn(Collections.emptyMap());
     // Iceberg and Delta have no commits to sync
     Map<String, SyncResult> expectedSyncResult = Collections.emptyMap();
-    OneTableClient oneTableClient =
-        new OneTableClient(mockConf, mockTableFormatClientFactory, tableFormatSync);
-    Map<String, SyncResult> result = oneTableClient.sync(perTableConfig, mockSourceClientProvider);
+    ConversionController conversionController =
+        new ConversionController(mockConf, mockConversionTargetFactory, tableFormatSync);
+    Map<String, SyncResult> result =
+        conversionController.sync(perTableConfig, mockConversionSourceProvider);
     assertEquals(expectedSyncResult, result);
   }
 
diff --git a/core/src/test/java/org/apache/xtable/client/TestTableFormatClientFactory.java b/core/src/test/java/org/apache/xtable/conversion/TestConversionTargetFactory.java
similarity index 77%
rename from core/src/test/java/org/apache/xtable/client/TestTableFormatClientFactory.java
rename to core/src/test/java/org/apache/xtable/conversion/TestConversionTargetFactory.java
index 9a7e4175..34d3cbef 100644
--- a/core/src/test/java/org/apache/xtable/client/TestTableFormatClientFactory.java
+++ b/core/src/test/java/org/apache/xtable/conversion/TestConversionTargetFactory.java
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
  
-package org.apache.xtable.client;
+package org.apache.xtable.conversion;
 
 import static org.apache.xtable.GenericTable.getTableName;
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -33,14 +33,14 @@ import org.junit.jupiter.api.Test;
 import org.apache.xtable.exception.NotSupportedException;
 import org.apache.xtable.model.storage.TableFormat;
 import org.apache.xtable.model.sync.SyncMode;
-import org.apache.xtable.spi.sync.TargetClient;
+import org.apache.xtable.spi.sync.ConversionTarget;
 
-public class TestTableFormatClientFactory {
+public class TestConversionTargetFactory {
 
   @Test
-  public void testTableClientFromNameForDELTA() {
-    TargetClient tc =
-        TableFormatClientFactory.getInstance().createTargetClientForName(TableFormat.DELTA);
+  public void testConversionTargetFromNameForDELTA() {
+    ConversionTarget tc =
+        ConversionTargetFactory.getInstance().createConversionTargetForName(TableFormat.DELTA);
     assertNotNull(tc);
     PerTableConfig perTableConfig =
         getPerTableConfig(Arrays.asList(TableFormat.DELTA), SyncMode.INCREMENTAL);
@@ -51,9 +51,9 @@ public class TestTableFormatClientFactory {
   }
 
   @Test
-  public void testTableClientFromNameForHUDI() {
-    TargetClient tc =
-        TableFormatClientFactory.getInstance().createTargetClientForName(TableFormat.HUDI);
+  public void testConversionTargetFromNameForHUDI() {
+    ConversionTarget tc =
+        ConversionTargetFactory.getInstance().createConversionTargetForName(TableFormat.HUDI);
     assertNotNull(tc);
     PerTableConfig perTableConfig =
         getPerTableConfig(Arrays.asList(TableFormat.HUDI), SyncMode.INCREMENTAL);
@@ -64,9 +64,9 @@ public class TestTableFormatClientFactory {
   }
 
   @Test
-  public void testTableClientFromNameForICEBERG() {
-    TargetClient tc =
-        TableFormatClientFactory.getInstance().createTargetClientForName(TableFormat.ICEBERG);
+  public void testConversionTargetFromNameForICEBERG() {
+    ConversionTarget tc =
+        ConversionTargetFactory.getInstance().createConversionTargetForName(TableFormat.ICEBERG);
     assertNotNull(tc);
     PerTableConfig perTableConfig =
         getPerTableConfig(Arrays.asList(TableFormat.ICEBERG), SyncMode.INCREMENTAL);
@@ -77,23 +77,23 @@ public class TestTableFormatClientFactory {
   }
 
   @Test
-  public void testTableClientFromNameForUNKOWN() {
+  public void testConversionTargetFromNameForUNKOWN() {
     NotSupportedException thrown =
         assertThrows(
             NotSupportedException.class,
-            () -> TableFormatClientFactory.getInstance().createTargetClientForName("UNKNOWN"),
+            () -> ConversionTargetFactory.getInstance().createConversionTargetForName("UNKNOWN"),
             "NotSupportedException expected and operation succeeded inappropriately.");
     assertTrue(thrown.getMessage().contains("UNKNOWN"));
   }
 
   @Test
-  public void testTableClientFromFormatType() {
+  public void testConversionTargetFromFormatType() {
     PerTableConfig perTableConfig =
         getPerTableConfig(Arrays.asList(TableFormat.DELTA), SyncMode.INCREMENTAL);
     Configuration conf = new Configuration();
     conf.setStrings("spark.master", "local");
-    TargetClient tc =
-        TableFormatClientFactory.getInstance()
+    ConversionTarget tc =
+        ConversionTargetFactory.getInstance()
             .createForFormat(TableFormat.DELTA, perTableConfig, conf);
     assertEquals(tc.getTableFormat(), TableFormat.DELTA);
   }
diff --git a/core/src/test/java/org/apache/xtable/client/TestPerTableConfig.java b/core/src/test/java/org/apache/xtable/conversion/TestPerTableConfig.java
similarity index 99%
rename from core/src/test/java/org/apache/xtable/client/TestPerTableConfig.java
rename to core/src/test/java/org/apache/xtable/conversion/TestPerTableConfig.java
index 1687cd1c..4f057385 100644
--- a/core/src/test/java/org/apache/xtable/client/TestPerTableConfig.java
+++ b/core/src/test/java/org/apache/xtable/conversion/TestPerTableConfig.java
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
  
-package org.apache.xtable.client;
+package org.apache.xtable.conversion;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNull;
diff --git a/core/src/test/java/org/apache/xtable/delta/ITDeltaSourceClient.java b/core/src/test/java/org/apache/xtable/delta/ITDeltaConversionTargetSource.java
similarity index 89%
rename from core/src/test/java/org/apache/xtable/delta/ITDeltaSourceClient.java
rename to core/src/test/java/org/apache/xtable/delta/ITDeltaConversionTargetSource.java
index 3a0f589a..6a29bd18 100644
--- a/core/src/test/java/org/apache/xtable/delta/ITDeltaSourceClient.java
+++ b/core/src/test/java/org/apache/xtable/delta/ITDeltaConversionTargetSource.java
@@ -53,8 +53,8 @@ import org.junit.jupiter.params.provider.MethodSource;
 import org.apache.xtable.GenericTable;
 import org.apache.xtable.TestSparkDeltaTable;
 import org.apache.xtable.ValidationTestHelper;
-import org.apache.xtable.client.PerTableConfig;
-import org.apache.xtable.client.PerTableConfigImpl;
+import org.apache.xtable.conversion.PerTableConfig;
+import org.apache.xtable.conversion.PerTableConfigImpl;
 import org.apache.xtable.model.CommitsBacklog;
 import org.apache.xtable.model.InstantsForIncrementalSync;
 import org.apache.xtable.model.InternalSnapshot;
@@ -73,7 +73,7 @@ import org.apache.xtable.model.stat.Range;
 import org.apache.xtable.model.storage.*;
 import org.apache.xtable.model.storage.InternalDataFile;
 
-public class ITDeltaSourceClient {
+public class ITDeltaConversionTargetSource {
 
   private static final InternalField COL1_INT_FIELD =
       InternalField.builder()
@@ -118,7 +118,7 @@ public class ITDeltaSourceClient {
   @TempDir private static Path tempDir;
   private static SparkSession sparkSession;
 
-  private DeltaSourceClientProvider clientProvider;
+  private DeltaConversionSourceProvider conversionSourceProvider;
 
   @BeforeAll
   public static void setupOnce() {
@@ -150,8 +150,8 @@ public class ITDeltaSourceClient {
     Configuration hadoopConf = new Configuration();
     hadoopConf.set("fs.defaultFS", "file:///");
 
-    clientProvider = new DeltaSourceClientProvider();
-    clientProvider.init(hadoopConf, null);
+    conversionSourceProvider = new DeltaConversionSourceProvider();
+    conversionSourceProvider.init(hadoopConf, null);
   }
 
   @Test
@@ -166,16 +166,17 @@ public class ITDeltaSourceClient {
             + "` USING DELTA LOCATION '"
             + basePath
             + "' AS SELECT * FROM VALUES (1, 2)");
-    // Create Delta source client
+    // Create Delta source
     PerTableConfig tableConfig =
         PerTableConfigImpl.builder()
             .tableName(tableName)
             .tableBasePath(basePath.toString())
             .targetTableFormats(Collections.singletonList(TableFormat.ICEBERG))
             .build();
-    DeltaSourceClient client = clientProvider.getSourceClientInstance(tableConfig);
+    DeltaConversionSource conversionSource =
+        conversionSourceProvider.getConversionSourceInstance(tableConfig);
     // Get current snapshot
-    InternalSnapshot snapshot = client.getCurrentSnapshot();
+    InternalSnapshot snapshot = conversionSource.getCurrentSnapshot();
     // Validate table
     List<InternalField> fields = Arrays.asList(COL1_INT_FIELD, COL2_INT_FIELD);
     validateTable(
@@ -228,16 +229,17 @@ public class ITDeltaSourceClient {
             + "LOCATION '"
             + basePath
             + "' AS SELECT 'SingleValue' AS part_col, 1 AS col1, 2 AS col2");
-    // Create Delta source client
+    // Create Delta source
     PerTableConfig tableConfig =
         PerTableConfigImpl.builder()
             .tableName(tableName)
             .tableBasePath(basePath.toString())
             .targetTableFormats(Collections.singletonList(TableFormat.ICEBERG))
             .build();
-    DeltaSourceClient client = clientProvider.getSourceClientInstance(tableConfig);
+    DeltaConversionSource conversionSource =
+        conversionSourceProvider.getConversionSourceInstance(tableConfig);
     // Get current snapshot
-    InternalSnapshot snapshot = client.getCurrentSnapshot();
+    InternalSnapshot snapshot = conversionSource.getCurrentSnapshot();
     // Validate table
     InternalField partCol =
         InternalField.builder()
@@ -320,16 +322,17 @@ public class ITDeltaSourceClient {
         "INSERT INTO TABLE `"
             + tableName
             + "` VALUES(1, CAST('2012-02-12 00:12:34' AS TIMESTAMP))");
-    // Create Delta source client
+    // Create Delta source
     PerTableConfig tableConfig =
         PerTableConfigImpl.builder()
             .tableName(tableName)
             .tableBasePath(basePath.toString())
             .targetTableFormats(Collections.singletonList(TableFormat.ICEBERG))
             .build();
-    DeltaSourceClient client = clientProvider.getSourceClientInstance(tableConfig);
+    DeltaConversionSource conversionSource =
+        conversionSourceProvider.getConversionSourceInstance(tableConfig);
     // Get current snapshot
-    InternalSnapshot snapshot = client.getCurrentSnapshot();
+    InternalSnapshot snapshot = conversionSource.getCurrentSnapshot();
   }
 
   @ParameterizedTest
@@ -365,9 +368,10 @@ public class ITDeltaSourceClient {
             .tableBasePath(testSparkDeltaTable.getBasePath())
             .targetTableFormats(Arrays.asList(TableFormat.HUDI, TableFormat.ICEBERG))
             .build();
-    DeltaSourceClient deltaSourceClient = clientProvider.getSourceClientInstance(tableConfig);
+    DeltaConversionSource conversionSource =
+        conversionSourceProvider.getConversionSourceInstance(tableConfig);
     assertEquals(180L, testSparkDeltaTable.getNumRows());
-    InternalSnapshot internalSnapshot = deltaSourceClient.getCurrentSnapshot();
+    InternalSnapshot internalSnapshot = conversionSource.getCurrentSnapshot();
 
     if (isPartitioned) {
       validateDeltaPartitioning(internalSnapshot);
@@ -380,9 +384,9 @@ public class ITDeltaSourceClient {
             .lastSyncInstant(Instant.ofEpochMilli(timestamp1))
             .build();
     CommitsBacklog<Long> commitsBacklog =
-        deltaSourceClient.getCommitsBacklog(instantsForIncrementalSync);
+        conversionSource.getCommitsBacklog(instantsForIncrementalSync);
     for (Long version : commitsBacklog.getCommitsToProcess()) {
-      TableChange tableChange = deltaSourceClient.getTableChangeForCommit(version);
+      TableChange tableChange = conversionSource.getTableChangeForCommit(version);
       allTableChanges.add(tableChange);
     }
     ValidationTestHelper.validateTableChanges(allActiveFiles, allTableChanges);
@@ -404,8 +408,9 @@ public class ITDeltaSourceClient {
             .tableBasePath(testSparkDeltaTable.getBasePath())
             .targetTableFormats(Arrays.asList(TableFormat.HUDI, TableFormat.ICEBERG))
             .build();
-    DeltaSourceClient deltaSourceClient = clientProvider.getSourceClientInstance(tableConfig);
-    InternalSnapshot snapshotAfterCommit1 = deltaSourceClient.getCurrentSnapshot();
+    DeltaConversionSource conversionSource =
+        conversionSourceProvider.getConversionSourceInstance(tableConfig);
+    InternalSnapshot snapshotAfterCommit1 = conversionSource.getCurrentSnapshot();
     List<String> allActivePaths = ValidationTestHelper.getAllFilePaths(snapshotAfterCommit1);
     assertEquals(1, allActivePaths.size());
     String activePathAfterCommit1 = allActivePaths.get(0);
@@ -423,19 +428,19 @@ public class ITDeltaSourceClient {
         InstantsForIncrementalSync.builder()
             .lastSyncInstant(Instant.ofEpochMilli(timestamp1))
             .build();
-    deltaSourceClient = clientProvider.getSourceClientInstance(tableConfig);
+    conversionSource = conversionSourceProvider.getConversionSourceInstance(tableConfig);
     CommitsBacklog<Long> instantCurrentCommitState =
-        deltaSourceClient.getCommitsBacklog(instantsForIncrementalSync);
+        conversionSource.getCommitsBacklog(instantsForIncrementalSync);
     boolean areFilesRemoved = false;
     for (Long version : instantCurrentCommitState.getCommitsToProcess()) {
-      TableChange tableChange = deltaSourceClient.getTableChangeForCommit(version);
+      TableChange tableChange = conversionSource.getTableChangeForCommit(version);
       areFilesRemoved = areFilesRemoved | checkIfFileIsRemoved(activePathAfterCommit1, tableChange);
     }
     assertTrue(areFilesRemoved);
-    assertTrue(deltaSourceClient.isIncrementalSyncSafeFrom(Instant.ofEpochMilli(timestamp1)));
+    assertTrue(conversionSource.isIncrementalSyncSafeFrom(Instant.ofEpochMilli(timestamp1)));
     // Table doesn't have instant of this older commit, hence it is not safe.
     Instant instantAsOfHourAgo = Instant.now().minus(1, ChronoUnit.HOURS);
-    assertFalse(deltaSourceClient.isIncrementalSyncSafeFrom(instantAsOfHourAgo));
+    assertFalse(conversionSource.isIncrementalSyncSafeFrom(instantAsOfHourAgo));
   }
 
   @ParameterizedTest
@@ -471,9 +476,10 @@ public class ITDeltaSourceClient {
             .tableBasePath(testSparkDeltaTable.getBasePath())
             .targetTableFormats(Arrays.asList(TableFormat.HUDI, TableFormat.ICEBERG))
             .build();
-    DeltaSourceClient deltaSourceClient = clientProvider.getSourceClientInstance(tableConfig);
+    DeltaConversionSource conversionSource =
+        conversionSourceProvider.getConversionSourceInstance(tableConfig);
     assertEquals(130L, testSparkDeltaTable.getNumRows());
-    InternalSnapshot internalSnapshot = deltaSourceClient.getCurrentSnapshot();
+    InternalSnapshot internalSnapshot = conversionSource.getCurrentSnapshot();
     if (isPartitioned) {
       validateDeltaPartitioning(internalSnapshot);
     }
@@ -485,9 +491,9 @@ public class ITDeltaSourceClient {
             .lastSyncInstant(Instant.ofEpochMilli(timestamp1))
             .build();
     CommitsBacklog<Long> commitsBacklog =
-        deltaSourceClient.getCommitsBacklog(instantsForIncrementalSync);
+        conversionSource.getCommitsBacklog(instantsForIncrementalSync);
     for (Long version : commitsBacklog.getCommitsToProcess()) {
-      TableChange tableChange = deltaSourceClient.getTableChangeForCommit(version);
+      TableChange tableChange = conversionSource.getTableChangeForCommit(version);
       allTableChanges.add(tableChange);
     }
     ValidationTestHelper.validateTableChanges(allActiveFiles, allTableChanges);
@@ -518,9 +524,10 @@ public class ITDeltaSourceClient {
             .tableBasePath(testSparkDeltaTable.getBasePath())
             .targetTableFormats(Arrays.asList(TableFormat.HUDI, TableFormat.ICEBERG))
             .build();
-    DeltaSourceClient deltaSourceClient = clientProvider.getSourceClientInstance(tableConfig);
+    DeltaConversionSource conversionSource =
+        conversionSourceProvider.getConversionSourceInstance(tableConfig);
     assertEquals(150L, testSparkDeltaTable.getNumRows());
-    InternalSnapshot internalSnapshot = deltaSourceClient.getCurrentSnapshot();
+    InternalSnapshot internalSnapshot = conversionSource.getCurrentSnapshot();
     if (isPartitioned) {
       validateDeltaPartitioning(internalSnapshot);
     }
@@ -532,9 +539,9 @@ public class ITDeltaSourceClient {
             .lastSyncInstant(Instant.ofEpochMilli(timestamp1))
             .build();
     CommitsBacklog<Long> commitsBacklog =
-        deltaSourceClient.getCommitsBacklog(instantsForIncrementalSync);
+        conversionSource.getCommitsBacklog(instantsForIncrementalSync);
     for (Long version : commitsBacklog.getCommitsToProcess()) {
-      TableChange tableChange = deltaSourceClient.getTableChangeForCommit(version);
+      TableChange tableChange = conversionSource.getTableChangeForCommit(version);
       allTableChanges.add(tableChange);
     }
     ValidationTestHelper.validateTableChanges(allActiveFiles, allTableChanges);
@@ -574,10 +581,11 @@ public class ITDeltaSourceClient {
             .tableBasePath(testSparkDeltaTable.getBasePath())
             .targetTableFormats(Arrays.asList(TableFormat.HUDI, TableFormat.ICEBERG))
             .build();
-    DeltaSourceClient deltaSourceClient = clientProvider.getSourceClientInstance(tableConfig);
+    DeltaConversionSource conversionSource =
+        conversionSourceProvider.getConversionSourceInstance(tableConfig);
     assertEquals(
         120 - rowsByPartition.get(partitionValueToDelete).size(), testSparkDeltaTable.getNumRows());
-    InternalSnapshot internalSnapshot = deltaSourceClient.getCurrentSnapshot();
+    InternalSnapshot internalSnapshot = conversionSource.getCurrentSnapshot();
 
     validateDeltaPartitioning(internalSnapshot);
     ValidationTestHelper.validateSnapshot(
@@ -588,9 +596,9 @@ public class ITDeltaSourceClient {
             .lastSyncInstant(Instant.ofEpochMilli(timestamp1))
             .build();
     CommitsBacklog<Long> commitsBacklog =
-        deltaSourceClient.getCommitsBacklog(instantsForIncrementalSync);
+        conversionSource.getCommitsBacklog(instantsForIncrementalSync);
     for (Long version : commitsBacklog.getCommitsToProcess()) {
-      TableChange tableChange = deltaSourceClient.getTableChangeForCommit(version);
+      TableChange tableChange = conversionSource.getTableChangeForCommit(version);
       allTableChanges.add(tableChange);
     }
     ValidationTestHelper.validateTableChanges(allActiveFiles, allTableChanges);
@@ -633,9 +641,10 @@ public class ITDeltaSourceClient {
             .tableBasePath(testSparkDeltaTable.getBasePath())
             .targetTableFormats(Arrays.asList(TableFormat.HUDI, TableFormat.ICEBERG))
             .build();
-    DeltaSourceClient deltaSourceClient = clientProvider.getSourceClientInstance(tableConfig);
+    DeltaConversionSource conversionSource =
+        conversionSourceProvider.getConversionSourceInstance(tableConfig);
     assertEquals(250L, testSparkDeltaTable.getNumRows());
-    InternalSnapshot internalSnapshot = deltaSourceClient.getCurrentSnapshot();
+    InternalSnapshot internalSnapshot = conversionSource.getCurrentSnapshot();
     if (isPartitioned) {
       validateDeltaPartitioning(internalSnapshot);
     }
@@ -647,9 +656,9 @@ public class ITDeltaSourceClient {
             .lastSyncInstant(Instant.ofEpochMilli(timestamp1))
             .build();
     CommitsBacklog<Long> commitsBacklog =
-        deltaSourceClient.getCommitsBacklog(instantsForIncrementalSync);
+        conversionSource.getCommitsBacklog(instantsForIncrementalSync);
     for (Long version : commitsBacklog.getCommitsToProcess()) {
-      TableChange tableChange = deltaSourceClient.getTableChangeForCommit(version);
+      TableChange tableChange = conversionSource.getTableChangeForCommit(version);
       allTableChanges.add(tableChange);
     }
     ValidationTestHelper.validateTableChanges(allActiveFiles, allTableChanges);
diff --git a/core/src/test/java/org/apache/xtable/delta/TestDeltaSync.java b/core/src/test/java/org/apache/xtable/delta/TestDeltaSync.java
index b248a630..514cc394 100644
--- a/core/src/test/java/org/apache/xtable/delta/TestDeltaSync.java
+++ b/core/src/test/java/org/apache/xtable/delta/TestDeltaSync.java
@@ -76,7 +76,7 @@ import io.delta.standalone.expressions.Literal;
 import io.delta.standalone.types.IntegerType;
 import io.delta.standalone.types.StringType;
 
-import org.apache.xtable.client.PerTableConfigImpl;
+import org.apache.xtable.conversion.PerTableConfigImpl;
 import org.apache.xtable.model.InternalSnapshot;
 import org.apache.xtable.model.InternalTable;
 import org.apache.xtable.model.schema.InternalField;
@@ -105,7 +105,7 @@ public class TestDeltaSync {
   private static SparkSession sparkSession;
 
   @TempDir public static java.nio.file.Path tempDir;
-  private DeltaClient deltaClient;
+  private DeltaConversionTarget conversionTarget;
   private Path basePath;
   private String tableName;
 
@@ -124,8 +124,8 @@ public class TestDeltaSync {
     tableName = "test-" + UUID.randomUUID();
     basePath = tempDir.resolve(tableName);
     Files.createDirectories(basePath);
-    deltaClient =
-        new DeltaClient(
+    conversionTarget =
+        new DeltaConversionTarget(
             PerTableConfigImpl.builder()
                 .tableName(tableName)
                 .tableBasePath(basePath.toString())
@@ -160,10 +160,12 @@ public class TestDeltaSync {
     InternalSnapshot snapshot1 = buildSnapshot(table1, dataFile1, dataFile2);
     InternalSnapshot snapshot2 = buildSnapshot(table2, dataFile2, dataFile3);
 
-    TableFormatSync.getInstance().syncSnapshot(Collections.singletonList(deltaClient), snapshot1);
+    TableFormatSync.getInstance()
+        .syncSnapshot(Collections.singletonList(conversionTarget), snapshot1);
     validateDeltaTable(basePath, new HashSet<>(Arrays.asList(dataFile1, dataFile2)), null);
 
-    TableFormatSync.getInstance().syncSnapshot(Collections.singletonList(deltaClient), snapshot2);
+    TableFormatSync.getInstance()
+        .syncSnapshot(Collections.singletonList(conversionTarget), snapshot2);
     validateDeltaTable(basePath, new HashSet<>(Arrays.asList(dataFile2, dataFile3)), null);
   }
 
@@ -212,7 +214,8 @@ public class TestDeltaSync {
 
     InternalSnapshot snapshot1 = buildSnapshot(table, dataFile1, dataFile2, dataFile3);
 
-    TableFormatSync.getInstance().syncSnapshot(Collections.singletonList(deltaClient), snapshot1);
+    TableFormatSync.getInstance()
+        .syncSnapshot(Collections.singletonList(conversionTarget), snapshot1);
     validateDeltaTable(basePath, new HashSet<>(Arrays.asList(dataFile3)), equalToExpr);
   }
 
@@ -290,7 +293,8 @@ public class TestDeltaSync {
     And CombinedExpr = new And(equalToExpr1, equalToExpr2);
 
     InternalSnapshot snapshot1 = buildSnapshot(table, dataFile1, dataFile2, dataFile3);
-    TableFormatSync.getInstance().syncSnapshot(Collections.singletonList(deltaClient), snapshot1);
+    TableFormatSync.getInstance()
+        .syncSnapshot(Collections.singletonList(conversionTarget), snapshot1);
     validateDeltaTable(basePath, new HashSet<>(Arrays.asList(dataFile2)), CombinedExpr);
   }
 
@@ -333,7 +337,8 @@ public class TestDeltaSync {
 
     InternalSnapshot snapshot1 = buildSnapshot(table, dataFile1, dataFile2, dataFile3);
 
-    TableFormatSync.getInstance().syncSnapshot(Collections.singletonList(deltaClient), snapshot1);
+    TableFormatSync.getInstance()
+        .syncSnapshot(Collections.singletonList(conversionTarget), snapshot1);
 
     Dataset<Row> dataset = sparkSession.read().format("delta").load(basePath.toString());
     org.apache.spark.sql.catalyst.expressions.Expression expression =
diff --git a/core/src/test/java/org/apache/xtable/hudi/ITHudiSourceClient.java b/core/src/test/java/org/apache/xtable/hudi/ITHudiConversionSourceSource.java
similarity index 98%
rename from core/src/test/java/org/apache/xtable/hudi/ITHudiSourceClient.java
rename to core/src/test/java/org/apache/xtable/hudi/ITHudiConversionSourceSource.java
index 2f782f8b..241a33a7 100644
--- a/core/src/test/java/org/apache/xtable/hudi/ITHudiSourceClient.java
+++ b/core/src/test/java/org/apache/xtable/hudi/ITHudiConversionSourceSource.java
@@ -70,7 +70,7 @@ import org.apache.xtable.model.TableChange;
 /**
  * A suite of functional tests that the extraction from Hudi to Intermediate representation works.
  */
-public class ITHudiSourceClient {
+public class ITHudiConversionSourceSource {
   @TempDir public static Path tempDir;
   private static JavaSparkContext jsc;
   private static SparkSession sparkSession;
@@ -133,7 +133,7 @@ public class ITHudiSourceClient {
         allBaseFilePaths.add(table.getAllLatestBaseFilePaths());
       }
 
-      HudiClient hudiClient =
+      HudiConversionSource hudiClient =
           getHudiSourceClient(
               CONFIGURATION, table.getBasePath(), partitionConfig.getOneTableConfig());
       // Get the current snapshot
@@ -181,7 +181,7 @@ public class ITHudiSourceClient {
       table.deleteRecords(insertsForCommit1.subList(15, 30), true);
       allBaseFilePaths.add(table.getAllLatestBaseFilePaths());
 
-      HudiClient hudiClient =
+      HudiConversionSource hudiClient =
           getHudiSourceClient(
               CONFIGURATION, table.getBasePath(), partitionConfig.getOneTableConfig());
       // Get the current snapshot
@@ -223,7 +223,7 @@ public class ITHudiSourceClient {
 
       table.clean(); // cleans up file groups from commitInstant1
 
-      HudiClient hudiClient =
+      HudiConversionSource hudiClient =
           getHudiSourceClient(
               CONFIGURATION, table.getBasePath(), partitionConfig.getOneTableConfig());
       // commitInstant1 is not safe for incremental sync as cleaner has run after and touched
@@ -270,7 +270,7 @@ public class ITHudiSourceClient {
       table.insertRecords(20, partitionToDelete, true);
       allBaseFilePaths.add(table.getAllLatestBaseFilePaths());
 
-      HudiClient hudiClient =
+      HudiConversionSource hudiClient =
           getHudiSourceClient(CONFIGURATION, table.getBasePath(), "level:VALUE");
       // Get the current snapshot
       InternalSnapshot internalSnapshot = hudiClient.getCurrentSnapshot();
@@ -322,7 +322,7 @@ public class ITHudiSourceClient {
       table.insertRecords(20, selectedPartition, true);
       allBaseFilePaths.add(table.getAllLatestBaseFilePaths());
 
-      HudiClient hudiClient =
+      HudiConversionSource hudiClient =
           getHudiSourceClient(CONFIGURATION, table.getBasePath(), "level:VALUE");
       // Get the current snapshot
       InternalSnapshot internalSnapshot = hudiClient.getCurrentSnapshot();
@@ -388,7 +388,7 @@ public class ITHudiSourceClient {
       table.insertRecords(100, true);
       allBaseFilePaths.add(table.getAllLatestBaseFilePaths());
 
-      HudiClient hudiClient =
+      HudiConversionSource hudiClient =
           getHudiSourceClient(
               CONFIGURATION, table.getBasePath(), partitionConfig.getOneTableConfig());
       // Get the current snapshot
@@ -443,7 +443,7 @@ public class ITHudiSourceClient {
       table.insertRecords(50, true);
       allBaseFilePaths.add(table.getAllLatestBaseFilePaths());
 
-      HudiClient hudiClient =
+      HudiConversionSource hudiClient =
           getHudiSourceClient(
               CONFIGURATION, table.getBasePath(), partitionConfig.getOneTableConfig());
       // Get the current snapshot
@@ -509,7 +509,7 @@ public class ITHudiSourceClient {
       table.insertRecordsWithCommitAlreadyStarted(insertsForCommit4, commitInstant4, true);
       List<String> baseFilesAfterCommit4 = table.getAllLatestBaseFilePaths();
 
-      HudiClient hudiClient =
+      HudiConversionSource hudiClient =
           getHudiSourceClient(
               CONFIGURATION, table.getBasePath(), partitionConfig.getOneTableConfig());
       // Get the current snapshot
@@ -559,7 +559,7 @@ public class ITHudiSourceClient {
             tableType -> partitionConfigs.stream().map(config -> Arguments.of(tableType, config)));
   }
 
-  private HudiClient getHudiSourceClient(
+  private HudiConversionSource getHudiSourceClient(
       Configuration conf, String basePath, String onetablePartitionConfig) {
     HoodieTableMetaClient hoodieTableMetaClient =
         HoodieTableMetaClient.builder()
@@ -572,7 +572,7 @@ public class ITHudiSourceClient {
             HudiSourceConfigImpl.builder()
                 .partitionFieldSpecConfig(onetablePartitionConfig)
                 .build());
-    return new HudiClient(hoodieTableMetaClient, partitionSpecExtractor);
+    return new HudiConversionSource(hoodieTableMetaClient, partitionSpecExtractor);
   }
 
   private boolean checkIfNewFileGroupIsAdded(String activePath, TableChange tableChange) {
diff --git a/core/src/test/java/org/apache/xtable/hudi/ITHudiTargetClient.java b/core/src/test/java/org/apache/xtable/hudi/ITHudiConversionSourceTarget.java
similarity index 97%
rename from core/src/test/java/org/apache/xtable/hudi/ITHudiTargetClient.java
rename to core/src/test/java/org/apache/xtable/hudi/ITHudiConversionSourceTarget.java
index ebe0d6bc..a0d51b7a 100644
--- a/core/src/test/java/org/apache/xtable/hudi/ITHudiTargetClient.java
+++ b/core/src/test/java/org/apache/xtable/hudi/ITHudiConversionSourceTarget.java
@@ -70,7 +70,7 @@ import org.apache.hudi.config.HoodieWriteConfig;
 import org.apache.hudi.metadata.HoodieBackedTableMetadata;
 import org.apache.hudi.metadata.HoodieMetadataFileSystemView;
 
-import org.apache.xtable.client.PerTableConfigImpl;
+import org.apache.xtable.conversion.PerTableConfigImpl;
 import org.apache.xtable.model.InternalTable;
 import org.apache.xtable.model.TableSyncMetadata;
 import org.apache.xtable.model.schema.InternalField;
@@ -87,13 +87,13 @@ import org.apache.xtable.model.storage.FileFormat;
 import org.apache.xtable.model.storage.InternalDataFile;
 import org.apache.xtable.model.storage.PartitionFileGroup;
 import org.apache.xtable.model.storage.TableFormat;
-import org.apache.xtable.spi.sync.TargetClient;
+import org.apache.xtable.spi.sync.ConversionTarget;
 
 /**
  * A suite of functional tests that assert that the metadata for the hudi table is properly written
  * to disk.
  */
-public class ITHudiTargetClient {
+public class ITHudiConversionSourceTarget {
   @TempDir public static Path tempDir;
   private static final Configuration CONFIGURATION = new Configuration();
   private static final HoodieEngineContext CONTEXT = new HoodieJavaEngineContext(CONFIGURATION);
@@ -199,7 +199,7 @@ public class ITHudiTargetClient {
             .fileRemoved(fileToRemove)
             .build();
     // perform sync
-    HudiTargetClient targetClient = getTargetClient();
+    HudiConversionTarget targetClient = getTargetClient();
     InternalTable initialState = getState(Instant.now());
     targetClient.beginSync(initialState);
     targetClient.syncFilesForDiff(dataFilesDiff);
@@ -240,7 +240,7 @@ public class ITHudiTargetClient {
                 .build());
     // sync snapshot and metadata
     InternalTable initialState = getState(Instant.now());
-    HudiTargetClient targetClient = getTargetClient();
+    HudiConversionTarget targetClient = getTargetClient();
     targetClient.beginSync(initialState);
     targetClient.syncFilesForSnapshot(snapshot);
     TableSyncMetadata latestState =
@@ -285,7 +285,7 @@ public class ITHudiTargetClient {
                 .build());
     // sync snapshot and metadata
     InternalTable initialState = getState(Instant.now().minus(24, ChronoUnit.HOURS));
-    HudiTargetClient targetClient = getTargetClient();
+    HudiConversionTarget targetClient = getTargetClient();
     targetClient.beginSync(initialState);
     targetClient.syncFilesForSnapshot(snapshot);
     TableSyncMetadata latestState =
@@ -374,19 +374,19 @@ public class ITHudiTargetClient {
   }
 
   private TableSyncMetadata incrementalSync(
-      TargetClient targetClient,
+      ConversionTarget conversionTarget,
       List<InternalDataFile> filesToAdd,
       List<InternalDataFile> filesToRemove,
       Instant commitStart) {
     DataFilesDiff dataFilesDiff2 =
         DataFilesDiff.builder().filesAdded(filesToAdd).filesRemoved(filesToRemove).build();
     InternalTable state3 = getState(commitStart);
-    targetClient.beginSync(state3);
-    targetClient.syncFilesForDiff(dataFilesDiff2);
+    conversionTarget.beginSync(state3);
+    conversionTarget.syncFilesForDiff(dataFilesDiff2);
     TableSyncMetadata latestState =
         TableSyncMetadata.of(state3.getLatestCommitTime(), Collections.emptyList());
-    targetClient.syncMetadata(latestState);
-    targetClient.completeSync();
+    conversionTarget.syncMetadata(latestState);
+    conversionTarget.completeSync();
     return latestState;
   }
 
@@ -583,8 +583,8 @@ public class ITHudiTargetClient {
         .build();
   }
 
-  private HudiTargetClient getTargetClient() {
-    return new HudiTargetClient(
+  private HudiConversionTarget getTargetClient() {
+    return new HudiConversionTarget(
         PerTableConfigImpl.builder()
             .tableBasePath(tableBasePath)
             .targetTableFormats(Collections.singletonList(TableFormat.HUDI))
diff --git a/core/src/test/java/org/apache/xtable/hudi/TestHudiTargetClient.java b/core/src/test/java/org/apache/xtable/hudi/TestHudiConversionSourceTarget.java
similarity index 84%
rename from core/src/test/java/org/apache/xtable/hudi/TestHudiTargetClient.java
rename to core/src/test/java/org/apache/xtable/hudi/TestHudiConversionSourceTarget.java
index 775307c0..8f2ccd94 100644
--- a/core/src/test/java/org/apache/xtable/hudi/TestHudiTargetClient.java
+++ b/core/src/test/java/org/apache/xtable/hudi/TestHudiConversionSourceTarget.java
@@ -53,10 +53,10 @@ import org.apache.xtable.model.storage.DataFilesDiff;
 import org.apache.xtable.model.storage.PartitionFileGroup;
 
 /**
- * Unit tests that focus on the basic control flow of the HudiTargetClient. Functional tests are in
- * {@link ITHudiTargetClient}.
+ * Unit tests that focus on the basic control flow of the HudiConversionTarget. Functional tests are
+ * in {@link ITHudiConversionSourceTarget}.
  */
-public class TestHudiTargetClient {
+public class TestHudiConversionSourceTarget {
   private static final int RETENTION_IN_HOURS = 1;
   private static final int MAX_DELTA_COMMITS = 2;
   private static final Instant COMMIT_TIME = Instant.ofEpochMilli(1598644800000L);
@@ -73,13 +73,13 @@ public class TestHudiTargetClient {
       mock(BaseFileUpdatesExtractor.class);
   private final AvroSchemaConverter mockAvroSchemaConverter = mock(AvroSchemaConverter.class);
   private final HudiTableManager mockHudiTableManager = mock(HudiTableManager.class);
-  private final HudiTargetClient.CommitStateCreator mockCommitStateCreator =
-      mock(HudiTargetClient.CommitStateCreator.class);
+  private final HudiConversionTarget.CommitStateCreator mockCommitStateCreator =
+      mock(HudiConversionTarget.CommitStateCreator.class);
 
-  private HudiTargetClient getTargetClient(HoodieTableMetaClient mockMetaClient) {
+  private HudiConversionTarget getTargetClient(HoodieTableMetaClient mockMetaClient) {
     when(mockHudiTableManager.loadTableMetaClientIfExists(BASE_PATH))
         .thenReturn(Optional.ofNullable(mockMetaClient));
-    return new HudiTargetClient(
+    return new HudiConversionTarget(
         BASE_PATH,
         RETENTION_IN_HOURS,
         MAX_DELTA_COMMITS,
@@ -96,8 +96,9 @@ public class TestHudiTargetClient {
 
   @Test
   void syncSchema() {
-    HudiTargetClient targetClient = getTargetClient(null);
-    HudiTargetClient.CommitState mockCommitState = initMocksForBeginSync(targetClient).getLeft();
+    HudiConversionTarget targetClient = getTargetClient(null);
+    HudiConversionTarget.CommitState mockCommitState =
+        initMocksForBeginSync(targetClient).getLeft();
     InternalSchema input =
         InternalSchema.builder()
             .name("schema")
@@ -114,7 +115,7 @@ public class TestHudiTargetClient {
 
   @Test
   void syncSchemaWithRecordKeyChanged() {
-    HudiTargetClient targetClient = getTargetClient(null);
+    HudiConversionTarget targetClient = getTargetClient(null);
     initMocksForBeginSync(targetClient);
     List<InternalField> recordKeyFields =
         Arrays.asList(
@@ -137,8 +138,9 @@ public class TestHudiTargetClient {
 
   @Test
   void syncMetadata() {
-    HudiTargetClient targetClient = getTargetClient(null);
-    HudiTargetClient.CommitState mockCommitState = initMocksForBeginSync(targetClient).getLeft();
+    HudiConversionTarget targetClient = getTargetClient(null);
+    HudiConversionTarget.CommitState mockCommitState =
+        initMocksForBeginSync(targetClient).getLeft();
     TableSyncMetadata metadata = TableSyncMetadata.of(COMMIT_TIME, Collections.emptyList());
     targetClient.syncMetadata(metadata);
     // validate that metadata is set in commitState
@@ -147,8 +149,9 @@ public class TestHudiTargetClient {
 
   @Test
   void completeSync() {
-    HudiTargetClient targetClient = getTargetClient(null);
-    HudiTargetClient.CommitState mockCommitState = initMocksForBeginSync(targetClient).getLeft();
+    HudiConversionTarget targetClient = getTargetClient(null);
+    HudiConversionTarget.CommitState mockCommitState =
+        initMocksForBeginSync(targetClient).getLeft();
     targetClient.completeSync();
     // validate that commit is called
     verify(mockCommitState).commit();
@@ -156,7 +159,7 @@ public class TestHudiTargetClient {
 
   @Test
   void syncPartitionSpecSucceedsWithoutChanges() {
-    HudiTargetClient targetClient = getTargetClient(null);
+    HudiConversionTarget targetClient = getTargetClient(null);
     HoodieTableMetaClient mockMetaClient = initMocksForBeginSync(targetClient).getRight();
     String field1 = "field1";
     String field2 = "field2";
@@ -179,7 +182,7 @@ public class TestHudiTargetClient {
   @ParameterizedTest
   @ValueSource(strings = {"", "field1", "field2,field1"})
   void syncPartitionSpecFailsWithChanges(String partitionFields) {
-    HudiTargetClient targetClient = getTargetClient(null);
+    HudiConversionTarget targetClient = getTargetClient(null);
     HoodieTableMetaClient mockMetaClient = initMocksForBeginSync(targetClient).getRight();
     String field1 = "field1";
     String field2 = "field2";
@@ -204,8 +207,9 @@ public class TestHudiTargetClient {
 
   @Test
   void syncFilesForDiff() {
-    HudiTargetClient targetClient = getTargetClient(null);
-    HudiTargetClient.CommitState mockCommitState = initMocksForBeginSync(targetClient).getLeft();
+    HudiConversionTarget targetClient = getTargetClient(null);
+    HudiConversionTarget.CommitState mockCommitState =
+        initMocksForBeginSync(targetClient).getLeft();
     String instant = "commit";
     DataFilesDiff input = DataFilesDiff.builder().build();
     BaseFileUpdatesExtractor.ReplaceMetadata output =
@@ -221,10 +225,10 @@ public class TestHudiTargetClient {
 
   @Test
   void syncFilesForSnapshot() {
-    HudiTargetClient targetClient = getTargetClient(null);
-    Pair<HudiTargetClient.CommitState, HoodieTableMetaClient> mocks =
+    HudiConversionTarget targetClient = getTargetClient(null);
+    Pair<HudiConversionTarget.CommitState, HoodieTableMetaClient> mocks =
         initMocksForBeginSync(targetClient);
-    HudiTargetClient.CommitState mockCommitState = mocks.getLeft();
+    HudiConversionTarget.CommitState mockCommitState = mocks.getLeft();
     HoodieTableMetaClient mockMetaClient = mocks.getRight();
     String instant = "commit";
     List<PartitionFileGroup> input = Collections.emptyList();
@@ -243,7 +247,7 @@ public class TestHudiTargetClient {
   @Test
   void beginSyncForExistingTable() {
     HoodieTableMetaClient mockMetaClient = mock(HoodieTableMetaClient.class);
-    HudiTargetClient targetClient = getTargetClient(mockMetaClient);
+    HudiConversionTarget targetClient = getTargetClient(mockMetaClient);
 
     targetClient.beginSync(TABLE);
     // verify meta client timeline refreshed
@@ -253,15 +257,15 @@ public class TestHudiTargetClient {
         .create(mockMetaClient, COMMIT, RETENTION_IN_HOURS, MAX_DELTA_COMMITS);
   }
 
-  private Pair<HudiTargetClient.CommitState, HoodieTableMetaClient> initMocksForBeginSync(
-      HudiTargetClient targetClient) {
+  private Pair<HudiConversionTarget.CommitState, HoodieTableMetaClient> initMocksForBeginSync(
+      HudiConversionTarget targetClient) {
     HoodieTableMetaClient mockMetaClient = mock(HoodieTableMetaClient.class);
     HoodieTableConfig mockTableConfig = mock(HoodieTableConfig.class);
     when(mockMetaClient.getTableConfig()).thenReturn(mockTableConfig);
     when(mockTableConfig.getRecordKeyFields())
         .thenReturn(Option.of(new String[] {"record_key_field"}));
     when(mockHudiTableManager.initializeHudiTable(BASE_PATH, TABLE)).thenReturn(mockMetaClient);
-    HudiTargetClient.CommitState mockCommitState = mock(HudiTargetClient.CommitState.class);
+    HudiConversionTarget.CommitState mockCommitState = mock(HudiConversionTarget.CommitState.class);
     when(mockCommitStateCreator.create(
             mockMetaClient, COMMIT, RETENTION_IN_HOURS, MAX_DELTA_COMMITS))
         .thenReturn(mockCommitState);
diff --git a/core/src/test/java/org/apache/xtable/iceberg/ITIcebergSourceClient.java b/core/src/test/java/org/apache/xtable/iceberg/ITIcebergConversionTargetSource.java
similarity index 86%
rename from core/src/test/java/org/apache/xtable/iceberg/ITIcebergSourceClient.java
rename to core/src/test/java/org/apache/xtable/iceberg/ITIcebergConversionTargetSource.java
index a1b16ff7..997ab184 100644
--- a/core/src/test/java/org/apache/xtable/iceberg/ITIcebergSourceClient.java
+++ b/core/src/test/java/org/apache/xtable/iceberg/ITIcebergConversionTargetSource.java
@@ -46,8 +46,8 @@ import org.apache.iceberg.Snapshot;
 import org.apache.iceberg.data.Record;
 
 import org.apache.xtable.TestIcebergTable;
-import org.apache.xtable.client.PerTableConfig;
-import org.apache.xtable.client.PerTableConfigImpl;
+import org.apache.xtable.conversion.PerTableConfig;
+import org.apache.xtable.conversion.PerTableConfigImpl;
 import org.apache.xtable.model.CommitsBacklog;
 import org.apache.xtable.model.InstantsForIncrementalSync;
 import org.apache.xtable.model.InternalSnapshot;
@@ -56,16 +56,16 @@ import org.apache.xtable.model.schema.InternalPartitionField;
 import org.apache.xtable.model.schema.PartitionTransformType;
 import org.apache.xtable.model.storage.TableFormat;
 
-public class ITIcebergSourceClient {
+public class ITIcebergConversionTargetSource {
   private static final Configuration hadoopConf = new Configuration();
 
   @TempDir public static Path tempDir;
-  private IcebergSourceClientProvider clientProvider;
+  private IcebergConversionSourceProvider sourceProvider;
 
   @BeforeEach
   void setup() {
-    clientProvider = new IcebergSourceClientProvider();
-    clientProvider.init(hadoopConf, null);
+    sourceProvider = new IcebergConversionSourceProvider();
+    sourceProvider.init(hadoopConf, null);
   }
 
   @ParameterizedTest
@@ -103,9 +103,10 @@ public class ITIcebergSourceClient {
               .tableBasePath(testIcebergTable.getBasePath())
               .targetTableFormats(Arrays.asList(TableFormat.HUDI, TableFormat.DELTA))
               .build();
-      IcebergSourceClient icebergSourceClient = clientProvider.getSourceClientInstance(tableConfig);
+      IcebergConversionSource conversionSource =
+          sourceProvider.getConversionSourceInstance(tableConfig);
       assertEquals(180L, testIcebergTable.getNumRows());
-      InternalSnapshot internalSnapshot = icebergSourceClient.getCurrentSnapshot();
+      InternalSnapshot internalSnapshot = conversionSource.getCurrentSnapshot();
 
       if (isPartitioned) {
         validateIcebergPartitioning(internalSnapshot);
@@ -117,9 +118,9 @@ public class ITIcebergSourceClient {
               .lastSyncInstant(Instant.ofEpochMilli(timestamp1))
               .build();
       CommitsBacklog<Snapshot> commitsBacklog =
-          icebergSourceClient.getCommitsBacklog(instantsForIncrementalSync);
+          conversionSource.getCommitsBacklog(instantsForIncrementalSync);
       for (Snapshot snapshot : commitsBacklog.getCommitsToProcess()) {
-        TableChange tableChange = icebergSourceClient.getTableChangeForCommit(snapshot);
+        TableChange tableChange = conversionSource.getTableChangeForCommit(snapshot);
         allTableChanges.add(tableChange);
       }
       validateTableChanges(allActiveFiles, allTableChanges);
@@ -162,11 +163,12 @@ public class ITIcebergSourceClient {
               .tableBasePath(testIcebergTable.getBasePath())
               .targetTableFormats(Arrays.asList(TableFormat.HUDI, TableFormat.DELTA))
               .build();
-      IcebergSourceClient icebergSourceClient = clientProvider.getSourceClientInstance(tableConfig);
+      IcebergConversionSource conversionSource =
+          sourceProvider.getConversionSourceInstance(tableConfig);
       assertEquals(
           120 - recordsByPartition.get(partitionValueToDelete).size(),
           testIcebergTable.getNumRows());
-      InternalSnapshot internalSnapshot = icebergSourceClient.getCurrentSnapshot();
+      InternalSnapshot internalSnapshot = conversionSource.getCurrentSnapshot();
 
       validateIcebergPartitioning(internalSnapshot);
       validateSnapshot(internalSnapshot, allActiveFiles.get(allActiveFiles.size() - 1));
@@ -176,9 +178,9 @@ public class ITIcebergSourceClient {
               .lastSyncInstant(Instant.ofEpochMilli(timestamp1))
               .build();
       CommitsBacklog<Snapshot> commitsBacklog =
-          icebergSourceClient.getCommitsBacklog(instantsForIncrementalSync);
+          conversionSource.getCommitsBacklog(instantsForIncrementalSync);
       for (Snapshot snapshot : commitsBacklog.getCommitsToProcess()) {
-        TableChange tableChange = icebergSourceClient.getTableChangeForCommit(snapshot);
+        TableChange tableChange = conversionSource.getTableChangeForCommit(snapshot);
         allTableChanges.add(tableChange);
       }
       validateTableChanges(allActiveFiles, allTableChanges);
@@ -221,11 +223,12 @@ public class ITIcebergSourceClient {
               .tableBasePath(testIcebergTable.getBasePath())
               .targetTableFormats(Arrays.asList(TableFormat.HUDI, TableFormat.DELTA))
               .build();
-      IcebergSourceClient icebergSourceClient = clientProvider.getSourceClientInstance(tableConfig);
+      IcebergConversionSource conversionSource =
+          sourceProvider.getConversionSourceInstance(tableConfig);
       assertEquals(
           120 - recordsByPartition.get(partitionValueToDelete).size(),
           testIcebergTable.getNumRows());
-      InternalSnapshot internalSnapshot = icebergSourceClient.getCurrentSnapshot();
+      InternalSnapshot internalSnapshot = conversionSource.getCurrentSnapshot();
 
       validateIcebergPartitioning(internalSnapshot);
       validateSnapshot(internalSnapshot, allActiveFiles.get(allActiveFiles.size() - 1));
@@ -235,9 +238,9 @@ public class ITIcebergSourceClient {
               .lastSyncInstant(Instant.ofEpochMilli(timestamp1))
               .build();
       CommitsBacklog<Snapshot> commitsBacklog =
-          icebergSourceClient.getCommitsBacklog(instantsForIncrementalSync);
+          conversionSource.getCommitsBacklog(instantsForIncrementalSync);
       for (Snapshot snapshot : commitsBacklog.getCommitsToProcess()) {
-        TableChange tableChange = icebergSourceClient.getTableChangeForCommit(snapshot);
+        TableChange tableChange = conversionSource.getTableChangeForCommit(snapshot);
         allTableChanges.add(tableChange);
       }
       validateTableChanges(allActiveFiles, allTableChanges);
@@ -280,9 +283,10 @@ public class ITIcebergSourceClient {
               .tableBasePath(testIcebergTable.getBasePath())
               .targetTableFormats(Arrays.asList(TableFormat.HUDI, TableFormat.DELTA))
               .build();
-      IcebergSourceClient icebergSourceClient = clientProvider.getSourceClientInstance(tableConfig);
+      IcebergConversionSource conversionSource =
+          sourceProvider.getConversionSourceInstance(tableConfig);
       assertEquals(200L, testIcebergTable.getNumRows());
-      InternalSnapshot internalSnapshot = icebergSourceClient.getCurrentSnapshot();
+      InternalSnapshot internalSnapshot = conversionSource.getCurrentSnapshot();
 
       if (isPartitioned) {
         validateIcebergPartitioning(internalSnapshot);
@@ -294,9 +298,9 @@ public class ITIcebergSourceClient {
               .lastSyncInstant(Instant.ofEpochMilli(timestamp1))
               .build();
       CommitsBacklog<Snapshot> commitsBacklog =
-          icebergSourceClient.getCommitsBacklog(instantsForIncrementalSync);
+          conversionSource.getCommitsBacklog(instantsForIncrementalSync);
       for (Snapshot snapshot : commitsBacklog.getCommitsToProcess()) {
-        TableChange tableChange = icebergSourceClient.getTableChangeForCommit(snapshot);
+        TableChange tableChange = conversionSource.getTableChangeForCommit(snapshot);
         allTableChanges.add(tableChange);
       }
       validateTableChanges(allActiveFiles, allTableChanges);
@@ -333,16 +337,16 @@ public class ITIcebergSourceClient {
         // Expire snapshotAfterCommit2.
         testIcebergTable.expireSnapshot(snapshotIdAfterCommit2);
       }
-      IcebergSourceClient icebergSourceClient = clientProvider.getSourceClientInstance(tableConfig);
+      IcebergConversionSource conversionSource =
+          sourceProvider.getConversionSourceInstance(tableConfig);
       if (shouldExpireSnapshots) {
-        assertFalse(
-            icebergSourceClient.isIncrementalSyncSafeFrom(Instant.ofEpochMilli(timestamp1)));
+        assertFalse(conversionSource.isIncrementalSyncSafeFrom(Instant.ofEpochMilli(timestamp1)));
       } else {
-        assertTrue(icebergSourceClient.isIncrementalSyncSafeFrom(Instant.ofEpochMilli(timestamp1)));
+        assertTrue(conversionSource.isIncrementalSyncSafeFrom(Instant.ofEpochMilli(timestamp1)));
       }
       // Table doesn't have instant of this older commit, hence it is not safe.
       Instant instantAsOfHourAgo = Instant.now().minus(1, ChronoUnit.HOURS);
-      assertFalse(icebergSourceClient.isIncrementalSyncSafeFrom(instantAsOfHourAgo));
+      assertFalse(conversionSource.isIncrementalSyncSafeFrom(instantAsOfHourAgo));
     }
   }
 
diff --git a/core/src/test/java/org/apache/xtable/iceberg/TestIcebergSourceClient.java b/core/src/test/java/org/apache/xtable/iceberg/TestIcebergConversionTargetSource.java
similarity index 91%
rename from core/src/test/java/org/apache/xtable/iceberg/TestIcebergSourceClient.java
rename to core/src/test/java/org/apache/xtable/iceberg/TestIcebergConversionTargetSource.java
index bca730a8..010a524b 100644
--- a/core/src/test/java/org/apache/xtable/iceberg/TestIcebergSourceClient.java
+++ b/core/src/test/java/org/apache/xtable/iceberg/TestIcebergConversionTargetSource.java
@@ -49,8 +49,8 @@ import org.apache.iceberg.io.DataWriter;
 import org.apache.iceberg.parquet.Parquet;
 import org.apache.iceberg.types.Types;
 
-import org.apache.xtable.client.PerTableConfig;
-import org.apache.xtable.client.PerTableConfigImpl;
+import org.apache.xtable.conversion.PerTableConfig;
+import org.apache.xtable.conversion.PerTableConfigImpl;
 import org.apache.xtable.model.CommitsBacklog;
 import org.apache.xtable.model.InstantsForIncrementalSync;
 import org.apache.xtable.model.InternalSnapshot;
@@ -66,12 +66,12 @@ import org.apache.xtable.model.storage.*;
 import org.apache.xtable.model.storage.FileFormat;
 import org.apache.xtable.model.storage.InternalDataFile;
 
-class TestIcebergSourceClient {
+class TestIcebergConversionTargetSource {
 
   private IcebergTableManager tableManager;
   private Schema csSchema;
   private PartitionSpec csPartitionSpec;
-  private IcebergSourceClientProvider clientProvider;
+  private IcebergConversionSourceProvider sourceProvider;
   private Configuration hadoopConf;
 
   @BeforeEach
@@ -79,8 +79,8 @@ class TestIcebergSourceClient {
     hadoopConf = new Configuration();
     hadoopConf.set("fs.defaultFS", "file:///");
 
-    clientProvider = new IcebergSourceClientProvider();
-    clientProvider.init(hadoopConf, null);
+    sourceProvider = new IcebergConversionSourceProvider();
+    sourceProvider.init(hadoopConf, null);
 
     tableManager = IcebergTableManager.of(hadoopConf);
 
@@ -96,10 +96,11 @@ class TestIcebergSourceClient {
     Table catalogSales = createTestTableWithData(workingDir.toString());
     PerTableConfig sourceTableConfig = getPerTableConfig(catalogSales);
 
-    IcebergSourceClient client = clientProvider.getSourceClientInstance(sourceTableConfig);
+    IcebergConversionSource conversionSource =
+        sourceProvider.getConversionSourceInstance(sourceTableConfig);
 
     Snapshot snapshot = catalogSales.currentSnapshot();
-    InternalTable internalTable = client.getTable(snapshot);
+    InternalTable internalTable = conversionSource.getTable(snapshot);
     Assertions.assertNotNull(internalTable);
     assertEquals(TableFormat.ICEBERG, internalTable.getTableFormat());
     Assertions.assertTrue(internalTable.getName().endsWith("catalog_sales"));
@@ -132,10 +133,11 @@ class TestIcebergSourceClient {
 
     PerTableConfig sourceTableConfig = getPerTableConfig(catalogSales);
 
-    IcebergSourceClient client = clientProvider.getSourceClientInstance(sourceTableConfig);
-    IcebergSourceClient spyClient = Mockito.spy(client);
+    IcebergConversionSource conversionSource =
+        sourceProvider.getConversionSourceInstance(sourceTableConfig);
+    IcebergConversionSource spyConversionSource = Mockito.spy(conversionSource);
 
-    SchemaCatalog schemaCatalog = spyClient.getSchemaCatalog(null, iceCurrentSnapshot);
+    SchemaCatalog schemaCatalog = spyConversionSource.getSchemaCatalog(null, iceCurrentSnapshot);
     Assertions.assertNotNull(schemaCatalog);
     Map<SchemaVersion, InternalSchema> schemas = schemaCatalog.getSchemas();
     assertEquals(1, schemas.size());
@@ -156,21 +158,22 @@ class TestIcebergSourceClient {
     IcebergPartitionValueConverter spyPartitionConverter =
         spy(IcebergPartitionValueConverter.getInstance());
 
-    IcebergSourceClient spyClient =
+    IcebergConversionSource spyConversionSource =
         spy(
-            IcebergSourceClient.builder()
+            IcebergConversionSource.builder()
                 .hadoopConf(hadoopConf)
                 .sourceTableConfig(sourceTableConfig)
                 .dataFileExtractor(spyDataFileExtractor)
                 .partitionConverter(spyPartitionConverter)
                 .build());
 
-    InternalSnapshot internalSnapshot = spyClient.getCurrentSnapshot();
+    InternalSnapshot internalSnapshot = spyConversionSource.getCurrentSnapshot();
     Assertions.assertNotNull(internalSnapshot);
     assertEquals(String.valueOf(iceCurrentSnapshot.snapshotId()), internalSnapshot.getVersion());
     Assertions.assertNotNull(internalSnapshot.getTable());
-    verify(spyClient, times(1)).getTable(iceCurrentSnapshot);
-    verify(spyClient, times(1)).getSchemaCatalog(internalSnapshot.getTable(), iceCurrentSnapshot);
+    verify(spyConversionSource, times(1)).getTable(iceCurrentSnapshot);
+    verify(spyConversionSource, times(1))
+        .getSchemaCatalog(internalSnapshot.getTable(), iceCurrentSnapshot);
     verify(spyPartitionConverter, times(5)).toOneTable(any(), any(), any());
     verify(spyDataFileExtractor, times(5)).fromIceberg(any(), any(), any());
 
@@ -328,8 +331,8 @@ class TestIcebergSourceClient {
         InstantsForIncrementalSync.builder()
             .lastSyncInstant(Instant.ofEpochMilli(lastSync.timestampMillis()))
             .build();
-    IcebergSourceClient sourceClient = getIcebergSourceClient(table);
-    CommitsBacklog<Snapshot> commitsBacklog = sourceClient.getCommitsBacklog(instant);
+    IcebergConversionSource conversionSource = getIcebergConversionSource(table);
+    CommitsBacklog<Snapshot> commitsBacklog = conversionSource.getCommitsBacklog(instant);
     assertEquals(0, commitsBacklog.getInFlightInstants().size());
     Assertions.assertArrayEquals(snapshots, commitsBacklog.getCommitsToProcess().toArray());
   }
@@ -342,8 +345,8 @@ class TestIcebergSourceClient {
 
   private void validateTableChangeDiffSize(
       Table table, Snapshot snapshot, int addedFiles, int removedFiles) {
-    IcebergSourceClient sourceClient = getIcebergSourceClient(table);
-    TableChange tableChange = sourceClient.getTableChangeForCommit(snapshot);
+    IcebergConversionSource conversionSource = getIcebergConversionSource(table);
+    TableChange tableChange = conversionSource.getTableChangeForCommit(snapshot);
     assertEquals(addedFiles, tableChange.getFilesDiff().getFilesAdded().size());
     assertEquals(removedFiles, tableChange.getFilesDiff().getFilesRemoved().size());
   }
@@ -411,10 +414,10 @@ class TestIcebergSourceClient {
     return tableManager.getOrCreateTable(null, null, csPath, csSchema, csPartitionSpec);
   }
 
-  private IcebergSourceClient getIcebergSourceClient(Table catalogSales) {
+  private IcebergConversionSource getIcebergConversionSource(Table catalogSales) {
     PerTableConfig tableConfig = getPerTableConfig(catalogSales);
 
-    return IcebergSourceClient.builder()
+    return IcebergConversionSource.builder()
         .hadoopConf(hadoopConf)
         .sourceTableConfig(tableConfig)
         .build();
diff --git a/core/src/test/java/org/apache/xtable/iceberg/TestIcebergSync.java b/core/src/test/java/org/apache/xtable/iceberg/TestIcebergSync.java
index df24495d..f676f8a9 100644
--- a/core/src/test/java/org/apache/xtable/iceberg/TestIcebergSync.java
+++ b/core/src/test/java/org/apache/xtable/iceberg/TestIcebergSync.java
@@ -81,8 +81,8 @@ import org.apache.iceberg.types.Types;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Sets;
 
-import org.apache.xtable.ITOneTableClient;
-import org.apache.xtable.client.PerTableConfigImpl;
+import org.apache.xtable.ITConversionController;
+import org.apache.xtable.conversion.PerTableConfigImpl;
 import org.apache.xtable.model.InternalSnapshot;
 import org.apache.xtable.model.InternalTable;
 import org.apache.xtable.model.TableSyncMetadata;
@@ -104,8 +104,8 @@ import org.apache.xtable.schema.SchemaFieldFinder;
 import org.apache.xtable.spi.sync.TableFormatSync;
 
 /**
- * Validates that the metadata for the table is properly created/updated. {@link ITOneTableClient}
- * validates that the table and its data can be properly read.
+ * Validates that the metadata for the table is properly created/updated. {@link
+ * ITConversionController} validates that the table and its data can be properly read.
  */
 public class TestIcebergSync {
   private static final Random RANDOM = new Random();
@@ -123,7 +123,7 @@ public class TestIcebergSync {
       Mockito.mock(IcebergPartitionSpecSync.class);
   private final IcebergColumnStatsConverter mockColumnStatsConverter =
       Mockito.mock(IcebergColumnStatsConverter.class);
-  private IcebergClient icebergClient;
+  private IcebergConversionTarget conversionTarget;
 
   private final InternalSchema internalSchema =
       InternalSchema.builder()
@@ -187,11 +187,11 @@ public class TestIcebergSync {
     tableName = "test-" + UUID.randomUUID();
     basePath = tempDir.resolve(tableName);
     Files.createDirectories(basePath);
-    icebergClient = getIcebergClient();
+    conversionTarget = getConversionTarget();
   }
 
-  private IcebergClient getIcebergClient() {
-    return new IcebergClient(
+  private IcebergConversionTarget getConversionTarget() {
+    return new IcebergConversionTarget(
         PerTableConfigImpl.builder()
             .tableBasePath(basePath.toString())
             .tableName(tableName)
@@ -247,10 +247,12 @@ public class TestIcebergSync {
     mockColStatsForFile(dataFile2, 2);
     mockColStatsForFile(dataFile3, 1);
 
-    TableFormatSync.getInstance().syncSnapshot(Collections.singletonList(icebergClient), snapshot1);
+    TableFormatSync.getInstance()
+        .syncSnapshot(Collections.singletonList(conversionTarget), snapshot1);
     validateIcebergTable(tableName, table1, Sets.newHashSet(dataFile1, dataFile2), null);
 
-    TableFormatSync.getInstance().syncSnapshot(Collections.singletonList(icebergClient), snapshot2);
+    TableFormatSync.getInstance()
+        .syncSnapshot(Collections.singletonList(conversionTarget), snapshot2);
     validateIcebergTable(tableName, table2, Sets.newHashSet(dataFile2, dataFile3), null);
 
     ArgumentCaptor<Transaction> transactionArgumentCaptor =
@@ -346,9 +348,11 @@ public class TestIcebergSync {
     mockColStatsForFile(dataFile3, 2);
     mockColStatsForFile(dataFile4, 1);
 
-    TableFormatSync.getInstance().syncSnapshot(Collections.singletonList(icebergClient), snapshot1);
+    TableFormatSync.getInstance()
+        .syncSnapshot(Collections.singletonList(conversionTarget), snapshot1);
     long snapshotIdBeforeCorruption = getTable(basePath).currentSnapshot().snapshotId();
-    TableFormatSync.getInstance().syncSnapshot(Collections.singletonList(icebergClient), snapshot2);
+    TableFormatSync.getInstance()
+        .syncSnapshot(Collections.singletonList(conversionTarget), snapshot2);
     String manifestFile =
         new HadoopTables(CONFIGURATION)
             .load(basePath.toString())
@@ -357,11 +361,12 @@ public class TestIcebergSync {
     Files.delete(Paths.get(URI.create(manifestFile)));
 
     Optional<Instant> actual =
-        getIcebergClient().getTableMetadata().map(TableSyncMetadata::getLastInstantSynced);
+        getConversionTarget().getTableMetadata().map(TableSyncMetadata::getLastInstantSynced);
     // assert that the last commit is rolled back and the metadata is removed
     assertFalse(actual.isPresent());
     // get a new iceberg sync to make sure table is re-read from disk and no metadata is cached
-    TableFormatSync.getInstance().syncSnapshot(Collections.singletonList(icebergClient), snapshot3);
+    TableFormatSync.getInstance()
+        .syncSnapshot(Collections.singletonList(conversionTarget), snapshot3);
     validateIcebergTable(tableName, table2, Sets.newHashSet(dataFile3, dataFile4), null);
     // Validate Iceberg table state
     Table table = getTable(basePath);
@@ -421,7 +426,8 @@ public class TestIcebergSync {
     mockColStatsForFile(dataFile1, 1);
     mockColStatsForFile(dataFile2, 1);
     mockColStatsForFile(dataFile3, 1);
-    TableFormatSync.getInstance().syncSnapshot(Collections.singletonList(icebergClient), snapshot);
+    TableFormatSync.getInstance()
+        .syncSnapshot(Collections.singletonList(conversionTarget), snapshot);
 
     assertTrue(schemaArgumentCaptor.getValue().sameSchema(icebergSchema));
     validateIcebergTable(
@@ -484,7 +490,8 @@ public class TestIcebergSync {
     mockColStatsForFile(dataFile1, 1);
     mockColStatsForFile(dataFile2, 1);
     mockColStatsForFile(dataFile3, 1);
-    TableFormatSync.getInstance().syncSnapshot(Collections.singletonList(icebergClient), snapshot);
+    TableFormatSync.getInstance()
+        .syncSnapshot(Collections.singletonList(conversionTarget), snapshot);
 
     assertTrue(schemaArgumentCaptor.getValue().sameSchema(icebergSchema));
     validateIcebergTable(
@@ -540,7 +547,8 @@ public class TestIcebergSync {
     mockColStatsForFile(dataFile1, 1);
     mockColStatsForFile(dataFile2, 1);
     mockColStatsForFile(dataFile3, 1);
-    TableFormatSync.getInstance().syncSnapshot(Collections.singletonList(icebergClient), snapshot);
+    TableFormatSync.getInstance()
+        .syncSnapshot(Collections.singletonList(conversionTarget), snapshot);
 
     assertTrue(schemaArgumentCaptor.getValue().sameSchema(icebergSchema));
     validateIcebergTable(
@@ -618,7 +626,8 @@ public class TestIcebergSync {
     mockColStatsForFile(dataFile1, 1);
     mockColStatsForFile(dataFile2, 1);
     mockColStatsForFile(dataFile3, 1);
-    TableFormatSync.getInstance().syncSnapshot(Collections.singletonList(icebergClient), snapshot);
+    TableFormatSync.getInstance()
+        .syncSnapshot(Collections.singletonList(conversionTarget), snapshot);
 
     assertTrue(schemaArgumentCaptor.getValue().sameSchema(icebergSchema));
     validateIcebergTable(
@@ -685,7 +694,8 @@ public class TestIcebergSync {
     mockColStatsForFile(dataFile1, 1);
     mockColStatsForFile(dataFile2, 1);
     mockColStatsForFile(dataFile3, 1);
-    TableFormatSync.getInstance().syncSnapshot(Collections.singletonList(icebergClient), snapshot);
+    TableFormatSync.getInstance()
+        .syncSnapshot(Collections.singletonList(conversionTarget), snapshot);
 
     assertTrue(schemaArgumentCaptor.getValue().sameSchema(icebergSchema));
     validateIcebergTable(
diff --git a/core/src/test/java/org/apache/xtable/loadtest/LoadTest.java b/core/src/test/java/org/apache/xtable/loadtest/LoadTest.java
index a5020fff..8b1a24e0 100644
--- a/core/src/test/java/org/apache/xtable/loadtest/LoadTest.java
+++ b/core/src/test/java/org/apache/xtable/loadtest/LoadTest.java
@@ -35,11 +35,11 @@ import org.apache.hudi.common.table.timeline.HoodieInstant;
 import org.apache.hudi.config.HoodieArchivalConfig;
 
 import org.apache.xtable.TestJavaHudiTable;
-import org.apache.xtable.client.OneTableClient;
-import org.apache.xtable.client.PerTableConfig;
-import org.apache.xtable.client.PerTableConfigImpl;
-import org.apache.xtable.client.SourceClientProvider;
-import org.apache.xtable.hudi.HudiSourceClientProvider;
+import org.apache.xtable.conversion.ConversionController;
+import org.apache.xtable.conversion.ConversionSourceProvider;
+import org.apache.xtable.conversion.PerTableConfig;
+import org.apache.xtable.conversion.PerTableConfigImpl;
+import org.apache.xtable.hudi.HudiConversionSourceProvider;
 import org.apache.xtable.model.storage.TableFormat;
 import org.apache.xtable.model.sync.SyncMode;
 
@@ -51,12 +51,12 @@ import org.apache.xtable.model.sync.SyncMode;
 public class LoadTest {
   @TempDir public static Path tempDir;
   private static final Configuration CONFIGURATION = new Configuration();
-  private SourceClientProvider<HoodieInstant> hudiSourceClientProvider;
+  private ConversionSourceProvider<HoodieInstant> hudiConversionSourceProvider;
 
   @BeforeEach
   public void setup() {
-    hudiSourceClientProvider = new HudiSourceClientProvider();
-    hudiSourceClientProvider.init(CONFIGURATION, Collections.emptyMap());
+    hudiConversionSourceProvider = new HudiConversionSourceProvider();
+    hudiConversionSourceProvider.init(CONFIGURATION, Collections.emptyMap());
   }
 
   @Test
@@ -82,9 +82,9 @@ public class LoadTest {
               .tableBasePath(table.getBasePath())
               .syncMode(SyncMode.FULL)
               .build();
-      OneTableClient oneTableClient = new OneTableClient(CONFIGURATION);
+      ConversionController conversionController = new ConversionController(CONFIGURATION);
       long start = System.currentTimeMillis();
-      oneTableClient.sync(perTableConfig, hudiSourceClientProvider);
+      conversionController.sync(perTableConfig, hudiConversionSourceProvider);
       long end = System.currentTimeMillis();
       System.out.println("Full sync took " + (end - start) + "ms");
     }
@@ -112,8 +112,8 @@ public class LoadTest {
               .syncMode(SyncMode.INCREMENTAL)
               .build();
       // sync once to establish first commit
-      OneTableClient oneTableClient = new OneTableClient(CONFIGURATION);
-      oneTableClient.sync(perTableConfig, hudiSourceClientProvider);
+      ConversionController conversionController = new ConversionController(CONFIGURATION);
+      conversionController.sync(perTableConfig, hudiConversionSourceProvider);
       for (int i = 0; i < numCommits; i++) {
         table.insertRecords(
             1,
@@ -124,7 +124,7 @@ public class LoadTest {
       }
 
       long start = System.currentTimeMillis();
-      oneTableClient.sync(perTableConfig, hudiSourceClientProvider);
+      conversionController.sync(perTableConfig, hudiConversionSourceProvider);
       long end = System.currentTimeMillis();
       System.out.println("Incremental sync took " + (end - start) + "ms");
     }
diff --git a/demo/notebook/demo.ipynb b/demo/notebook/demo.ipynb
index f7379365..244c52b4 100644
--- a/demo/notebook/demo.ipynb
+++ b/demo/notebook/demo.ipynb
@@ -33,7 +33,7 @@
     "import $ivy.`org.apache.iceberg:iceberg-hive-runtime:1.3.1`\n",
     "import $ivy.`io.trino:trino-jdbc:431`\n",
     "import java.util._\n",
-    "import org.apache.xtable.client._\n",
+    "import org.apache.xtable.conversion._\n",
     "import org.apache.xtable.model.sync._\n",
     "import org.apache.xtable.model.storage._\n",
     "import org.apache.xtable.hudi._\n",
@@ -128,10 +128,10 @@
     "    .icebergCatalogConfig(icebergCatalogConfig)\n",
     "    .syncMode(SyncMode.INCREMENTAL)\n",
     "    .build()\n",
-    "val hudiSourceClientProvider = new HudiSourceClientProvider()\n",
-    "hudiSourceClientProvider.init(spark.sparkContext.hadoopConfiguration, Collections.emptyMap())\n",
-    "val oneTableClient = new OneTableClient(spark.sparkContext.hadoopConfiguration)\n",
-    "oneTableClient.sync(perTableConfig, hudiSourceClientProvider)"
+    "val hudiConversionSourceProvider = new HudiConversionSourceProvider()\n",
+    "hudiConversionSourceProvider.init(spark.sparkContext.hadoopConfiguration, Collections.emptyMap())\n",
+    "val conversionController = new ConversionController(spark.sparkContext.hadoopConfiguration)\n",
+    "conversionController.sync(perTableConfig, hudiConversionSourceProvider)"
    ]
   },
   {
@@ -162,7 +162,7 @@
     "    .options(hudiWriteOptions)\n",
     "    .mode(\"append\")\n",
     "    .save(hudiBasePath)\n",
-    "oneTableClient.sync(perTableConfig, hudiSourceClientProvider)"
+    "conversionController.sync(perTableConfig, hudiConversionSourceProvider)"
    ]
   },
   {
@@ -207,8 +207,8 @@
    "metadata": {},
    "outputs": [],
    "source": [
-    "val icebergSourceClientProvider = new IcebergSourceClientProvider()\n",
-    "icebergSourceClientProvider.init(spark.sparkContext.hadoopConfiguration, Collections.emptyMap())\n",
+    "val icebergConversionSourceProvider = new IcebergConversionSourceProvider()\n",
+    "icebergConversionSourceProvider.init(spark.sparkContext.hadoopConfiguration, Collections.emptyMap())\n",
     "val icebergSourcePerTableConfig = PerTableConfigImpl.builder()\n",
     "    .tableName(hudiTableName)\n",
     "    .namespace(namespaceArray)\n",
@@ -217,7 +217,7 @@
     "    .icebergCatalogConfig(icebergCatalogConfig)\n",
     "    .syncMode(SyncMode.INCREMENTAL)\n",
     "    .build()\n",
-    "oneTableClient.sync(icebergSourcePerTableConfig, icebergSourceClientProvider)"
+    "conversionController.sync(icebergSourcePerTableConfig, icebergConversionSourceProvider)"
    ]
   },
   {
@@ -240,15 +240,15 @@
    "source": [
     "// Sync from a Delta Lake table to Hudi\n",
     "import org.apache.xtable.delta._\n",
-    "val deltaSourceClientProvider = new DeltaSourceClientProvider()\n",
-    "deltaSourceClientProvider.init(spark.sparkContext.hadoopConfiguration, Collections.emptyMap())\n",
+    "val deltaConversionSourceProvider = new DeltaConversionSourceProvider()\n",
+    "deltaConversionSourceProvider.init(spark.sparkContext.hadoopConfiguration, Collections.emptyMap())\n",
     "val deltaSourcePerTableConfig = PerTableConfigImpl.builder()\n",
     "    .tableName(deltaTableName)\n",
     "    .targetTableFormats(Arrays.asList(TableFormat.HUDI))\n",
     "    .tableBasePath(deltaBasePath)\n",
     "    .syncMode(SyncMode.INCREMENTAL)\n",
     "    .build()\n",
-    "oneTableClient.sync(deltaSourcePerTableConfig, deltaSourceClientProvider)"
+    "conversionController.sync(deltaSourcePerTableConfig, deltaConversionSourceProvider)"
    ]
   },
   {
@@ -302,10 +302,10 @@
     "    .icebergCatalogConfig(icebergCatalogConfig)\n",
     "    .syncMode(SyncMode.INCREMENTAL)\n",
     "    .build()\n",
-    "val deltaSourceClientProvider = new DeltaSourceClientProvider()\n",
-    "deltaSourceClientProvider.init(spark.sparkContext.hadoopConfiguration, Collections.emptyMap())\n",
-    "val oneTableClient = new OneTableClient(spark.sparkContext.hadoopConfiguration)\n",
-    "oneTableClient.sync(perTableConfig, deltaSourceClientProvider)"
+    "val deltaConversionSourceProvider = new DeltaConversionSourceProvider()\n",
+    "deltaConversionSourceProvider.init(spark.sparkContext.hadoopConfiguration, Collections.emptyMap())\n",
+    "val conversionController = new ConversionController(spark.sparkContext.hadoopConfiguration)\n",
+    "conversionController.sync(perTableConfig, deltaConversionSourceProvider)"
    ]
   },
   {
diff --git a/hudi-support/extensions/README.md b/hudi-support/extensions/README.md
index 51ea57b6..26782ed1 100644
--- a/hudi-support/extensions/README.md
+++ b/hudi-support/extensions/README.md
@@ -16,7 +16,7 @@ For example, if you're using the Hudi [quick-start guide](https://hudi.apache.or
 If you want to use OneTable with Hudi [streaming ingestion](https://hudi.apache.org/docs/hoodie_streaming_ingestion) to sync each commit into other table formats.
 ### How do you use them?
 1. Add the extensions jar (`hudi-extensions-0.1.0-SNAPSHOT-bundled.jar`) to your class path.
-2. Add `org.apache.xtable.hudi.sync.OneTableSyncTool` to your list of sync classes
+2. Add `org.apache.xtable.hudi.sync.XTableSyncTool` to your list of sync classes
 3. Set the following configurations based on your preferences:
    `hoodie.onetable.formats: "ICEBERG,DELTA"` (or simply use one format)
    `hoodie.onetable.target.metadata.retention.hr: 168` (default retention for target format metadata is 168 hours)
\ No newline at end of file
diff --git a/hudi-support/extensions/src/main/java/org/apache/xtable/hudi/sync/OneTableSyncConfig.java b/hudi-support/extensions/src/main/java/org/apache/xtable/hudi/sync/XTableSyncConfig.java
similarity index 92%
rename from hudi-support/extensions/src/main/java/org/apache/xtable/hudi/sync/OneTableSyncConfig.java
rename to hudi-support/extensions/src/main/java/org/apache/xtable/hudi/sync/XTableSyncConfig.java
index fe716ad4..c4e6a600 100644
--- a/hudi-support/extensions/src/main/java/org/apache/xtable/hudi/sync/OneTableSyncConfig.java
+++ b/hudi-support/extensions/src/main/java/org/apache/xtable/hudi/sync/XTableSyncConfig.java
@@ -24,7 +24,7 @@ import java.util.Properties;
 import org.apache.hudi.common.config.ConfigProperty;
 import org.apache.hudi.sync.common.HoodieSyncConfig;
 
-public class OneTableSyncConfig extends HoodieSyncConfig implements Serializable {
+public class XTableSyncConfig extends HoodieSyncConfig implements Serializable {
 
   public static final ConfigProperty<String> ONE_TABLE_FORMATS =
       ConfigProperty.key("hoodie.onetable.formats.to.sync")
@@ -36,7 +36,7 @@ public class OneTableSyncConfig extends HoodieSyncConfig implements Serializable
           .defaultValue(24 * 7)
           .withDocumentation("Retention in hours for metadata in target table.");
 
-  public OneTableSyncConfig(Properties props) {
+  public XTableSyncConfig(Properties props) {
     super(props);
   }
 }
diff --git a/hudi-support/extensions/src/main/java/org/apache/xtable/hudi/sync/OneTableSyncTool.java b/hudi-support/extensions/src/main/java/org/apache/xtable/hudi/sync/XTableSyncTool.java
similarity index 83%
rename from hudi-support/extensions/src/main/java/org/apache/xtable/hudi/sync/OneTableSyncTool.java
rename to hudi-support/extensions/src/main/java/org/apache/xtable/hudi/sync/XTableSyncTool.java
index b84171b1..49a7a743 100644
--- a/hudi-support/extensions/src/main/java/org/apache/xtable/hudi/sync/OneTableSyncTool.java
+++ b/hudi-support/extensions/src/main/java/org/apache/xtable/hudi/sync/XTableSyncTool.java
@@ -34,10 +34,10 @@ import org.apache.hudi.keygen.constant.KeyGeneratorOptions;
 import org.apache.hudi.sync.common.HoodieSyncConfig;
 import org.apache.hudi.sync.common.HoodieSyncTool;
 
-import org.apache.xtable.client.OneTableClient;
-import org.apache.xtable.client.PerTableConfig;
-import org.apache.xtable.client.PerTableConfigImpl;
-import org.apache.xtable.hudi.HudiSourceClientProvider;
+import org.apache.xtable.conversion.ConversionController;
+import org.apache.xtable.conversion.PerTableConfig;
+import org.apache.xtable.conversion.PerTableConfigImpl;
+import org.apache.xtable.hudi.HudiConversionSourceProvider;
 import org.apache.xtable.hudi.HudiSourceConfigImpl;
 import org.apache.xtable.model.schema.PartitionTransformType;
 import org.apache.xtable.model.sync.SyncMode;
@@ -47,21 +47,21 @@ import org.apache.xtable.model.sync.SyncResult;
  * A HoodieSyncTool for syncing a Hudi table to other formats (Delta and Iceberg) with
  * InternalTable.
  */
-public class OneTableSyncTool extends HoodieSyncTool {
-  private final OneTableSyncConfig config;
-  private final HudiSourceClientProvider hudiSourceClientProvider;
+public class XTableSyncTool extends HoodieSyncTool {
+  private final XTableSyncConfig config;
+  private final HudiConversionSourceProvider hudiConversionSourceProvider;
 
-  public OneTableSyncTool(Properties props, Configuration hadoopConf) {
+  public XTableSyncTool(Properties props, Configuration hadoopConf) {
     super(props, hadoopConf);
-    this.config = new OneTableSyncConfig(props);
-    this.hudiSourceClientProvider = new HudiSourceClientProvider();
-    hudiSourceClientProvider.init(hadoopConf, Collections.emptyMap());
+    this.config = new XTableSyncConfig(props);
+    this.hudiConversionSourceProvider = new HudiConversionSourceProvider();
+    hudiConversionSourceProvider.init(hadoopConf, Collections.emptyMap());
   }
 
   @Override
   public void syncHoodieTable() {
     List<String> formatsToSync =
-        Arrays.stream(config.getString(OneTableSyncConfig.ONE_TABLE_FORMATS).split(","))
+        Arrays.stream(config.getString(XTableSyncConfig.ONE_TABLE_FORMATS).split(","))
             .map(format -> format.toUpperCase())
             .collect(Collectors.toList());
     String basePath = config.getString(HoodieSyncConfig.META_SYNC_BASE_PATH);
@@ -77,10 +77,10 @@ public class OneTableSyncTool extends HoodieSyncTool {
                     .build())
             .syncMode(SyncMode.INCREMENTAL)
             .targetMetadataRetentionInHours(
-                config.getInt(OneTableSyncConfig.ONE_TABLE_TARGET_METADATA_RETENTION_HOURS))
+                config.getInt(XTableSyncConfig.ONE_TABLE_TARGET_METADATA_RETENTION_HOURS))
             .build();
     Map<String, SyncResult> results =
-        new OneTableClient(hadoopConf).sync(perTableConfig, hudiSourceClientProvider);
+        new ConversionController(hadoopConf).sync(perTableConfig, hudiConversionSourceProvider);
     String failingFormats =
         results.entrySet().stream()
             .filter(
diff --git a/hudi-support/extensions/src/test/java/org/apache/xtable/hudi/sync/TestOneTableSyncTool.java b/hudi-support/extensions/src/test/java/org/apache/xtable/hudi/sync/TestXTableSyncTool.java
similarity index 95%
rename from hudi-support/extensions/src/test/java/org/apache/xtable/hudi/sync/TestOneTableSyncTool.java
rename to hudi-support/extensions/src/test/java/org/apache/xtable/hudi/sync/TestXTableSyncTool.java
index 7c4fac61..d44465c8 100644
--- a/hudi-support/extensions/src/test/java/org/apache/xtable/hudi/sync/TestOneTableSyncTool.java
+++ b/hudi-support/extensions/src/test/java/org/apache/xtable/hudi/sync/TestXTableSyncTool.java
@@ -52,7 +52,7 @@ import org.apache.hudi.DataSourceWriteOptions;
 import org.apache.hudi.keygen.constant.KeyGeneratorOptions;
 import org.apache.hudi.sync.common.HoodieSyncConfig;
 
-public class TestOneTableSyncTool {
+public class TestXTableSyncTool {
   private static SparkSession spark;
   @TempDir static Path tempDir;
 
@@ -68,7 +68,7 @@ public class TestOneTableSyncTool {
   public static void initSpark() {
     SparkConf sparkConf =
         new SparkConf()
-            .setAppName("onetableclient")
+            .setAppName("xtable")
             .set("spark.serializer", KryoSerializer.class.getName())
             .set("spark.databricks.delta.constraints.allowUnenforcedNotNull.enabled", "true")
             .set("spark.sql.shuffle.partitions", "1")
@@ -98,12 +98,12 @@ public class TestOneTableSyncTool {
     writeBasicHudiTable(path, options);
 
     Properties properties = new Properties();
-    properties.put(OneTableSyncConfig.ONE_TABLE_FORMATS.key(), "iceberg,DELTA");
+    properties.put(XTableSyncConfig.ONE_TABLE_FORMATS.key(), "iceberg,DELTA");
     properties.put(KeyGeneratorOptions.PARTITIONPATH_FIELD_NAME.key(), partitionPath);
     properties.put(HoodieSyncConfig.META_SYNC_BASE_PATH.key(), path);
     properties.putAll(options);
 
-    new OneTableSyncTool(properties, new Configuration()).syncHoodieTable();
+    new XTableSyncTool(properties, new Configuration()).syncHoodieTable();
     // lightweight check to make sure metadata dirs are made - assumes that InternalTable sync is
     // correct if it succeeds
     assertTrue(Files.exists(Paths.get(URI.create(path + "/_delta_log"))));
diff --git a/utilities/src/main/java/org/apache/xtable/utilities/RunSync.java b/utilities/src/main/java/org/apache/xtable/utilities/RunSync.java
index 9741a0b4..09ce2c2b 100644
--- a/utilities/src/main/java/org/apache/xtable/utilities/RunSync.java
+++ b/utilities/src/main/java/org/apache/xtable/utilities/RunSync.java
@@ -44,17 +44,17 @@ import com.fasterxml.jackson.databind.ObjectReader;
 import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
 import com.google.common.annotations.VisibleForTesting;
 
-import org.apache.xtable.client.OneTableClient;
-import org.apache.xtable.client.PerTableConfig;
-import org.apache.xtable.client.PerTableConfigImpl;
-import org.apache.xtable.client.SourceClientProvider;
+import org.apache.xtable.conversion.ConversionController;
+import org.apache.xtable.conversion.ConversionSourceProvider;
+import org.apache.xtable.conversion.PerTableConfig;
+import org.apache.xtable.conversion.PerTableConfigImpl;
 import org.apache.xtable.hudi.ConfigurationBasedPartitionSpecExtractor;
 import org.apache.xtable.hudi.HudiSourceConfigImpl;
 import org.apache.xtable.iceberg.IcebergCatalogConfig;
 import org.apache.xtable.model.storage.TableFormat;
 import org.apache.xtable.model.sync.SyncMode;
 import org.apache.xtable.reflection.ReflectionUtils;
-import org.apache.xtable.utilities.RunSync.TableFormatClients.ClientConfig;
+import org.apache.xtable.utilities.RunSync.TableFormatConverters.ConversionConfig;
 
 /**
  * Provides a standalone runner for the sync process. See README.md for more details on how to run
@@ -66,7 +66,7 @@ public class RunSync {
   public static final ObjectMapper YAML_MAPPER = new ObjectMapper(new YAMLFactory());
   private static final String DATASET_CONFIG_OPTION = "d";
   private static final String HADOOP_CONFIG_PATH = "p";
-  private static final String CLIENTS_CONFIG_PATH = "c";
+  private static final String CONVERTERS_CONFIG_PATH = "c";
   private static final String ICEBERG_CATALOG_CONFIG_PATH = "i";
   private static final String HELP_OPTION = "h";
 
@@ -84,10 +84,10 @@ public class RunSync {
               "Hadoop config xml file path containing configs necessary to access the "
                   + "file system. These configs will override the default configs.")
           .addOption(
-              CLIENTS_CONFIG_PATH,
-              "clientsConfig",
+              CONVERTERS_CONFIG_PATH,
+              "convertersConfig",
               true,
-              "The path to a yaml file containing InternalTable client configurations. "
+              "The path to a yaml file containing InternalTable converter configurations. "
                   + "These configs will override the default")
           .addOption(
               ICEBERG_CATALOG_CONFIG_PATH,
@@ -127,22 +127,23 @@ public class RunSync {
     IcebergCatalogConfig icebergCatalogConfig = loadIcebergCatalogConfig(icebergCatalogConfigInput);
 
     String sourceFormat = datasetConfig.sourceFormat;
-    customConfig = getCustomConfigurations(cmd, CLIENTS_CONFIG_PATH);
-    TableFormatClients tableFormatClients = loadTableFormatClientConfigs(customConfig);
-    ClientConfig sourceClientConfig = tableFormatClients.getTableFormatsClients().get(sourceFormat);
-    if (sourceClientConfig == null) {
+    customConfig = getCustomConfigurations(cmd, CONVERTERS_CONFIG_PATH);
+    TableFormatConverters tableFormatConverters = loadTableFormatConversionConfigs(customConfig);
+    ConversionConfig sourceConversionConfig =
+        tableFormatConverters.getTableFormatConverters().get(sourceFormat);
+    if (sourceConversionConfig == null) {
       throw new IllegalArgumentException(
           String.format(
               "Source format %s is not supported. Known source and target formats are %s",
-              sourceFormat, tableFormatClients.getTableFormatsClients().keySet()));
+              sourceFormat, tableFormatConverters.getTableFormatConverters().keySet()));
     }
-    String sourceProviderClass = sourceClientConfig.sourceClientProviderClass;
-    SourceClientProvider<?> sourceClientProvider =
+    String sourceProviderClass = sourceConversionConfig.conversionSourceProviderClass;
+    ConversionSourceProvider<?> conversionSourceProvider =
         ReflectionUtils.createInstanceOfClass(sourceProviderClass);
-    sourceClientProvider.init(hadoopConf, sourceClientConfig.configuration);
+    conversionSourceProvider.init(hadoopConf, sourceConversionConfig.configuration);
 
     List<String> tableFormatList = datasetConfig.getTargetFormats();
-    OneTableClient client = new OneTableClient(hadoopConf);
+    ConversionController conversionController = new ConversionController(hadoopConf);
     for (DatasetConfig.Table table : datasetConfig.getDatasets()) {
       log.info(
           "Running sync for basePath {} for following table formats {}",
@@ -165,7 +166,7 @@ public class RunSync {
               .syncMode(SyncMode.INCREMENTAL)
               .build();
       try {
-        client.sync(config, sourceClientProvider);
+        conversionController.sync(config, conversionSourceProvider);
       } catch (Exception e) {
         log.error(String.format("Error running sync for %s", table.getTableBasePath()), e);
       }
@@ -191,22 +192,24 @@ public class RunSync {
   }
 
   /**
-   * Loads the client configs. The method first loads the default configs and then merges any custom
-   * configs provided by the user.
+   * Loads the conversion configs. The method first loads the default configs and then merges any
+   * custom configs provided by the user.
    *
    * @param customConfigs the custom configs provided by the user
-   * @return available tableFormatsClients and their configs
+   * @return available tableFormatConverters and their configs
    */
   @VisibleForTesting
-  static TableFormatClients loadTableFormatClientConfigs(byte[] customConfigs) throws IOException {
-    // get resource stream from default client config yaml file
+  static TableFormatConverters loadTableFormatConversionConfigs(byte[] customConfigs)
+      throws IOException {
+    // get resource stream from default converter config yaml file
     try (InputStream inputStream =
-        RunSync.class.getClassLoader().getResourceAsStream("onetable-client-defaults.yaml")) {
-      TableFormatClients clients = YAML_MAPPER.readValue(inputStream, TableFormatClients.class);
+        RunSync.class.getClassLoader().getResourceAsStream("onetable-conversion-defaults.yaml")) {
+      TableFormatConverters converters =
+          YAML_MAPPER.readValue(inputStream, TableFormatConverters.class);
       if (customConfigs != null) {
-        YAML_MAPPER.readerForUpdating(clients).readValue(customConfigs);
+        YAML_MAPPER.readerForUpdating(converters).readValue(customConfigs);
       }
-      return clients;
+      return converters;
     }
   }
 
@@ -250,19 +253,22 @@ public class RunSync {
   }
 
   @Data
-  public static class TableFormatClients {
-    /** Map of table format name to the client configs. */
-    @JsonProperty("tableFormatsClients")
+  public static class TableFormatConverters {
+    /** Map of table format name to the conversion configs. */
+    @JsonProperty("tableFormatConverters")
     @JsonMerge
-    Map<String, ClientConfig> tableFormatsClients;
+    Map<String, ConversionConfig> tableFormatConverters;
 
     @Data
-    public static class ClientConfig {
-      /** The class name of the source client which reads the table metadata. */
-      String sourceClientProviderClass;
+    public static class ConversionConfig {
+      /**
+       * The class name of the {@link ConversionSourceProvider} that will generate the {@link
+       * org.apache.xtable.spi.extractor.ConversionSource}.
+       */
+      String conversionSourceProviderClass;
 
-      /** The class name of the target client which writes the table metadata. */
-      String targetClientProviderClass;
+      /** The class name of the target converter which writes the table metadata. */
+      String conversionTargetProviderClass;
 
       /** the configuration specific to the table format. */
       @JsonMerge Map<String, String> configuration;
diff --git a/utilities/src/main/resources/onetable-client-defaults.yaml b/utilities/src/main/resources/onetable-conversion-defaults.yaml
similarity index 52%
rename from utilities/src/main/resources/onetable-client-defaults.yaml
rename to utilities/src/main/resources/onetable-conversion-defaults.yaml
index 93e5cad3..c80c939b 100644
--- a/utilities/src/main/resources/onetable-client-defaults.yaml
+++ b/utilities/src/main/resources/onetable-conversion-defaults.yaml
@@ -14,27 +14,27 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-## This file contains the default configuration of known InternalTable tableFormatsClients for both source and target
-## table formats. The config maps a table format name to a client class, and contains the default configuration
-## values needed by the client.
+## This file contains the default configuration of known InternalTable tableFormatConverters for both source and target
+## table formats. The config maps a table format name to a converter class, and contains the default configuration
+## values needed by the converter.
 
-## sourceClientProviderClass: The class name of a table format's client factory, where the client is
+## conversionSourceProviderClass: The class name of a table format's converter factory, where the converter is
 ##     used for reading from a table of this format. All user configurations, including hadoop config
-##     and client specific configuration, will be available to the factory for instantiation of the
-##     client.
-## targetClientProviderClass: The class name of a table format's client factory, where the client is
+##     and converter specific configuration, will be available to the factory for instantiation of the
+##     converter.
+## conversionTargetProviderClass: The class name of a table format's converter factory, where the converter is
 ##     used for writing to a table of this format.
-## configuration: A map of configuration values specific to this client.
+## configuration: A map of configuration values specific to this converter.
 
-tableFormatsClients:
+tableFormatConverters:
     HUDI:
-      sourceClientProviderClass: org.apache.xtable.hudi.HudiSourceClientProvider
+      conversionSourceProviderClass: org.apache.xtable.hudi.HudiConversionSourceProvider
     DELTA:
-      sourceClientProviderClass: org.apache.xtable.delta.DeltaSourceClientProvider
-      targetClientProviderClass: org.apache.xtable.delta.DeltaClient
+      conversionSourceProviderClass: org.apache.xtable.delta.DeltaConversionSourceProvider
+      conversionTargetProviderClass: org.apache.xtable.delta.DeltaConversionTarget
       configuration:
         spark.master: local[2]
-        spark.app.name: onetableclient
+        spark.app.name: xtable
     ICEBERG:
-      sourceClientProviderClass: org.apache.xtable.iceberg.IcebergSourceClientProvider
-      targetClientProviderClass: org.apache.xtable.iceberg.IcebergTargetClient
\ No newline at end of file
+      conversionSourceProviderClass: org.apache.xtable.iceberg.IcebergConversionSourceProvider
+      conversionTargetProviderClass: org.apache.xtable.iceberg.IcebergConversionTarget
\ No newline at end of file
diff --git a/utilities/src/test/java/org/apache/xtable/utilities/TestRunSync.java b/utilities/src/test/java/org/apache/xtable/utilities/TestRunSync.java
index 1249f736..a61d948e 100644
--- a/utilities/src/test/java/org/apache/xtable/utilities/TestRunSync.java
+++ b/utilities/src/test/java/org/apache/xtable/utilities/TestRunSync.java
@@ -30,8 +30,8 @@ import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
 import org.apache.xtable.iceberg.IcebergCatalogConfig;
-import org.apache.xtable.utilities.RunSync.TableFormatClients;
-import org.apache.xtable.utilities.RunSync.TableFormatClients.ClientConfig;
+import org.apache.xtable.utilities.RunSync.TableFormatConverters;
+import org.apache.xtable.utilities.RunSync.TableFormatConverters.ConversionConfig;
 
 class TestRunSync {
 
@@ -77,50 +77,52 @@ class TestRunSync {
   }
 
   @Test
-  public void testTableFormatClientConfigDefault() throws IOException {
-    TableFormatClients clients = RunSync.loadTableFormatClientConfigs(null);
-    Map<String, ClientConfig> tfClients = clients.getTableFormatsClients();
-    Assertions.assertEquals(3, tfClients.size());
-    Assertions.assertNotNull(tfClients.get(DELTA));
-    Assertions.assertNotNull(tfClients.get(HUDI));
-    Assertions.assertNotNull(tfClients.get(ICEBERG));
+  public void testTableFormatConverterConfigDefault() throws IOException {
+    TableFormatConverters converters = RunSync.loadTableFormatConversionConfigs(null);
+    Map<String, ConversionConfig> tfConverters = converters.getTableFormatConverters();
+    Assertions.assertEquals(3, tfConverters.size());
+    Assertions.assertNotNull(tfConverters.get(DELTA));
+    Assertions.assertNotNull(tfConverters.get(HUDI));
+    Assertions.assertNotNull(tfConverters.get(ICEBERG));
 
     Assertions.assertEquals(
-        "org.apache.xtable.hudi.HudiSourceClientProvider",
-        tfClients.get(HUDI).getSourceClientProviderClass());
+        "org.apache.xtable.hudi.HudiConversionSourceProvider",
+        tfConverters.get(HUDI).getConversionSourceProviderClass());
     Assertions.assertEquals(
-        "org.apache.xtable.iceberg.IcebergTargetClient",
-        tfClients.get(ICEBERG).getTargetClientProviderClass());
+        "org.apache.xtable.iceberg.IcebergConversionTarget",
+        tfConverters.get(ICEBERG).getConversionTargetProviderClass());
     Assertions.assertEquals(
-        "org.apache.xtable.iceberg.IcebergSourceClientProvider",
-        tfClients.get(ICEBERG).getSourceClientProviderClass());
+        "org.apache.xtable.iceberg.IcebergConversionSourceProvider",
+        tfConverters.get(ICEBERG).getConversionSourceProviderClass());
   }
 
   @Test
-  public void testTableFormatClientCustom() throws IOException {
-    String customClients =
-        "tableFormatsClients:\n"
+  public void testTableFormatConverterCustom() throws IOException {
+    String customConverters =
+        "tableFormatConverters:\n"
             + "  HUDI:\n"
-            + "    sourceClientProviderClass: foo\n"
+            + "    conversionSourceProviderClass: foo\n"
             + "  DELTA:\n"
             + "    configuration:\n"
             + "      spark.master: local[4]\n"
             + "      foo: bar\n"
             + "  NEW_FORMAT:\n"
-            + "    sourceClientProviderClass: bar\n";
-    TableFormatClients clients = RunSync.loadTableFormatClientConfigs(customClients.getBytes());
-    Map<String, ClientConfig> tfClients = clients.getTableFormatsClients();
-    Assertions.assertEquals(4, tfClients.size());
+            + "    conversionSourceProviderClass: bar\n";
+    TableFormatConverters converters =
+        RunSync.loadTableFormatConversionConfigs(customConverters.getBytes());
+    Map<String, ConversionConfig> tfConverters = converters.getTableFormatConverters();
+    Assertions.assertEquals(4, tfConverters.size());
 
-    Assertions.assertNotNull(tfClients.get("NEW_FORMAT"));
-    Assertions.assertEquals("bar", tfClients.get("NEW_FORMAT").getSourceClientProviderClass());
+    Assertions.assertNotNull(tfConverters.get("NEW_FORMAT"));
+    Assertions.assertEquals(
+        "bar", tfConverters.get("NEW_FORMAT").getConversionSourceProviderClass());
 
-    Assertions.assertEquals("foo", tfClients.get(HUDI).getSourceClientProviderClass());
+    Assertions.assertEquals("foo", tfConverters.get(HUDI).getConversionSourceProviderClass());
 
-    Map<String, String> deltaClientConfigs = tfClients.get(DELTA).getConfiguration();
-    Assertions.assertEquals(3, deltaClientConfigs.size());
-    Assertions.assertEquals("local[4]", deltaClientConfigs.get("spark.master"));
-    Assertions.assertEquals("bar", deltaClientConfigs.get("foo"));
+    Map<String, String> deltaConfigs = tfConverters.get(DELTA).getConfiguration();
+    Assertions.assertEquals(3, deltaConfigs.size());
+    Assertions.assertEquals("local[4]", deltaConfigs.get("spark.master"));
+    Assertions.assertEquals("bar", deltaConfigs.get("foo"));
   }
 
   @Test