You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sk...@apache.org on 2024/04/09 13:02:37 UTC

(ignite-3) branch main updated: IGNITE-21594 Storage profiles (#3266)

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

sk0x50 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new 0c7076c0b6 IGNITE-21594 Storage profiles (#3266)
0c7076c0b6 is described below

commit 0c7076c0b688eb018d6406e6a1b3901dccb7834c
Author: Kirill Gusakov <kg...@gmail.com>
AuthorDate: Tue Apr 9 16:02:30 2024 +0300

    IGNITE-21594 Storage profiles (#3266)
---
 examples/build.gradle                              |   1 +
 examples/config/ignite-config.conf                 |   7 +
 .../storage/ItPageMemoryStorageExampleTest.java    |  21 ---
 .../storage/ItRocksdbStorageExampleTest.java       |  11 --
 .../PersistentPageMemoryStorageExample.java        |   2 +-
 .../example/storage/RocksDbStorageExample.java     |   2 +-
 .../example/storage/StorageEngineExample.java      |  15 +-
 .../storage/VolatilePageMemoryStorageExample.java  |   2 +-
 .../org/apache/ignite/catalog/IgniteCatalog.java   |   6 +-
 .../apache/ignite/catalog/annotations/Zone.java    |  14 +-
 .../ignite/catalog/definitions/ZoneDefinition.java |  64 ++------
 .../internal/ConfigurationModuleArchTest.java      |  92 -----------
 .../ignite/internal/catalog/ItCatalogDslTest.java  |  16 +-
 .../catalog/sql/CreateFromAnnotationsImpl.java     |   7 +-
 .../catalog/sql/CreateFromDefinitionImpl.java      |   7 +-
 .../internal/catalog/sql/CreateZoneImpl.java       |  18 +--
 .../ignite/internal/catalog/sql/WithOption.java    |   4 +
 .../catalog/sql/CreateFromAnnotationsTest.java     |  37 +++--
 .../catalog/sql/CreateFromDefinitionTest.java      |  13 +-
 .../internal/catalog/sql/CreateZoneTest.java       |  13 +-
 .../catalog/sql/InvalidDefinitionTest.java         |   3 -
 .../catalog/CatalogParamsValidationUtils.java      |  44 +++++
 .../ignite/internal/catalog/CatalogService.java    |   3 +
 .../catalog/commands/AlterZoneCommand.java         |  25 +--
 .../catalog/commands/AlterZoneCommandBuilder.java  |   7 +-
 .../internal/catalog/commands/CatalogUtils.java    |  29 ++--
 .../catalog/commands/CreateTableCommand.java       |  28 +++-
 .../commands/CreateTableCommandBuilder.java        |   5 +-
 .../catalog/commands/CreateZoneCommand.java        |  28 ++--
 .../catalog/commands/CreateZoneCommandBuilder.java |   7 +-
 .../catalog/commands/RenameZoneCommand.java        |   2 +-
 ...torageParams.java => StorageProfileParams.java} |  55 ++-----
 .../descriptors/CatalogDataStorageDescriptor.java  |  88 ----------
 .../CatalogStorageProfileDescriptor.java           |  73 +++++++++
 .../CatalogStorageProfilesDescriptor.java          |  90 +++++++++++
 .../descriptors/CatalogTableDescriptor.java        |  25 ++-
 .../catalog/descriptors/CatalogZoneDescriptor.java |  28 ++--
 .../internal/catalog/storage/AlterColumnEntry.java |   3 +-
 .../internal/catalog/storage/DropColumnsEntry.java |   3 +-
 .../internal/catalog/storage/NewColumnsEntry.java  |   3 +-
 .../internal/catalog/storage/RenameTableEntry.java |   3 +-
 ...CatalogManagerDescriptorCausalityTokenTest.java |  19 ++-
 .../internal/catalog/CatalogManagerSelfTest.java   |  42 +++--
 .../commands/AbstractCommandValidationTest.java    |  21 ++-
 .../catalog/commands/CatalogUtilsTest.java         |   3 +-
 .../commands/CreateTableCommandValidationTest.java |  28 ++++
 .../commands/CreateZoneCommandValidationTest.java  |  22 +++
 .../CatalogDataStorageDescriptorTest.java          |  37 -----
 .../descriptors/CatalogTableDescriptorTest.java    |   4 +-
 .../descriptors/CatalogZoneDescriptorTest.java     |   8 +-
 .../storage/CatalogEntrySerializationTest.java     |  29 ++--
 .../ignite/internal/catalog/CatalogTestUtils.java  |  12 +-
 .../repl/executor/ItIgnitePicocliCommandsTest.java |   5 +-
 .../ignite/client/handler/FakeCatalogService.java  |   6 +-
 modules/cluster-management/build.gradle            |   3 +
 .../management/topology/ItLogicalTopologyTest.java |  15 +-
 .../cluster/management/NodeAttributes.java         |   5 +-
 .../management/NodeAttributesCollector.java        |  15 +-
 .../ClusterManagementConfigurationModule.java      |   2 +-
 .../StorageProfileConfigurationSchema.java         |  36 -----
 .../management/raft/CmgRaftGroupListener.java      |   2 +-
 .../raft/commands/ClusterNodeMessage.java          |   3 +-
 .../management/topology/api/LogicalNode.java       |  25 +--
 .../management/BaseItClusterManagementTest.java    |   8 +-
 .../internal/cluster/management/MockNode.java      |   4 +-
 modules/compute/build.gradle                       |   1 +
 .../internal/compute/ItWorkerShutdownTest.java     |   3 +-
 .../ignite/configuration/ConfigurationModule.java  |   5 +-
 .../configuration/ConfigurationTreeGenerator.java  |   6 +-
 .../configuration/ConfigurationTestUtils.java      |   0
 .../internal/replicator/ReplicatorConstants.java}  |  11 +-
 .../testframework/TestIgnitionManager.java         |   9 +-
 ...st.java => ItDistributionZonesFiltersTest.java} |  70 +++++---
 ...niteDistributionZoneManagerNodeRestartTest.java |  40 ++---
 .../distributionzones/DistributionZoneManager.java |   6 +-
 .../distributionzones/DistributionZonesUtil.java   |  61 +++++--
 .../distributionzones/NodeWithAttributes.java      |  46 +++++-
 .../CausalityDataNodesEngine.java                  |   6 +-
 .../rebalance/DistributionZoneRebalanceEngine.java |   2 +-
 .../BaseDistributionZoneManagerTest.java           |  17 ++
 ...a => DistributionZoneAttributeFiltersTest.java} |  44 ++---
 .../DistributionZoneManagerAlterFilterTest.java    |  24 ++-
 ...ibutionZoneManagerConfigurationChangesTest.java |   8 +-
 .../DistributionZoneManagerFilterTest.java         |  24 ++-
 ...istributionZoneManagerScaleUpScaleDownTest.java | 145 +++++++++--------
 ...utionZoneManagerStorageProfilesFilterTest.java} |  51 +++---
 .../DistributionZoneStorageProfilesFilterTest.java |  71 ++++++++
 .../DistributionZoneCausalityDataNodesTest.java    |  31 +++-
 .../DistributionZoneRebalanceEngineTest.java       |  13 ++
 .../RebalanceUtilUpdateAssignmentsTest.java        |   4 +-
 .../DistributionZonesTestUtil.java                 | 124 +++++++-------
 .../internal/index/ItBuildIndexOneNodeTest.java    |   3 +-
 .../ignite/internal/index/ItBuildIndexTest.java    |   5 +-
 ...IndexNodeFinishedRwTransactionsCheckerTest.java |   6 +-
 .../index/ItRwTransactionAndIndexesTest.java       |   6 +-
 .../ignite/internal/index/IndexManagerTest.java    |   4 +-
 modules/low-watermark/build.gradle                 |   2 +
 .../internal/lowwatermark/LowWatermarkImpl.java    |   4 +-
 .../lowwatermark/LowWatermarkImplTest.java         |   2 +-
 modules/metastorage/build.gradle                   |   2 +
 .../ItMetaStorageMultipleNodesAbstractTest.java    |   6 +-
 .../metastorage/impl/ItMetaStorageWatchTest.java   |   6 +-
 modules/page-memory/build.gradle                   |   1 +
 .../tree/ItBplusTreeReplaceRemoveRaceTest.java     |  18 ++-
 ...ItBplusTreeReuseListVolatilePageMemoryTest.java |  24 ++-
 .../ItBplusTreeVolatilePageMemoryTest.java         |  24 ++-
 .../ItBplusTreePersistentPageMemoryTest.java       |  22 ++-
 ...BplusTreeReuseListPersistentPageMemoryTest.java |  20 ++-
 .../PageMemoryLocalConfigurationModule.java        |   7 +-
 ...stentPageMemoryProfileConfigurationSchema.java} |  15 +-
 ...atilePageMemoryProfileConfigurationSchema.java} |  16 +-
 .../pagememory/inmemory/VolatilePageMemory.java    |  32 ++--
 .../persistence/PersistentPageMemory.java          |  40 ++---
 .../pagememory/freelist/AbstractFreeListTest.java  |  18 ++-
 .../inmemory/VolatilePageMemoryNoLoadSelfTest.java |  25 +--
 .../PersistentPageMemoryNoLoadTest.java            |  19 ++-
 .../ItPrimaryReplicaChoiceTest.java                |   7 +-
 ...apache.ignite.configuration.ConfigurationModule |   1 -
 .../ignite/internal/replicator/ReplicaManager.java |   4 +-
 modules/runner/build.gradle                        |   2 +
 .../configuration/generator/DefaultsGenerator.java |   3 +-
 .../benchmark/AbstractMultiNodeBenchmark.java      |   4 +-
 .../ItDistributedConfigurationPropertiesTest.java  |   6 +-
 .../ItNodeBootstrapConfigurationTest.java          |   2 +-
 .../configuration/ItNodeConfigurationFileTest.java |   2 +-
 .../ItDistributedConfigurationStorageTest.java     |   6 +-
 .../inmemory/ItRaftStorageVolatilityTest.java      |  26 ++-
 .../app/ItIgniteInMemoryNodeRestartTest.java       |   5 +-
 .../runner/app/ItIgniteNodeRestartTest.java        |  34 ++--
 .../app/client/ItAbstractThinClientTest.java       |   4 +-
 .../schemasync/ItSchemaSyncAndReplicationTest.java |   3 +-
 .../schemasync/ItSchemaSyncMultiNodeTest.java      |   2 +-
 .../ignite/internal/table/ItDurableFinishTest.java |   3 +-
 .../ignite/internal/table/ItInternalTableTest.java |   4 +-
 .../internal/table/ItReadOnlyTransactionTest.java  |   5 +-
 .../ignite/internal/table/ItTableScanTest.java     |   3 +-
 .../org/apache/ignite/internal/app/IgniteImpl.java |  13 +-
 .../storage/LocalFileConfigurationStorage.java     |  47 +++++-
 .../storage/LocalFileConfigurationStorageTest.java |   4 +-
 .../ignite/internal/BaseIgniteRestartTest.java     |   4 +
 .../internal/ClusterPerClassIntegrationTest.java   |  29 ++--
 .../internal/ClusterPerTestIntegrationTest.java    |  11 ++
 .../ignite/internal/TestDefaultProfilesNames.java} |  14 +-
 modules/schema/build.gradle                        |   3 +-
 .../configuration/GcConfigurationSchema.java       |   1 -
 .../LowWatermarkConfigurationSchema.java           |   4 +-
 .../ignite/internal/schema/SchemaManagerTest.java  |   9 +-
 .../CatalogToSchemaDescriptorConverterTest.java    |   4 +-
 modules/sql-engine/build.gradle                    |   1 +
 .../internal/sql/engine/ItAggregatesTest.java      |   3 +-
 .../internal/sql/engine/ItCreateTableDdlTest.java  |  84 +++++++++-
 .../internal/sql/engine/ItIndexSpoolTest.java      |   8 +-
 .../sql/engine/ItPkOnlyTableCrossApiTest.java      |  13 +-
 .../ignite/internal/sql/engine/ItZoneDdlTest.java  |   5 +-
 .../internal/sql/engine/ItZonesSystemViewTest.java |   6 +-
 .../src/main/codegen/includes/parserImpls.ftl      |   6 +-
 .../internal/sql/engine/SqlQueryProcessor.java     |   7 -
 .../exec/ddl/DdlToCatalogCommandConverter.java     |  12 +-
 .../sql/engine/prepare/PrepareServiceImpl.java     |   5 +-
 .../sql/engine/prepare/ddl/CreateTableCommand.java |  17 ++
 .../sql/engine/prepare/ddl/CreateZoneCommand.java  |  43 ++---
 .../prepare/ddl/DdlSqlToCommandConverter.java      | 119 +++-----------
 .../sql/engine/prepare/ddl/TableOptionEnum.java}   |  12 +-
 .../sql/engine/prepare/ddl/ZoneOptionEnum.java     |   4 +-
 .../sql/engine/sql/IgniteSqlCreateZone.java        |  25 +--
 .../DdlCommandHandlerExceptionHandlingTest.java    |   2 +
 .../ddl/DistributionZoneDdlCommandHandlerTest.java |   2 +
 .../exec/rel/TableScanNodeExecutionTest.java       |   2 +-
 .../sql/engine/framework/TestBuilders.java         |   4 +-
 .../ddl/AbstractDdlSqlToCommandConverterTest.java  |   3 +-
 .../prepare/ddl/DdlSqlToCommandConverterTest.java  |  65 ++++----
 .../DistributionZoneSqlToCommandConverterTest.java |  43 ++++-
 .../engine/schema/SqlSchemaManagerImplTest.java    |   3 +
 ...apache.ignite.configuration.ConfigurationModule |   1 -
 modules/storage-api/README.md                      |   2 +-
 modules/storage-api/build.gradle                   |   3 -
 .../internal/storage/DataStorageManager.java       |  89 +++--------
 .../ignite/internal/storage/DataStorageModule.java |   4 +-
 .../internal/storage/DataStorageModules.java       |  81 +---------
 .../StorageConfigurationModule.java}               |  23 +--
 .../StorageConfigurationSchema.java}               |  24 ++-
 .../StorageEngineConfigurationSchema.java}         |  10 +-
 .../StorageProfileConfigurationSchema.java}        |  19 ++-
 .../storage/engine/StorageTableDescriptor.java     |  14 +-
 .../internal/storage/DataStorageManagerTest.java   | 162 -------------------
 .../internal/storage/DataStorageModulesTest.java   | 100 +-----------
 ...apache.ignite.configuration.ConfigurationModule |   1 -
 .../storage/AbstractMvTableStorageTest.java        |   4 +-
 .../storage/engine/AbstractStorageEngineTest.java  |  10 +-
 .../TestPersistStorageConfigurationSchema.java     |  34 ----
 .../impl/TestStorageLocalConfigurationModule.java  |   4 +-
 ...ma.java => TestProfileConfigurationSchema.java} |  11 +-
 .../storage/index/AbstractIndexStorageTest.java    |   4 +-
 .../pagememory/PersistentPageMemoryDataRegion.java |  26 +--
 .../PersistentPageMemoryDataStorageModule.java     |  11 +-
 .../PersistentPageMemoryStorageEngine.java         |  36 ++---
 .../pagememory/VolatilePageMemoryDataRegion.java   |   6 +-
 .../VolatilePageMemoryDataStorageModule.java       |  11 +-
 .../VolatilePageMemoryStorageEngine.java           |  40 ++---
 .../configuration/PageMemoryDataRegionName.java    |  34 ----
 .../PageMemoryDataRegionValidatorImpl.java         |  93 -----------
 ...emoryStorageEngineLocalConfigurationModule.java |  38 +++--
 ...PageMemoryStorageEngineConfigurationSchema.java |  41 -----
 ...ntPageMemoryDataStorageConfigurationSchema.java |  38 -----
 ...PageMemoryStorageEngineConfigurationSchema.java |  33 ++--
 ...StorageEngineExtensionConfigurationSchema.java} |  19 +--
 ...lePageMemoryDataStorageConfigurationSchema.java |  38 -----
 ...PageMemoryStorageEngineConfigurationSchema.java |  35 ++--
 ...StorageEngineExtensionConfigurationSchema.java} |  19 +--
 .../PersistentPageMemoryDataRegionTest.java        |  46 ++++--
 .../PersistentPageMemoryMvTableStorageTest.java    |  10 +-
 .../VolatilePageMemoryMvTableStorageTest.java      |  11 +-
 .../PageMemoryDataRegionValidatorImplTest.java     | 178 ---------------------
 ...yStorageEngineLocalConfigurationModuleTest.java |  74 +++++++++
 .../PersistentPageMemoryStorageEngineTest.java     |   7 +-
 .../AbstractPageMemoryHashIndexStorageTest.java    |  11 +-
 .../AbstractPageMemorySortedIndexStorageTest.java  |   9 +-
 .../PersistentPageMemoryHashIndexStorageTest.java  |  12 +-
 ...PersistentPageMemorySortedIndexStorageTest.java |  12 +-
 .../VolatilePageMemoryHashIndexStorageTest.java    |  14 +-
 .../VolatilePageMemorySortedIndexStorageTest.java  |  14 +-
 .../storage/pagememory/mv/BlobStorageTest.java     |  13 +-
 ...ageMemoryMvPartitionStorageConcurrencyTest.java |  10 +-
 ...rsistentPageMemoryMvPartitionStorageGcTest.java |  10 +-
 ...PersistentPageMemoryMvPartitionStorageTest.java |   9 +-
 ...ageMemoryMvPartitionStorageConcurrencyTest.java |  11 +-
 ...VolatilePageMemoryMvPartitionStorageGcTest.java |  12 +-
 .../VolatilePageMemoryMvPartitionStorageTest.java  |  11 +-
 .../storage/rocksdb/RocksDbDataRegion.java         |  18 +--
 .../storage/rocksdb/RocksDbDataStorageModule.java  |  10 +-
 .../storage/rocksdb/RocksDbStorageEngine.java      |  37 ++---
 .../RocksDbDataRegionValidatorImpl.java            |  56 -------
 ...cksDbStorageEngineLocalConfigurationModule.java |  24 ++-
 .../RocksDbDataStorageConfigurationSchema.java     |  38 -----
 ...java => RocksDbProfileConfigurationSchema.java} |  12 +-
 .../RocksDbStorageEngineConfigurationSchema.java   |  23 +--
 ...StorageEngineExtensionConfigurationSchema.java} |  20 +--
 .../RocksDbMvPartitionStorageConcurrencyTest.java  |  12 +-
 .../rocksdb/RocksDbMvPartitionStorageGcTest.java   |  12 +-
 .../rocksdb/RocksDbMvPartitionStorageTest.java     |  12 +-
 .../storage/rocksdb/RocksDbMvTableStorageTest.java |  12 +-
 .../storage/rocksdb/RocksDbStorageEngineTest.java  |  44 +----
 .../RocksDbDataRegionValidatorImplTest.java        | 107 -------------
 .../rocksdb/engine/RocksDbStorageEngineTest.java   |   5 +
 .../rocksdb/index/RocksDbHashIndexStorageTest.java |  12 +-
 .../index/RocksDbSortedIndexStorageTest.java       |  12 +-
 .../instance/SharedRocksDbInstanceTest.java        |  12 +-
 ...apache.ignite.configuration.ConfigurationModule |   1 -
 .../internal/systemview/SystemViewManagerTest.java |   2 +-
 modules/table/build.gradle                         |   1 +
 .../apache/ignite/distributed/ItLockTableTest.java |   2 +-
 ...xDistributedTestSingleNodeNoCleanupMessage.java |   2 +-
 .../ItDisasterRecoveryReconfigurationTest.java     |   5 +-
 .../raftsnapshot/ItTableRaftSnapshotsTest.java     |  19 ++-
 .../rebalance/ItRebalanceDistributedTest.java      |  45 +++---
 .../rebalance/ItRebalanceRecoveryTest.java         |   4 +-
 .../ignite/internal/rebalance/ItRebalanceTest.java |   4 +-
 .../rebalance/ItRebalanceTriggersRecoveryTest.java |  10 +-
 .../ignite/internal/table/ItColocationTest.java    |   2 +-
 .../internal/table/ItOperationRetryTest.java       |   3 +-
 .../table/ItTransactionPrimaryChangeTest.java      |   3 +-
 .../internal/table/ItTransactionRecoveryTest.java  |   3 +-
 ...apache.ignite.configuration.ConfigurationModule |   1 -
 .../internal/table/distributed/TableManager.java   |  21 +--
 .../CatalogStorageIndexDescriptorSupplierTest.java |   4 +-
 .../distributed/TableManagerRecoveryTest.java      |  18 ++-
 .../table/distributed/TableManagerTest.java        |  39 ++---
 .../PersistentPageMemoryGcUpdateHandlerTest.java   |  10 +-
 .../distributed/gc/RocksDbGcUpdateHandlerTest.java |  11 +-
 .../gc/VolatilePageMemoryGcUpdateHandlerTest.java  |  12 +-
 .../replication/PartitionReplicaListenerTest.java  |   4 +-
 .../schema/CatalogValidationSchemasSourceTest.java |   6 +-
 .../apache/ignite/distributed/ItTxTestCluster.java |   2 +-
 .../table/impl/DummyInternalTableImpl.java         |   2 +-
 .../apache/ignite/internal/tx/TxManagerTest.java   |   2 +-
 ...apache.ignite.configuration.ConfigurationModule |   1 -
 276 files changed, 2510 insertions(+), 2969 deletions(-)

diff --git a/examples/build.gradle b/examples/build.gradle
index 58051394d5..5f5a7b2d3c 100644
--- a/examples/build.gradle
+++ b/examples/build.gradle
@@ -35,6 +35,7 @@ dependencies {
     integrationTestImplementation project(':ignite-api')
     integrationTestImplementation project(':ignite-runner')
     integrationTestImplementation project(':ignite-storage-page-memory')
+    integrationTestImplementation project(':ignite-storage-api')
     integrationTestImplementation project(':ignite-page-memory')
     integrationTestImplementation project(':ignite-storage-rocksdb')
     integrationTestImplementation project(':ignite-configuration')
diff --git a/examples/config/ignite-config.conf b/examples/config/ignite-config.conf
index 52b286d9ef..007ab41aba 100644
--- a/examples/config/ignite-config.conf
+++ b/examples/config/ignite-config.conf
@@ -6,6 +6,13 @@ network {
     }
     port=3344
 }
+storage {
+    profiles {
+        "in-memory" {engine: "aimem"}
+        "persistent" {engine: "aipersist"}
+        "rocksdb-example" : {engine: "rocksDb"}
+    }
+}
 nodeAttributes.nodeAttributes {
       region.attribute = "US"
       storage.attribute = "SSD"
diff --git a/examples/src/integrationTest/java/org/apache/ignite/example/storage/ItPageMemoryStorageExampleTest.java b/examples/src/integrationTest/java/org/apache/ignite/example/storage/ItPageMemoryStorageExampleTest.java
index d97612689d..9df5354f9d 100644
--- a/examples/src/integrationTest/java/org/apache/ignite/example/storage/ItPageMemoryStorageExampleTest.java
+++ b/examples/src/integrationTest/java/org/apache/ignite/example/storage/ItPageMemoryStorageExampleTest.java
@@ -19,12 +19,9 @@ package org.apache.ignite.example.storage;
 
 import static org.apache.ignite.example.ExampleTestUtils.assertConsoleOutputContains;
 
-import java.util.concurrent.TimeUnit;
 import org.apache.ignite.example.AbstractExamplesTest;
 import org.apache.ignite.internal.storage.pagememory.PersistentPageMemoryStorageEngine;
 import org.apache.ignite.internal.storage.pagememory.VolatilePageMemoryStorageEngine;
-import org.apache.ignite.internal.storage.pagememory.configuration.schema.PersistentPageMemoryStorageEngineConfiguration;
-import org.apache.ignite.internal.storage.pagememory.configuration.schema.VolatilePageMemoryStorageEngineConfiguration;
 import org.junit.jupiter.api.Test;
 
 /**
@@ -33,8 +30,6 @@ import org.junit.jupiter.api.Test;
 public class ItPageMemoryStorageExampleTest extends AbstractExamplesTest {
     @Test
     public void testPersistentExample() throws Exception {
-        addPersistentDataRegionConfig("persistent");
-
         assertConsoleOutputContains(PersistentPageMemoryStorageExample::main, EMPTY_ARGS,
                 "\nAll accounts:\n"
                         + "    1, John, Doe, 1000.0\n"
@@ -46,8 +41,6 @@ public class ItPageMemoryStorageExampleTest extends AbstractExamplesTest {
 
     @Test
     public void testInMemoryExample() throws Exception {
-        addVolatileDataRegionConfig("in-memory");
-
         assertConsoleOutputContains(VolatilePageMemoryStorageExample::main, EMPTY_ARGS,
                 "\nAll accounts:\n"
                         + "    1, John, Doe, 1000.0\n"
@@ -56,18 +49,4 @@ public class ItPageMemoryStorageExampleTest extends AbstractExamplesTest {
                         + "    4, Richard, Miles, 1450.0\n"
         );
     }
-
-    private void addVolatileDataRegionConfig(String name) throws Exception {
-        ignite.nodeConfiguration().getConfiguration(VolatilePageMemoryStorageEngineConfiguration.KEY)
-                .regions()
-                .change(regionsChange -> regionsChange.create(name, c -> {}))
-                .get(1, TimeUnit.SECONDS);
-    }
-
-    private void addPersistentDataRegionConfig(String name) throws Exception {
-        ignite.nodeConfiguration().getConfiguration(PersistentPageMemoryStorageEngineConfiguration.KEY)
-                .regions()
-                .change(regionsChange -> regionsChange.create(name, c -> {}))
-                .get(1, TimeUnit.SECONDS);
-    }
 }
diff --git a/examples/src/integrationTest/java/org/apache/ignite/example/storage/ItRocksdbStorageExampleTest.java b/examples/src/integrationTest/java/org/apache/ignite/example/storage/ItRocksdbStorageExampleTest.java
index caff4a32b1..0b22e604f3 100644
--- a/examples/src/integrationTest/java/org/apache/ignite/example/storage/ItRocksdbStorageExampleTest.java
+++ b/examples/src/integrationTest/java/org/apache/ignite/example/storage/ItRocksdbStorageExampleTest.java
@@ -19,9 +19,7 @@ package org.apache.ignite.example.storage;
 
 import static org.apache.ignite.example.ExampleTestUtils.assertConsoleOutputContains;
 
-import java.util.concurrent.TimeUnit;
 import org.apache.ignite.example.AbstractExamplesTest;
-import org.apache.ignite.internal.storage.rocksdb.configuration.schema.RocksDbStorageEngineConfiguration;
 import org.junit.jupiter.api.Test;
 
 /**
@@ -30,8 +28,6 @@ import org.junit.jupiter.api.Test;
 public class ItRocksdbStorageExampleTest extends AbstractExamplesTest {
     @Test
     public void testExample() throws Exception {
-        addDataRegionConfig("rocksdb-example");
-
         assertConsoleOutputContains(RocksDbStorageExample::main, EMPTY_ARGS,
                 "\nAll accounts:\n"
                         + "    1, John, Doe, 1000.0\n"
@@ -40,11 +36,4 @@ public class ItRocksdbStorageExampleTest extends AbstractExamplesTest {
                         + "    4, Richard, Miles, 1450.0\n"
         );
     }
-
-    private void addDataRegionConfig(String name) throws Exception {
-        ignite.nodeConfiguration().getConfiguration(RocksDbStorageEngineConfiguration.KEY)
-                .regions()
-                .change(regionsChange -> regionsChange.create(name, regionChange -> {}))
-                .get(1, TimeUnit.SECONDS);
-    }
 }
diff --git a/examples/src/main/java/org/apache/ignite/example/storage/PersistentPageMemoryStorageExample.java b/examples/src/main/java/org/apache/ignite/example/storage/PersistentPageMemoryStorageExample.java
index 0e89447fe3..7d982bda37 100644
--- a/examples/src/main/java/org/apache/ignite/example/storage/PersistentPageMemoryStorageExample.java
+++ b/examples/src/main/java/org/apache/ignite/example/storage/PersistentPageMemoryStorageExample.java
@@ -54,6 +54,6 @@ public class PersistentPageMemoryStorageExample {
      * @throws Exception If failed.
      */
     public static void main(String[] args) throws Exception {
-        new StorageEngineExample("aipersist", "persistent").run();
+        new StorageEngineExample("persistent").run();
     }
 }
diff --git a/examples/src/main/java/org/apache/ignite/example/storage/RocksDbStorageExample.java b/examples/src/main/java/org/apache/ignite/example/storage/RocksDbStorageExample.java
index 8536cc3b51..5230880f9a 100644
--- a/examples/src/main/java/org/apache/ignite/example/storage/RocksDbStorageExample.java
+++ b/examples/src/main/java/org/apache/ignite/example/storage/RocksDbStorageExample.java
@@ -54,6 +54,6 @@ public class RocksDbStorageExample {
      * @throws Exception If failed.
      */
     public static void main(String[] args) throws Exception {
-        new StorageEngineExample("rocksdb", "rocksdb-example").run();
+        new StorageEngineExample("rocksdb-example").run();
     }
 }
diff --git a/examples/src/main/java/org/apache/ignite/example/storage/StorageEngineExample.java b/examples/src/main/java/org/apache/ignite/example/storage/StorageEngineExample.java
index ca272f02f6..16f58a0f4a 100644
--- a/examples/src/main/java/org/apache/ignite/example/storage/StorageEngineExample.java
+++ b/examples/src/main/java/org/apache/ignite/example/storage/StorageEngineExample.java
@@ -28,19 +28,15 @@ import java.sql.Statement;
  * Class for executing examples that demonstrate working with different storage engines.
  */
 class StorageEngineExample {
-    private final String engineName;
-
-    private final String dataRegionName;
+    private final String storageProfileName;
 
     /**
      * Creates an instance of the example runner.
      *
-     * @param engineName Name of the storage engine, that created SQL tables will use.
-     * @param dataRegionName Name of the data region, that created SQL tables will use.
+     * @param storageProfileName Name of the storage profile, that created SQL tables will use.
      */
-    StorageEngineExample(String engineName, String dataRegionName) {
-        this.engineName = engineName;
-        this.dataRegionName = dataRegionName;
+    StorageEngineExample(String storageProfileName) {
+        this.storageProfileName = storageProfileName;
     }
 
     /**
@@ -67,8 +63,7 @@ class StorageEngineExample {
             try (Statement stmt = conn.createStatement()) {
                 stmt.executeUpdate(
                         "CREATE ZONE ACCOUNTS_ZONE "
-                                + "ENGINE "  + engineName
-                                + " WITH DATAREGION='" + dataRegionName + "'"
+                                + " WITH STORAGE_PROFILES='" + storageProfileName + "'"
                 );
                 stmt.executeUpdate(
                         "CREATE TABLE ACCOUNTS ( "
diff --git a/examples/src/main/java/org/apache/ignite/example/storage/VolatilePageMemoryStorageExample.java b/examples/src/main/java/org/apache/ignite/example/storage/VolatilePageMemoryStorageExample.java
index 1848086317..7556e4e52b 100644
--- a/examples/src/main/java/org/apache/ignite/example/storage/VolatilePageMemoryStorageExample.java
+++ b/examples/src/main/java/org/apache/ignite/example/storage/VolatilePageMemoryStorageExample.java
@@ -54,6 +54,6 @@ public class VolatilePageMemoryStorageExample {
      * @throws Exception If failed.
      */
     public static void main(String[] args) throws Exception {
-        new StorageEngineExample("aimem", "in-memory").run();
+        new StorageEngineExample("in-memory").run();
     }
 }
diff --git a/modules/api/src/main/java/org/apache/ignite/catalog/IgniteCatalog.java b/modules/api/src/main/java/org/apache/ignite/catalog/IgniteCatalog.java
index 2e35b57a88..5fb7f277c6 100644
--- a/modules/api/src/main/java/org/apache/ignite/catalog/IgniteCatalog.java
+++ b/modules/api/src/main/java/org/apache/ignite/catalog/IgniteCatalog.java
@@ -73,7 +73,7 @@ import org.apache.ignite.catalog.definitions.ZoneDefinition;
  *            value = "zone_test",
  *            replicas = 3,
  *            partitions = 1,
- *            engine = ZoneEngine.AIMEM
+ *            storageProfiles = "default"
  *    )
  *    private static class ZoneTest {}
  *
@@ -105,7 +105,7 @@ import org.apache.ignite.catalog.definitions.ZoneDefinition;
  * </pre>
  * These classes when passed to the {@link #create(Class)} method will produce the following statements:
  * <pre>
- *    CREATE ZONE IF NOT EXISTS zone_test ENGINE AIMEM WITH PARTITIONS=1, REPLICAS=3;
+ *    CREATE ZONE IF NOT EXISTS zone_test WITH PARTITIONS=1, REPLICAS=3, STORAGE_PROFILES='default';
  *    CREATE TABLE IF NOT EXISTS table_test (id int, id_str varchar(20), f_name varchar(20) not null default 'a', \
  *    l_name varchar, str varchar, PRIMARY KEY (id, id_str)) COLOCATE BY (id, id_str) WITH PRIMARY_ZONE='ZONE_TEST';
  *    CREATE INDEX IF NOT EXISTS ix_pojo ON table_test (f_name, l_name desc);
@@ -116,7 +116,7 @@ import org.apache.ignite.catalog.definitions.ZoneDefinition;
  *             .ifNotExists()
  *             .partitions(1)
  *             .replicas(3)
- *             .engine(ZoneEngine.AIMEM)
+ *             .storageProfiles("default")
  *             .build();
  *    TableDefinition table = TableDefinition.builder("table_test")
  *            .ifNotExists()
diff --git a/modules/api/src/main/java/org/apache/ignite/catalog/annotations/Zone.java b/modules/api/src/main/java/org/apache/ignite/catalog/annotations/Zone.java
index fc8cff04c1..939936f0ea 100644
--- a/modules/api/src/main/java/org/apache/ignite/catalog/annotations/Zone.java
+++ b/modules/api/src/main/java/org/apache/ignite/catalog/annotations/Zone.java
@@ -22,7 +22,6 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.Target;
-import org.apache.ignite.catalog.ZoneEngine;
 
 /**
  * Describes a distribution zone.
@@ -87,16 +86,9 @@ public @interface Zone {
     String filter() default "";
 
     /**
-     * The storage engine name.
+     * Storage profiles.
      *
-     * @return The storage engine name.
+     * @return Storage profiles.
      */
-    ZoneEngine engine() default ZoneEngine.DEFAULT;
-
-    /**
-     * Data region name within the storage engine.
-     *
-     * @return Data region name.
-     */
-    String dataRegion() default "";
+    String storageProfiles();
 }
diff --git a/modules/api/src/main/java/org/apache/ignite/catalog/definitions/ZoneDefinition.java b/modules/api/src/main/java/org/apache/ignite/catalog/definitions/ZoneDefinition.java
index aa4260f0c9..9d260ac889 100644
--- a/modules/api/src/main/java/org/apache/ignite/catalog/definitions/ZoneDefinition.java
+++ b/modules/api/src/main/java/org/apache/ignite/catalog/definitions/ZoneDefinition.java
@@ -18,7 +18,6 @@
 package org.apache.ignite.catalog.definitions;
 
 import java.util.Objects;
-import org.apache.ignite.catalog.ZoneEngine;
 
 /**
  * Definition of the {@code CREATE ZONE} statement.
@@ -42,9 +41,7 @@ public class ZoneDefinition {
 
     private final String filter;
 
-    private final ZoneEngine engine;
-
-    private final String dataRegion;
+    private final String storageProfiles;
 
     private ZoneDefinition(
             String zoneName,
@@ -56,8 +53,7 @@ public class ZoneDefinition {
             Integer dataNodesAutoAdjustScaleUp,
             Integer dataNodesAutoAdjustScaleDown,
             String filter,
-            ZoneEngine engine,
-            String dataRegion
+            String storageProfiles
     ) {
         this.zoneName = zoneName;
         this.ifNotExists = ifNotExists;
@@ -68,8 +64,7 @@ public class ZoneDefinition {
         this.dataNodesAutoAdjustScaleUp = dataNodesAutoAdjustScaleUp;
         this.dataNodesAutoAdjustScaleDown = dataNodesAutoAdjustScaleDown;
         this.filter = filter;
-        this.engine = engine;
-        this.dataRegion = dataRegion;
+        this.storageProfiles = storageProfiles;
     }
 
     /**
@@ -164,21 +159,12 @@ public class ZoneDefinition {
     }
 
     /**
-     * Returns the storage engine name.
-     *
-     * @return The storage engine name.
-     */
-    public ZoneEngine engine() {
-        return engine;
-    }
-
-    /**
-     * Returns the data region name within the storage engine.
+     * Returns storage profiles.
      *
-     * @return Data region name.
+     * @return Storage profiles.
      */
-    public String dataRegion() {
-        return dataRegion;
+    public String storageProfiles() {
+        return storageProfiles;
     }
 
     /**
@@ -212,9 +198,7 @@ public class ZoneDefinition {
 
         private String filter;
 
-        private ZoneEngine engine = ZoneEngine.DEFAULT;
-
-        private String dataRegion;
+        private String storageProfiles;
 
         private Builder() {}
 
@@ -228,8 +212,7 @@ public class ZoneDefinition {
             dataNodesAutoAdjustScaleUp = definition.dataNodesAutoAdjustScaleUp;
             dataNodesAutoAdjustScaleDown = definition.dataNodesAutoAdjustScaleDown;
             filter = definition.filter;
-            engine = definition.engine;
-            dataRegion = definition.dataRegion;
+            storageProfiles = definition.storageProfiles;
         }
 
         /**
@@ -359,31 +342,15 @@ public class ZoneDefinition {
         }
 
         /**
-         * Sets the storage engine name.
-         *
-         * @param engine Storage engine name.
-         * @return This builder instance.
-         */
-        public Builder engine(ZoneEngine engine) {
-            Objects.requireNonNull(engine, "Engine must not be null.");
-
-            this.engine = engine;
-            return this;
-        }
-
-        /**
-         * Sets the data region name within the storage engine.
+         * Sets the storage profiles.
          *
-         * @param dataRegion Data region name within the storage engine.
+         * @param storageProfiles Storage profiles.
          * @return This builder instance.
          */
-        public Builder dataRegion(String dataRegion) {
-            Objects.requireNonNull(dataRegion, "Data region must not be null.");
-            if (dataRegion.isBlank()) {
-                throw new IllegalArgumentException("Data region must not be blank.");
-            }
+        public Builder storageProfiles(String storageProfiles) {
+            Objects.requireNonNull(storageProfiles, "Storage profiles must not be null.");
 
-            this.dataRegion = dataRegion;
+            this.storageProfiles = storageProfiles;
             return this;
         }
 
@@ -403,8 +370,7 @@ public class ZoneDefinition {
                     dataNodesAutoAdjustScaleUp,
                     dataNodesAutoAdjustScaleDown,
                     filter,
-                    engine,
-                    dataRegion
+                    storageProfiles
             );
         }
     }
diff --git a/modules/arch-test/src/test/java/org/apache/ignite/internal/ConfigurationModuleArchTest.java b/modules/arch-test/src/test/java/org/apache/ignite/internal/ConfigurationModuleArchTest.java
deleted file mode 100644
index e7e04e0b5e..0000000000
--- a/modules/arch-test/src/test/java/org/apache/ignite/internal/ConfigurationModuleArchTest.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal;
-
-import static com.tngtech.archunit.core.domain.JavaClass.Predicates.assignableTo;
-import static com.tngtech.archunit.lang.conditions.ArchPredicates.are;
-
-import com.tngtech.archunit.base.DescribedPredicate;
-import com.tngtech.archunit.core.domain.JavaClass;
-import com.tngtech.archunit.core.importer.ImportOption;
-import com.tngtech.archunit.junit.AnalyzeClasses;
-import com.tngtech.archunit.junit.ArchTest;
-import com.tngtech.archunit.lang.ArchCondition;
-import com.tngtech.archunit.lang.ArchRule;
-import com.tngtech.archunit.lang.ConditionEvents;
-import com.tngtech.archunit.lang.SimpleConditionEvent;
-import com.tngtech.archunit.lang.syntax.ArchRuleDefinition;
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
-import org.apache.ignite.configuration.ConfigurationModule;
-import org.apache.ignite.configuration.SuperRootChange;
-import org.apache.ignite.configuration.annotation.ConfigurationType;
-import org.apache.ignite.internal.configuration.ServiceLoaderModulesProvider;
-import org.apache.ignite.lang.LocationProvider.RootLocationProvider;
-
-/**
- * Tests that all local configuration modules do not override
- * {@link ConfigurationModule#patchConfigurationWithDynamicDefaults(SuperRootChange)}.
- */
-@AnalyzeClasses(
-        packages = "org.apache.ignite",
-        importOptions = ImportOption.DoNotIncludeTests.class,
-        locations = RootLocationProvider.class)
-public class ConfigurationModuleArchTest {
-    @ArchTest
-    public static final ArchRule LOCAL_CONFIGURATION_MODULES_DOES_NOT_OVERRIDE = ArchRuleDefinition.classes()
-            .that(new Predicate())
-            .and(are(assignableTo(ConfigurationModule.class)))
-            .should(new ArchCondition<>(
-                    "not override org.apache.ignite.configuration.ConfigurationModule.patchConfigurationWithDynamicDefaults") {
-                @Override
-                public void check(JavaClass javaClass, ConditionEvents conditionEvents) {
-                    boolean overrided = javaClass.getMethods().stream()
-                            .anyMatch(it -> it.getName().equals("patchConfigurationWithDynamicDefaults"));
-
-                    if (overrided) {
-                        conditionEvents.add(SimpleConditionEvent.violated(
-                                javaClass,
-                                javaClass.getName() + " overrides patchConfigurationWithDynamicDefaults"
-                        ));
-                    }
-                }
-            });
-
-    private static final Set<String> local;
-
-    static {
-        var modulesProvider = new ServiceLoaderModulesProvider();
-        List<ConfigurationModule> modules = modulesProvider.modules(ConfigurationModuleArchTest.class.getClassLoader());
-        local = modules.stream()
-                .filter(it -> it.type() == ConfigurationType.LOCAL)
-                .map(it -> it.getClass().getCanonicalName())
-                .collect(Collectors.toSet());
-    }
-
-    private static class Predicate extends DescribedPredicate<JavaClass> {
-        public Predicate() {
-            super("local configuration module");
-        }
-
-        @Override
-        public boolean test(JavaClass javaClass) {
-            return local.contains(javaClass.getFullName());
-        }
-    }
-}
diff --git a/modules/catalog-dsl/src/integrationTest/java/org/apache/ignite/internal/catalog/ItCatalogDslTest.java b/modules/catalog-dsl/src/integrationTest/java/org/apache/ignite/internal/catalog/ItCatalogDslTest.java
index cfd590cb42..d784022490 100644
--- a/modules/catalog-dsl/src/integrationTest/java/org/apache/ignite/internal/catalog/ItCatalogDslTest.java
+++ b/modules/catalog-dsl/src/integrationTest/java/org/apache/ignite/internal/catalog/ItCatalogDslTest.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.internal.catalog;
 
 import static org.apache.ignite.catalog.definitions.ColumnDefinition.column;
+import static org.apache.ignite.internal.TestDefaultProfilesNames.DEFAULT_AIPERSIST_PROFILE_NAME;
 import static org.apache.ignite.internal.testframework.IgniteTestUtils.assertThrows;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.contains;
@@ -29,7 +30,6 @@ import java.util.UUID;
 import org.apache.ignite.catalog.ColumnType;
 import org.apache.ignite.catalog.IgniteCatalog;
 import org.apache.ignite.catalog.SortOrder;
-import org.apache.ignite.catalog.ZoneEngine;
 import org.apache.ignite.catalog.annotations.Column;
 import org.apache.ignite.catalog.annotations.ColumnRef;
 import org.apache.ignite.catalog.annotations.Id;
@@ -77,8 +77,7 @@ class ItCatalogDslTest extends ClusterPerClassIntegrationTest {
                 .affinity("affinity")
                 .dataNodesAutoAdjust(1)
                 .filter("filter")
-                .engine(ZoneEngine.AIMEM)
-                .dataRegion("dataRegion")
+                .storageProfiles(DEFAULT_AIPERSIST_PROFILE_NAME)
                 .build();
 
         // When create zone from definition
@@ -87,7 +86,7 @@ class ItCatalogDslTest extends ClusterPerClassIntegrationTest {
         // Then zone was created
         assertThrows(
                 SqlException.class,
-                () -> sql("CREATE ZONE " + ZONE_NAME),
+                () -> sql("CREATE ZONE " + ZONE_NAME + " WITH STORAGE_PROFILES='" + DEFAULT_AIPERSIST_PROFILE_NAME + "'"),
                 "Distribution zone with name '" + ZONE_NAME.toUpperCase() + "' already exists"
         );
 
@@ -105,7 +104,10 @@ class ItCatalogDslTest extends ClusterPerClassIntegrationTest {
     @Test
     void zoneCreateAndDropByName() {
         // Given zone definition
-        ZoneDefinition zoneDefinition = ZoneDefinition.builder(ZONE_NAME).build();
+        ZoneDefinition zoneDefinition = ZoneDefinition
+                .builder(ZONE_NAME)
+                .storageProfiles(DEFAULT_AIPERSIST_PROFILE_NAME)
+                .build();
 
         // When create zone from definition
         catalog().createZone(zoneDefinition).execute();
@@ -113,7 +115,7 @@ class ItCatalogDslTest extends ClusterPerClassIntegrationTest {
         // Then zone was created
         assertThrows(
                 SqlException.class,
-                () -> sql("CREATE ZONE " + ZONE_NAME),
+                () -> sql("CREATE ZONE " + ZONE_NAME + " WITH STORAGE_PROFILES='" + DEFAULT_AIPERSIST_PROFILE_NAME + "'"),
                 "Distribution zone with name '" + ZONE_NAME.toUpperCase() + "' already exists"
         );
 
@@ -284,7 +286,7 @@ class ItCatalogDslTest extends ClusterPerClassIntegrationTest {
         return CLUSTER.node(0).tables();
     }
 
-    @Zone(ZONE_NAME)
+    @Zone(value = ZONE_NAME, storageProfiles = DEFAULT_AIPERSIST_PROFILE_NAME)
     private static class ZoneTest {
     }
 
diff --git a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateFromAnnotationsImpl.java b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateFromAnnotationsImpl.java
index 836d3b135a..cda0865ef0 100644
--- a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateFromAnnotationsImpl.java
+++ b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateFromAnnotationsImpl.java
@@ -111,6 +111,7 @@ class CreateFromAnnotationsImpl extends AbstractCatalogQuery {
             String zoneName = zone.value().isEmpty() ? zoneRef.getSimpleName() : zone.value();
             createTable.zone(zoneName);
             createZone.name(zoneName);
+            createZone.storageProfiles(zone.storageProfiles());
             if (zone.partitions() > 0) {
                 createZone.partitions(zone.partitions());
             }
@@ -135,12 +136,6 @@ class CreateFromAnnotationsImpl extends AbstractCatalogQuery {
             if (!zone.filter().isEmpty()) {
                 createZone.filter(zone.filter());
             }
-
-            createZone.engine(zone.engine());
-
-            if (!zone.dataRegion().isEmpty()) {
-                createZone.dataRegion(zone.dataRegion());
-            }
         }
     }
 
diff --git a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateFromDefinitionImpl.java b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateFromDefinitionImpl.java
index 472bda3bfd..86fc7d2295 100644
--- a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateFromDefinitionImpl.java
+++ b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateFromDefinitionImpl.java
@@ -46,6 +46,7 @@ class CreateFromDefinitionImpl extends AbstractCatalogQuery {
     Query from(ZoneDefinition def) {
         createZone = new CreateZoneImpl(sql, options);
         createZone.name(def.zoneName());
+        createZone.storageProfiles(def.storageProfiles());
         if (def.ifNotExists()) {
             createZone.ifNotExists();
         }
@@ -74,12 +75,6 @@ class CreateFromDefinitionImpl extends AbstractCatalogQuery {
             createZone.filter(def.filter());
         }
 
-        createZone.engine(def.engine());
-
-        if (!StringUtils.nullOrBlank(def.dataRegion())) {
-            createZone.dataRegion(def.dataRegion());
-        }
-
         return this;
     }
 
diff --git a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateZoneImpl.java b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateZoneImpl.java
index 1b3899a091..bb307a57f6 100644
--- a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateZoneImpl.java
+++ b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/CreateZoneImpl.java
@@ -23,7 +23,6 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
 import org.apache.ignite.catalog.Options;
-import org.apache.ignite.catalog.ZoneEngine;
 import org.apache.ignite.sql.IgniteSql;
 
 class CreateZoneImpl extends AbstractCatalogQuery {
@@ -33,8 +32,6 @@ class CreateZoneImpl extends AbstractCatalogQuery {
 
     private final List<WithOption> withOptions = new ArrayList<>();
 
-    private ZoneEngine engine;
-
     /**
      * Constructor for internal usage.
      *
@@ -108,15 +105,10 @@ class CreateZoneImpl extends AbstractCatalogQuery {
         return this;
     }
 
-    CreateZoneImpl engine(ZoneEngine engine) {
-        this.engine = engine;
-        return this;
-    }
-
-    CreateZoneImpl dataRegion(String dataRegion) {
-        Objects.requireNonNull(dataRegion, "Data region must not be null.");
+    CreateZoneImpl storageProfiles(String storageProfiles) {
+        Objects.requireNonNull(storageProfiles, "Storage profiles must not be null");
 
-        withOptions.add(WithOption.dataRegion(dataRegion));
+        withOptions.add(WithOption.storageProfiles(storageProfiles));
         return this;
     }
 
@@ -128,10 +120,6 @@ class CreateZoneImpl extends AbstractCatalogQuery {
         }
         ctx.visit(zoneName);
 
-        if (engine != null && engine != ZoneEngine.DEFAULT) {
-            ctx.sql(" ENGINE ").sql(engine.name());
-        }
-
         if (!withOptions.isEmpty()) {
             ctx.sql(" ").formatSeparator().sql("WITH ");
             ctx.visit(partsList(withOptions).formatSeparator());
diff --git a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/WithOption.java b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/WithOption.java
index d6d5355835..5d089f72d5 100644
--- a/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/WithOption.java
+++ b/modules/catalog-dsl/src/main/java/org/apache/ignite/internal/catalog/sql/WithOption.java
@@ -63,6 +63,10 @@ class WithOption extends QueryPart {
         return new WithOption("DATAREGION", dataRegion);
     }
 
+    public static WithOption storageProfiles(String storageProfiles) {
+        return new WithOption("STORAGE_PROFILES", storageProfiles);
+    }
+
     @Override
     protected void accept(QueryContext ctx) {
         ctx.sql(name).sql("=");
diff --git a/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/CreateFromAnnotationsTest.java b/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/CreateFromAnnotationsTest.java
index cd50f1008a..73b8b81c65 100644
--- a/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/CreateFromAnnotationsTest.java
+++ b/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/CreateFromAnnotationsTest.java
@@ -27,7 +27,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
 import org.apache.ignite.catalog.IndexType;
 import org.apache.ignite.catalog.Options;
 import org.apache.ignite.catalog.SortOrder;
-import org.apache.ignite.catalog.ZoneEngine;
 import org.apache.ignite.catalog.annotations.Column;
 import org.apache.ignite.catalog.annotations.ColumnRef;
 import org.apache.ignite.catalog.annotations.Id;
@@ -70,8 +69,7 @@ class CreateFromAnnotationsTest {
                 .dataNodesAutoAdjustScaleDown(2)
                 .dataNodesAutoAdjustScaleUp(3)
                 .filter("filter")
-                .engine(ZoneEngine.AIMEM)
-                .dataRegion("dataRegion")
+                .storageProfiles("default")
                 .build();
         String sqlZoneFromDefinition = new CreateFromDefinitionImpl(null, Options.DEFAULT).from(zoneDefinition).toSqlString();
 
@@ -94,9 +92,10 @@ class CreateFromAnnotationsTest {
         // primitive/boxed key class is a primary key with default name 'id'
         assertThat(
                 createTable().processKeyValueClasses(Integer.class, PojoValue.class).toSqlString(),
-                is("CREATE ZONE IF NOT EXISTS zone_test ENGINE AIMEM WITH PARTITIONS=1, REPLICAS=3, AFFINITY_FUNCTION='affinity',"
+                is("CREATE ZONE IF NOT EXISTS zone_test WITH STORAGE_PROFILES='default', PARTITIONS=1, REPLICAS=3,"
+                        + " AFFINITY_FUNCTION='affinity',"
                         + " DATA_NODES_AUTO_ADJUST=1, DATA_NODES_AUTO_ADJUST_SCALE_UP=3, DATA_NODES_AUTO_ADJUST_SCALE_DOWN=2,"
-                        + " DATA_NODES_FILTER='filter', DATAREGION='dataRegion';"
+                        + " DATA_NODES_FILTER='filter';"
                         + "CREATE TABLE IF NOT EXISTS pojo_value_test (id int, f_name varchar, l_name varchar, str varchar,"
                         + " PRIMARY KEY (id)) COLOCATE BY (id, id_str) WITH PRIMARY_ZONE='ZONE_TEST';"
                         + "CREATE INDEX IF NOT EXISTS ix_pojo ON pojo_value_test (f_name, l_name desc);")
@@ -108,9 +107,10 @@ class CreateFromAnnotationsTest {
         // primitive/boxed key class is a primary key with default name 'id'
         assertThat(
                 createTableQuoted().processKeyValueClasses(Integer.class, PojoValue.class).toSqlString(),
-                is("CREATE ZONE IF NOT EXISTS \"zone_test\" ENGINE AIMEM WITH PARTITIONS=1, REPLICAS=3, AFFINITY_FUNCTION='affinity',"
+                is("CREATE ZONE IF NOT EXISTS \"zone_test\" WITH STORAGE_PROFILES='default', PARTITIONS=1, REPLICAS=3,"
+                        + " AFFINITY_FUNCTION='affinity',"
                         + " DATA_NODES_AUTO_ADJUST=1, DATA_NODES_AUTO_ADJUST_SCALE_UP=3, DATA_NODES_AUTO_ADJUST_SCALE_DOWN=2,"
-                        + " DATA_NODES_FILTER='filter', DATAREGION='dataRegion';"
+                        + " DATA_NODES_FILTER='filter';"
                         + "CREATE TABLE IF NOT EXISTS \"pojo_value_test\" (\"id\" int, \"f_name\" varchar, \"l_name\" varchar,"
                         + " \"str\" varchar, PRIMARY KEY (\"id\")) COLOCATE BY (\"id\", \"id_str\") WITH PRIMARY_ZONE='ZONE_TEST';"
                         + "CREATE INDEX IF NOT EXISTS \"ix_pojo\" ON \"pojo_value_test\" (\"f_name\", \"l_name\" desc);")
@@ -122,9 +122,10 @@ class CreateFromAnnotationsTest {
         // key class fields (annotated only) is a composite primary keys
         assertThat(
                 createTable().processKeyValueClasses(PojoKey.class, PojoValue.class).toSqlString(),
-                is("CREATE ZONE IF NOT EXISTS zone_test ENGINE AIMEM WITH PARTITIONS=1, REPLICAS=3, AFFINITY_FUNCTION='affinity',"
+                is("CREATE ZONE IF NOT EXISTS zone_test WITH STORAGE_PROFILES='default', PARTITIONS=1, REPLICAS=3,"
+                        + " AFFINITY_FUNCTION='affinity',"
                         + " DATA_NODES_AUTO_ADJUST=1, DATA_NODES_AUTO_ADJUST_SCALE_UP=3, DATA_NODES_AUTO_ADJUST_SCALE_DOWN=2,"
-                        + " DATA_NODES_FILTER='filter', DATAREGION='dataRegion';"
+                        + " DATA_NODES_FILTER='filter';"
                         + "CREATE TABLE IF NOT EXISTS pojo_value_test (id int, id_str varchar(20), f_name varchar, l_name varchar,"
                         + " str varchar, PRIMARY KEY (id, id_str)) COLOCATE BY (id, id_str) WITH PRIMARY_ZONE='ZONE_TEST';"
                         + "CREATE INDEX IF NOT EXISTS ix_pojo ON pojo_value_test (f_name, l_name desc);")
@@ -136,9 +137,10 @@ class CreateFromAnnotationsTest {
         // key class fields (annotated only) is a composite primary keys
         assertThat(
                 createTableQuoted().processKeyValueClasses(PojoKey.class, PojoValue.class).toSqlString(),
-                is("CREATE ZONE IF NOT EXISTS \"zone_test\" ENGINE AIMEM WITH PARTITIONS=1, REPLICAS=3, AFFINITY_FUNCTION='affinity',"
+                is("CREATE ZONE IF NOT EXISTS \"zone_test\" WITH STORAGE_PROFILES='default', PARTITIONS=1, REPLICAS=3,"
+                        + " AFFINITY_FUNCTION='affinity',"
                         + " DATA_NODES_AUTO_ADJUST=1, DATA_NODES_AUTO_ADJUST_SCALE_UP=3, DATA_NODES_AUTO_ADJUST_SCALE_DOWN=2,"
-                        + " DATA_NODES_FILTER='filter', DATAREGION='dataRegion';"
+                        + " DATA_NODES_FILTER='filter';"
                         + "CREATE TABLE IF NOT EXISTS \"pojo_value_test\" (\"id\" int, \"id_str\" varchar(20), \"f_name\" varchar,"
                         + " \"l_name\" varchar, \"str\" varchar, PRIMARY KEY (\"id\", \"id_str\")) COLOCATE BY (\"id\", \"id_str\")"
                         + " WITH PRIMARY_ZONE='ZONE_TEST';"
@@ -150,9 +152,10 @@ class CreateFromAnnotationsTest {
     void createFromRecordClass() {
         assertThat(
                 createTable().processRecordClass(Pojo.class).toSqlString(),
-                is("CREATE ZONE IF NOT EXISTS zone_test ENGINE AIMEM WITH PARTITIONS=1, REPLICAS=3, AFFINITY_FUNCTION='affinity',"
+                is("CREATE ZONE IF NOT EXISTS zone_test WITH STORAGE_PROFILES='default', PARTITIONS=1, REPLICAS=3,"
+                        + " AFFINITY_FUNCTION='affinity',"
                         + " DATA_NODES_AUTO_ADJUST=1, DATA_NODES_AUTO_ADJUST_SCALE_UP=3, DATA_NODES_AUTO_ADJUST_SCALE_DOWN=2,"
-                        + " DATA_NODES_FILTER='filter', DATAREGION='dataRegion';"
+                        + " DATA_NODES_FILTER='filter';"
                         + "CREATE TABLE IF NOT EXISTS pojo_test (id int, id_str varchar(20), f_name varchar(20) not null default 'a',"
                         + " l_name varchar, str varchar, PRIMARY KEY (id, id_str))"
                         + " COLOCATE BY (id, id_str) WITH PRIMARY_ZONE='ZONE_TEST';"
@@ -164,9 +167,10 @@ class CreateFromAnnotationsTest {
     void createFromRecordClassQuoted() {
         assertThat(
                 createTableQuoted().processRecordClass(Pojo.class).toSqlString(),
-                is("CREATE ZONE IF NOT EXISTS \"zone_test\" ENGINE AIMEM WITH PARTITIONS=1, REPLICAS=3, AFFINITY_FUNCTION='affinity',"
+                is("CREATE ZONE IF NOT EXISTS \"zone_test\" WITH STORAGE_PROFILES='default', PARTITIONS=1, REPLICAS=3,"
+                        + " AFFINITY_FUNCTION='affinity',"
                         + " DATA_NODES_AUTO_ADJUST=1, DATA_NODES_AUTO_ADJUST_SCALE_UP=3, DATA_NODES_AUTO_ADJUST_SCALE_DOWN=2,"
-                        + " DATA_NODES_FILTER='filter', DATAREGION='dataRegion';"
+                        + " DATA_NODES_FILTER='filter';"
                         + "CREATE TABLE IF NOT EXISTS \"pojo_test\" (\"id\" int, \"id_str\" varchar(20),"
                         + " \"f_name\" varchar(20) not null default 'a', \"l_name\" varchar, \"str\" varchar,"
                         + " PRIMARY KEY (\"id\", \"id_str\")) COLOCATE BY (\"id\", \"id_str\") WITH PRIMARY_ZONE='ZONE_TEST';"
@@ -228,8 +232,7 @@ class CreateFromAnnotationsTest {
             dataNodesAutoAdjustScaleDown = 2,
             dataNodesAutoAdjustScaleUp = 3,
             filter = "filter",
-            engine = ZoneEngine.AIMEM,
-            dataRegion = "dataRegion"
+            storageProfiles = "default"
     )
     private static class ZoneTest {}
 
diff --git a/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/CreateFromDefinitionTest.java b/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/CreateFromDefinitionTest.java
index f0d5ee01ad..1600cf1187 100644
--- a/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/CreateFromDefinitionTest.java
+++ b/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/CreateFromDefinitionTest.java
@@ -29,7 +29,6 @@ import static org.hamcrest.Matchers.is;
 import org.apache.ignite.catalog.ColumnType;
 import org.apache.ignite.catalog.IndexType;
 import org.apache.ignite.catalog.Options;
-import org.apache.ignite.catalog.ZoneEngine;
 import org.apache.ignite.catalog.annotations.Column;
 import org.apache.ignite.catalog.annotations.Id;
 import org.apache.ignite.catalog.definitions.TableDefinition;
@@ -41,9 +40,9 @@ import org.junit.jupiter.api.Test;
 class CreateFromDefinitionTest {
     @Test
     void createFromZoneBuilderSimple() {
-        ZoneDefinition zone = ZoneDefinition.builder("zone_test").build();
+        ZoneDefinition zone = ZoneDefinition.builder("zone_test").storageProfiles("default").build();
 
-        assertThat(createZone(zone), is("CREATE ZONE zone_test;"));
+        assertThat(createZone(zone), is("CREATE ZONE zone_test WITH STORAGE_PROFILES='default';"));
     }
 
     @Test
@@ -57,15 +56,15 @@ class CreateFromDefinitionTest {
                 .dataNodesAutoAdjustScaleDown(2)
                 .dataNodesAutoAdjustScaleUp(3)
                 .filter("filter")
-                .engine(ZoneEngine.AIMEM)
-                .dataRegion("dataRegion")
+                .storageProfiles("default")
                 .build();
 
         assertThat(
                 createZone(zone),
-                is("CREATE ZONE IF NOT EXISTS zone_test ENGINE AIMEM WITH PARTITIONS=3, REPLICAS=3, AFFINITY_FUNCTION='affinity',"
+                is("CREATE ZONE IF NOT EXISTS zone_test WITH STORAGE_PROFILES='default', PARTITIONS=3, REPLICAS=3,"
+                        + " AFFINITY_FUNCTION='affinity',"
                         + " DATA_NODES_AUTO_ADJUST=1, DATA_NODES_AUTO_ADJUST_SCALE_UP=3, DATA_NODES_AUTO_ADJUST_SCALE_DOWN=2,"
-                        + " DATA_NODES_FILTER='filter', DATAREGION='dataRegion';")
+                        + " DATA_NODES_FILTER='filter';")
         );
     }
 
diff --git a/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/CreateZoneTest.java b/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/CreateZoneTest.java
index f3fc63d60c..544ce6a726 100644
--- a/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/CreateZoneTest.java
+++ b/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/CreateZoneTest.java
@@ -17,7 +17,6 @@
 
 package org.apache.ignite.internal.catalog.sql;
 
-import static org.apache.ignite.catalog.ZoneEngine.ROCKSDB;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
 
@@ -44,15 +43,6 @@ class CreateZoneTest {
         assertThat(sql, is("CREATE ZONE \"public\".\"zone1\";"));
     }
 
-    @Test
-    void testEngine() {
-        String sql = createZone().name("zone1").engine(ROCKSDB).toSqlString();
-        assertThat(sql, is("CREATE ZONE zone1 ENGINE ROCKSDB;"));
-
-        sql = createZoneQuoted().name("zone1").engine(ROCKSDB).toSqlString();
-        assertThat(sql, is("CREATE ZONE \"zone1\" ENGINE ROCKSDB;"));
-    }
-
     @Test
     void testWithOptions() {
         String sql = createZone().name("zone1").partitions(1).toSqlString();
@@ -67,6 +57,9 @@ class CreateZoneTest {
 
         sql = createZoneQuoted().name("zone1").partitions(1).replicas(1).toSqlString();
         assertThat(sql, is("CREATE ZONE \"zone1\" WITH PARTITIONS=1, REPLICAS=1;"));
+
+        sql = createZoneQuoted().name("zone1").storageProfiles("profile1,profile2").toSqlString();
+        assertThat(sql, is("CREATE ZONE \"zone1\" WITH STORAGE_PROFILES='profile1,profile2';"));
     }
 
     private static CreateZoneImpl createZone() {
diff --git a/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/InvalidDefinitionTest.java b/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/InvalidDefinitionTest.java
index b6e0b3b443..26d7c7ab8a 100644
--- a/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/InvalidDefinitionTest.java
+++ b/modules/catalog-dsl/src/test/java/org/apache/ignite/internal/catalog/sql/InvalidDefinitionTest.java
@@ -27,7 +27,6 @@ import java.util.function.BiConsumer;
 import java.util.function.Consumer;
 import java.util.function.Supplier;
 import org.apache.ignite.catalog.ColumnSorted;
-import org.apache.ignite.catalog.ZoneEngine;
 import org.apache.ignite.catalog.definitions.ColumnDefinition;
 import org.apache.ignite.catalog.definitions.TableDefinition;
 import org.apache.ignite.catalog.definitions.ZoneDefinition;
@@ -42,7 +41,6 @@ class InvalidDefinitionTest {
 
     @Test
     void zone() {
-        assertZoneBuilderNull(ZoneDefinition.Builder::engine, ZoneEngine.AIMEM, "Engine");
         assertZoneBuilderNull(ZoneDefinition.Builder::partitions, 1, "Number of partitions");
         assertZoneBuilderNull(ZoneDefinition.Builder::replicas, 1, "Number of replicas");
 
@@ -56,7 +54,6 @@ class InvalidDefinitionTest {
                 "Timeout between node left topology event itself and data nodes switch");
 
         assertZoneBuilderNullOrBlank(ZoneDefinition.Builder::filter, "f", "Filter");
-        assertZoneBuilderNullOrBlank(ZoneDefinition.Builder::dataRegion, "r", "Data region");
     }
 
     @Test
diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/CatalogParamsValidationUtils.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/CatalogParamsValidationUtils.java
index 351d2ed3c9..fcb5dd3b76 100644
--- a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/CatalogParamsValidationUtils.java
+++ b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/CatalogParamsValidationUtils.java
@@ -21,7 +21,13 @@ import static org.apache.ignite.internal.lang.IgniteStringFormatter.format;
 
 import com.jayway.jsonpath.InvalidPathException;
 import com.jayway.jsonpath.JsonPath;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.ignite.internal.catalog.commands.StorageProfileParams;
 import org.apache.ignite.internal.catalog.descriptors.CatalogSchemaDescriptor;
+import org.apache.ignite.internal.catalog.descriptors.CatalogStorageProfileDescriptor;
+import org.apache.ignite.internal.catalog.descriptors.CatalogZoneDescriptor;
 import org.apache.ignite.internal.util.StringUtils;
 import org.jetbrains.annotations.Nullable;
 
@@ -96,6 +102,23 @@ public class CatalogParamsValidationUtils {
         }
     }
 
+    /**
+     * Validates correctness of the storage profiles.
+     */
+    public static void validateStorageProfiles(List<StorageProfileParams> storageProfiles) {
+        if (storageProfiles == null) {
+            throw new CatalogValidationException(
+                    "Storage profile cannot be null"
+            );
+        }
+
+        if (storageProfiles.isEmpty()) {
+            throw new CatalogValidationException(
+                    "Storage profile cannot be empty"
+            );
+        }
+    }
+
     /**
      * Validates that given schema doesn't contain any relation with specified name.
      *
@@ -116,4 +139,25 @@ public class CatalogParamsValidationUtils {
             throw new CatalogValidationException(format("System view with name '{}.{}' already exists", schema.name(), name));
         }
     }
+
+    /**
+     * Validates that table's zone contains table's storage profile.
+     *
+     * @throws CatalogValidationException If zone does not contain table's storage profile.
+     */
+    public static void ensureZoneContainsTablesStorageProfile(CatalogZoneDescriptor zone, String tableStorageProfile) {
+        Set<String> zonesStorageProfile = zone.storageProfiles().profiles()
+                .stream().map(CatalogStorageProfileDescriptor::storageProfile)
+                .collect(Collectors.toSet());
+
+        if (!zonesStorageProfile.contains(tableStorageProfile)) {
+            throw new CatalogValidationException(
+                    format(
+                            "Zone with name '{}' does not contain table's storage profile [storageProfile='{}']",
+                            zone.name(),
+                            tableStorageProfile
+                    )
+            );
+        }
+    }
 }
diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/CatalogService.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/CatalogService.java
index d2c167c863..e944beb665 100644
--- a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/CatalogService.java
+++ b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/CatalogService.java
@@ -51,6 +51,9 @@ public interface CatalogService extends EventProducer<CatalogEvent, CatalogEvent
 
     String DEFAULT_ZONE_NAME = "Default";
 
+    /** Default storage profile. */
+    String DEFAULT_STORAGE_PROFILE = "default";
+
     @Nullable Catalog catalog(int catalogVersion);
 
     @Nullable CatalogTableDescriptor table(String tableName, long timestamp);
diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/AlterZoneCommand.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/AlterZoneCommand.java
index 78ba8d3b22..564fd85001 100644
--- a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/AlterZoneCommand.java
+++ b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/AlterZoneCommand.java
@@ -30,7 +30,7 @@ import java.util.Objects;
 import org.apache.ignite.internal.catalog.Catalog;
 import org.apache.ignite.internal.catalog.CatalogCommand;
 import org.apache.ignite.internal.catalog.CatalogValidationException;
-import org.apache.ignite.internal.catalog.descriptors.CatalogDataStorageDescriptor;
+import org.apache.ignite.internal.catalog.descriptors.CatalogStorageProfilesDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.CatalogZoneDescriptor;
 import org.apache.ignite.internal.catalog.storage.AlterZoneEntry;
 import org.apache.ignite.internal.catalog.storage.UpdateEntry;
@@ -56,7 +56,7 @@ public class AlterZoneCommand extends AbstractZoneCommand {
 
     private final @Nullable String filter;
 
-    private final @Nullable DataStorageParams dataStorageParams;
+    private final @Nullable List<StorageProfileParams> storageProfileParams;
 
     /**
      * Constructor.
@@ -68,7 +68,7 @@ public class AlterZoneCommand extends AbstractZoneCommand {
      * @param dataNodesAutoAdjustScaleUp Timeout in seconds between node added topology event itself and data nodes switch.
      * @param dataNodesAutoAdjustScaleDown Timeout in seconds between node left topology event itself and data nodes switch.
      * @param filter Nodes filter.
-     * @param dataStorageParams Data storage params.
+     * @param storageProfileParams Storage profiles params.
      * @throws CatalogValidationException if any of restrictions above is violated.
      */
     private AlterZoneCommand(
@@ -79,7 +79,7 @@ public class AlterZoneCommand extends AbstractZoneCommand {
             @Nullable Integer dataNodesAutoAdjustScaleUp,
             @Nullable Integer dataNodesAutoAdjustScaleDown,
             @Nullable String filter,
-            @Nullable DataStorageParams dataStorageParams
+            @Nullable List<StorageProfileParams> storageProfileParams
     ) throws CatalogValidationException {
         super(zoneName);
 
@@ -89,7 +89,7 @@ public class AlterZoneCommand extends AbstractZoneCommand {
         this.dataNodesAutoAdjustScaleUp = dataNodesAutoAdjustScaleUp;
         this.dataNodesAutoAdjustScaleDown = dataNodesAutoAdjustScaleDown;
         this.filter = filter;
-        this.dataStorageParams = dataStorageParams;
+        this.storageProfileParams = storageProfileParams;
 
         validate();
     }
@@ -118,8 +118,8 @@ public class AlterZoneCommand extends AbstractZoneCommand {
             scaleDown = dataNodesAutoAdjustScaleDown;
         }
 
-        CatalogDataStorageDescriptor dataStorageDescriptor = dataStorageParams != null
-                ? fromParams(dataStorageParams) : previous.dataStorage();
+        CatalogStorageProfilesDescriptor storageProfiles = storageProfileParams != null
+                ? fromParams(storageProfileParams) : previous.storageProfiles();
 
         return new CatalogZoneDescriptor(
                 previous.id(),
@@ -130,7 +130,7 @@ public class AlterZoneCommand extends AbstractZoneCommand {
                 Objects.requireNonNullElse(scaleUp, previous.dataNodesAutoAdjustScaleUp()),
                 Objects.requireNonNullElse(scaleDown, previous.dataNodesAutoAdjustScaleDown()),
                 Objects.requireNonNullElse(filter, previous.filter()),
-                dataStorageDescriptor
+                storageProfiles
         );
     }
 
@@ -168,7 +168,7 @@ public class AlterZoneCommand extends AbstractZoneCommand {
 
         private @Nullable String filter;
 
-        private @Nullable DataStorageParams dataStorageParams;
+        private @Nullable List<StorageProfileParams> storageProfileParams;
 
         @Override
         public AlterZoneCommandBuilder zoneName(String zoneName) {
@@ -220,8 +220,8 @@ public class AlterZoneCommand extends AbstractZoneCommand {
         }
 
         @Override
-        public AlterZoneCommandBuilder dataStorageParams(DataStorageParams params) {
-            this.dataStorageParams = params;
+        public AlterZoneCommandBuilder storageProfilesParams(@Nullable List<StorageProfileParams> params) {
+            this.storageProfileParams = params;
 
             return this;
         }
@@ -236,7 +236,8 @@ public class AlterZoneCommand extends AbstractZoneCommand {
                     dataNodesAutoAdjustScaleUp,
                     dataNodesAutoAdjustScaleDown,
                     filter,
-                    dataStorageParams);
+                    storageProfileParams
+            );
         }
     }
 }
diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/AlterZoneCommandBuilder.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/AlterZoneCommandBuilder.java
index ecdd6cb8d5..ce81764a6c 100644
--- a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/AlterZoneCommandBuilder.java
+++ b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/AlterZoneCommandBuilder.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.catalog.commands;
 
+import java.util.List;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -76,10 +77,10 @@ public interface AlterZoneCommandBuilder extends AbstractZoneCommandBuilder<Alte
     AlterZoneCommandBuilder filter(@Nullable String filter);
 
     /**
-     * Sets the data storage.
+     * Sets storage profiles.
      *
-     * @param params Optional data storage params.
+     * @param params Optional storage profiles params.
      * @return This instance.
      */
-    AlterZoneCommandBuilder dataStorageParams(@Nullable DataStorageParams params);
+    AlterZoneCommandBuilder storageProfilesParams(@Nullable List<StorageProfileParams> params);
 }
diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CatalogUtils.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CatalogUtils.java
index 84d397f97e..7c6bc8e1c7 100644
--- a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CatalogUtils.java
+++ b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CatalogUtils.java
@@ -36,14 +36,14 @@ import org.apache.ignite.internal.catalog.CatalogValidationException;
 import org.apache.ignite.internal.catalog.DistributionZoneNotFoundValidationException;
 import org.apache.ignite.internal.catalog.IndexNotFoundValidationException;
 import org.apache.ignite.internal.catalog.TableNotFoundValidationException;
-import org.apache.ignite.internal.catalog.descriptors.CatalogDataStorageDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.CatalogIndexDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.CatalogSchemaDescriptor;
+import org.apache.ignite.internal.catalog.descriptors.CatalogStorageProfileDescriptor;
+import org.apache.ignite.internal.catalog.descriptors.CatalogStorageProfilesDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.CatalogTableColumnDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.CatalogTableDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.CatalogZoneDescriptor;
 import org.apache.ignite.internal.hlc.HybridTimestamp;
-import org.apache.ignite.internal.lang.IgniteSystemProperties;
 import org.apache.ignite.internal.type.NativeTypes;
 import org.apache.ignite.sql.ColumnType;
 import org.jetbrains.annotations.Nullable;
@@ -64,14 +64,6 @@ public class CatalogUtils {
      */
     public static final String DEFAULT_FILTER = "$..*";
 
-    /** Default distribution zone storage engine. */
-    // TODO: IGNITE-19719 Should be defined differently
-    public static final String DEFAULT_STORAGE_ENGINE = IgniteSystemProperties.getString("IGNITE_DEFAULT_STORAGE_ENGINE", "aipersist");
-
-    /** Default distribution zone storage engine data region. */
-    // TODO: IGNITE-19719 Must be storage engine specific
-    public static final String DEFAULT_DATA_REGION = "default";
-
     /** Infinite value for the distribution zone timers. */
     public static final int INFINITE_TIMER_VALUE = Integer.MAX_VALUE;
 
@@ -156,8 +148,8 @@ public class CatalogUtils {
      * @return Distribution zone descriptor.
      */
     public static CatalogZoneDescriptor fromParams(int id, String zoneName) {
-        DataStorageParams dataStorageParams =
-                DataStorageParams.builder().engine(DEFAULT_STORAGE_ENGINE).dataRegion(DEFAULT_DATA_REGION).build();
+        List<StorageProfileParams> storageProfiles =
+                List.of(StorageProfileParams.builder().storageProfile(CatalogService.DEFAULT_STORAGE_PROFILE).build());
 
         return new CatalogZoneDescriptor(
                 id,
@@ -168,19 +160,20 @@ public class CatalogUtils {
                 IMMEDIATE_TIMER_VALUE,
                 INFINITE_TIMER_VALUE,
                 DEFAULT_FILTER,
-                fromParams(dataStorageParams)
+                fromParams(storageProfiles)
         );
     }
 
     /**
-     * Converts DataStorageParams to descriptor.
+     * Converts StorageProfileParams to descriptor.
      *
      * @param params Parameters.
-     * @return Data storage descriptor.
+     * @return Storage profiles descriptor.
      */
-    // TODO: IGNITE-19719 Must be storage engine specific
-    public static CatalogDataStorageDescriptor fromParams(DataStorageParams params) {
-        return new CatalogDataStorageDescriptor(params.engine(), params.dataRegion());
+    public static CatalogStorageProfilesDescriptor fromParams(List<StorageProfileParams> params) {
+        return new CatalogStorageProfilesDescriptor(
+                params.stream().map(p -> new CatalogStorageProfileDescriptor(p.storageProfile())).collect(toList())
+        );
     }
 
     /**
diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CreateTableCommand.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CreateTableCommand.java
index 24c8e32209..bb5dd51571 100644
--- a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CreateTableCommand.java
+++ b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CreateTableCommand.java
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.catalog.commands;
 import static java.util.Objects.requireNonNullElse;
 import static java.util.stream.Collectors.toList;
 import static org.apache.ignite.internal.catalog.CatalogParamsValidationUtils.ensureNoTableIndexOrSysViewExistsWithGivenName;
+import static org.apache.ignite.internal.catalog.CatalogParamsValidationUtils.ensureZoneContainsTablesStorageProfile;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.pkIndexName;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.schemaOrThrow;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.zoneOrThrow;
@@ -69,6 +70,8 @@ public class CreateTableCommand extends AbstractTableCommand {
 
     private final String zoneName;
 
+    private String storageProfile;
+
     /**
      * Constructs the object.
      *
@@ -87,7 +90,8 @@ public class CreateTableCommand extends AbstractTableCommand {
             TablePrimaryKey primaryKey,
             List<String> colocationColumns,
             List<ColumnParams> columns,
-            String zoneName
+            String zoneName,
+            String storageProfile
     ) throws CatalogValidationException {
         super(schemaName, tableName);
 
@@ -95,6 +99,7 @@ public class CreateTableCommand extends AbstractTableCommand {
         this.colocationColumns = copyOrNull(colocationColumns);
         this.columns = copyOrNull(columns);
         this.zoneName = zoneName;
+        this.storageProfile = storageProfile;
 
         validate();
     }
@@ -107,6 +112,12 @@ public class CreateTableCommand extends AbstractTableCommand {
 
         CatalogZoneDescriptor zone = zoneOrThrow(catalog, zoneName);
 
+        if (storageProfile == null) {
+            storageProfile = zone.storageProfiles().defaultProfile().storageProfile();
+        }
+
+        ensureZoneContainsTablesStorageProfile(zone, storageProfile);
+
         int id = catalog.objectIdGenState();
         int tableId = id++;
         int pkIndexId = id++;
@@ -119,7 +130,8 @@ public class CreateTableCommand extends AbstractTableCommand {
                 zone.id(),
                 columns.stream().map(CatalogUtils::fromParams).collect(toList()),
                 primaryKey.columns(),
-                colocationColumns
+                colocationColumns,
+                storageProfile
         );
 
         String indexName = pkIndexName(tableName);
@@ -237,6 +249,8 @@ public class CreateTableCommand extends AbstractTableCommand {
 
         private String zoneName;
 
+        private String storageProfile;
+
         @Override
         public CreateTableCommandBuilder schemaName(String schemaName) {
             this.schemaName = schemaName;
@@ -279,6 +293,13 @@ public class CreateTableCommand extends AbstractTableCommand {
             return this;
         }
 
+        @Override
+        public CreateTableCommandBuilder storageProfile(String storageProfile) {
+            this.storageProfile = storageProfile;
+
+            return this;
+        }
+
         @Override
         public CatalogCommand build() {
             String zoneName = requireNonNullElse(this.zoneName, CatalogService.DEFAULT_ZONE_NAME);
@@ -301,7 +322,8 @@ public class CreateTableCommand extends AbstractTableCommand {
                     primaryKey,
                     colocationColumns,
                     columns,
-                    zoneName
+                    zoneName,
+                    storageProfile
             );
         }
     }
diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CreateTableCommandBuilder.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CreateTableCommandBuilder.java
index 60b995816b..4d497bcd92 100644
--- a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CreateTableCommandBuilder.java
+++ b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CreateTableCommandBuilder.java
@@ -42,6 +42,9 @@ public interface CreateTableCommandBuilder extends AbstractTableCommandBuilder<C
      */
     CreateTableCommandBuilder colocationColumns(@Nullable List<String> colocationColumns);
 
-    /** A name of the zone to create new table in. Should not be null or blank. */
+    /** A name of the zone to create new table in. Should not be blank. */
     CreateTableCommandBuilder zone(@Nullable String zoneName);
+
+    /** A name of the table's storage profile. Table's zone must contain this storage profile. */
+    CreateTableCommandBuilder storageProfile(@Nullable String storageProfile);
 }
diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CreateZoneCommand.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CreateZoneCommand.java
index a0288fcef1..4086364034 100644
--- a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CreateZoneCommand.java
+++ b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CreateZoneCommand.java
@@ -18,13 +18,12 @@
 package org.apache.ignite.internal.catalog.commands;
 
 import static org.apache.ignite.internal.catalog.CatalogParamsValidationUtils.validateField;
+import static org.apache.ignite.internal.catalog.CatalogParamsValidationUtils.validateStorageProfiles;
 import static org.apache.ignite.internal.catalog.CatalogParamsValidationUtils.validateZoneDataNodesAutoAdjustParametersCompatibility;
 import static org.apache.ignite.internal.catalog.CatalogParamsValidationUtils.validateZoneFilter;
-import static org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_DATA_REGION;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_FILTER;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_PARTITION_COUNT;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_REPLICA_COUNT;
-import static org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_STORAGE_ENGINE;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.IMMEDIATE_TIMER_VALUE;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.INFINITE_TIMER_VALUE;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.MAX_PARTITION_COUNT;
@@ -64,7 +63,7 @@ public class CreateZoneCommand extends AbstractZoneCommand {
 
     private final @Nullable String filter;
 
-    private final @Nullable DataStorageParams dataStorageParams;
+    private final List<StorageProfileParams> storageProfileParams;
 
     /**
      * Constructor.
@@ -76,7 +75,7 @@ public class CreateZoneCommand extends AbstractZoneCommand {
      * @param dataNodesAutoAdjustScaleUp Timeout in seconds between node added topology event itself and data nodes switch.
      * @param dataNodesAutoAdjustScaleDown Timeout in seconds between node left topology event itself and data nodes switch.
      * @param filter Nodes filter.
-     * @param dataStorageParams Data storage params.
+     * @param storageProfileParams Storage profile params.
      * @throws CatalogValidationException if any of restrictions above is violated.
      */
     private CreateZoneCommand(
@@ -87,7 +86,7 @@ public class CreateZoneCommand extends AbstractZoneCommand {
             @Nullable Integer dataNodesAutoAdjustScaleUp,
             @Nullable Integer dataNodesAutoAdjustScaleDown,
             @Nullable String filter,
-            @Nullable DataStorageParams dataStorageParams
+            List<StorageProfileParams> storageProfileParams
     ) throws CatalogValidationException {
         super(zoneName);
 
@@ -97,7 +96,7 @@ public class CreateZoneCommand extends AbstractZoneCommand {
         this.dataNodesAutoAdjustScaleUp = dataNodesAutoAdjustScaleUp;
         this.dataNodesAutoAdjustScaleDown = dataNodesAutoAdjustScaleDown;
         this.filter = filter;
-        this.dataStorageParams = dataStorageParams;
+        this.storageProfileParams = storageProfileParams;
 
         validate();
     }
@@ -117,10 +116,6 @@ public class CreateZoneCommand extends AbstractZoneCommand {
     }
 
     private CatalogZoneDescriptor descriptor(int objectId) {
-        DataStorageParams dataStorageParams0 = dataStorageParams != null
-                ? dataStorageParams
-                : DataStorageParams.builder().engine(DEFAULT_STORAGE_ENGINE).dataRegion(DEFAULT_DATA_REGION).build();
-
         CatalogZoneDescriptor zone = new CatalogZoneDescriptor(
                 objectId,
                 zoneName,
@@ -133,7 +128,7 @@ public class CreateZoneCommand extends AbstractZoneCommand {
                 ),
                 Objects.requireNonNullElse(dataNodesAutoAdjustScaleDown, INFINITE_TIMER_VALUE),
                 Objects.requireNonNullElse(filter, DEFAULT_FILTER),
-                fromParams(dataStorageParams0)
+                fromParams(storageProfileParams)
         );
 
         return zone;
@@ -153,6 +148,8 @@ public class CreateZoneCommand extends AbstractZoneCommand {
         );
 
         validateZoneFilter(filter);
+
+        validateStorageProfiles(storageProfileParams);
     }
 
     /**
@@ -173,7 +170,7 @@ public class CreateZoneCommand extends AbstractZoneCommand {
 
         private @Nullable String filter;
 
-        private @Nullable DataStorageParams dataStorageParams;
+        private List<StorageProfileParams> storageProfileParams;
 
         @Override
         public CreateZoneCommandBuilder zoneName(String zoneName) {
@@ -225,8 +222,8 @@ public class CreateZoneCommand extends AbstractZoneCommand {
         }
 
         @Override
-        public CreateZoneCommandBuilder dataStorageParams(DataStorageParams params) {
-            this.dataStorageParams = params;
+        public CreateZoneCommandBuilder storageProfilesParams(List<StorageProfileParams> params) {
+            this.storageProfileParams = params;
 
             return this;
         }
@@ -241,7 +238,8 @@ public class CreateZoneCommand extends AbstractZoneCommand {
                     dataNodesAutoAdjustScaleUp,
                     dataNodesAutoAdjustScaleDown,
                     filter,
-                    dataStorageParams);
+                    storageProfileParams
+            );
         }
     }
 }
diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CreateZoneCommandBuilder.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CreateZoneCommandBuilder.java
index 8cc50facc7..00ade113a7 100644
--- a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CreateZoneCommandBuilder.java
+++ b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CreateZoneCommandBuilder.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.catalog.commands;
 
+import java.util.List;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -76,10 +77,10 @@ public interface CreateZoneCommandBuilder extends AbstractZoneCommandBuilder<Cre
     CreateZoneCommandBuilder filter(@Nullable String filter);
 
     /**
-     * Sets the data storage.
+     * Sets the storage profiles.
      *
-     * @param params Optional data storage params.
+     * @param params Optional storage profile params.
      * @return This instance.
      */
-    CreateZoneCommandBuilder dataStorageParams(@Nullable DataStorageParams params);
+    CreateZoneCommandBuilder storageProfilesParams(List<StorageProfileParams> params);
 }
diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/RenameZoneCommand.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/RenameZoneCommand.java
index 8856c9989e..75f927c28a 100644
--- a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/RenameZoneCommand.java
+++ b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/RenameZoneCommand.java
@@ -74,7 +74,7 @@ public class RenameZoneCommand extends AbstractZoneCommand {
                 zone.dataNodesAutoAdjustScaleUp(),
                 zone.dataNodesAutoAdjustScaleDown(),
                 zone.filter(),
-                zone.dataStorage()
+                zone.storageProfiles()
         );
 
         return List.of(new AlterZoneEntry(descriptor));
diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/DataStorageParams.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/StorageProfileParams.java
similarity index 50%
rename from modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/DataStorageParams.java
rename to modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/StorageProfileParams.java
index 7b81ead830..38e2a3670a 100644
--- a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/DataStorageParams.java
+++ b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/StorageProfileParams.java
@@ -18,69 +18,46 @@
 package org.apache.ignite.internal.catalog.commands;
 
 /**
- * Define a data storage.
+ *  Define a storage profile.
  */
-// TODO: IGNITE-19719 Must be storage engine specific
-// TODO: IGNITE-19719 Implement validation of engines and their parameters
-public class DataStorageParams {
+public class StorageProfileParams {
     /** Creates parameters builder. */
-    public static Builder builder() {
-        return new Builder();
+    public static StorageProfileParams.Builder builder() {
+        return new StorageProfileParams.Builder();
     }
 
-    private String engine;
-
-    private String dataRegion;
+    private String storageProfile;
 
     /**
-     * Returns the storage engine name.
+     * Returns storage profiles.
      */
-    public String engine() {
-        return engine;
-    }
-
-    /**
-     * Returns the data region name within the storage engine.
-     */
-    public String dataRegion() {
-        return dataRegion;
+    public String storageProfile() {
+        return storageProfile;
     }
 
     /** Parameters builder. */
     public static class Builder {
-        private DataStorageParams params;
+        private StorageProfileParams params;
 
         private Builder() {
-            params = new DataStorageParams();
-        }
-
-        /**
-         * Sets the storage engine name.
-         *
-         * @param engine Storage engine name.
-         * @return {@code this}.
-         */
-        public Builder engine(String engine) {
-            params.engine = engine;
-
-            return this;
+            params = new StorageProfileParams();
         }
 
         /**
-         * Sets the data region name within the storage engine.
+         * Sets the storage profiles.
          *
-         * @param dataRegion Data region name within the storage engine.
+         * @param storageProfiles Storage profiles.
          * @return {@code this}.
          */
-        public Builder dataRegion(String dataRegion) {
-            params.dataRegion = dataRegion;
+        public StorageProfileParams.Builder storageProfile(String storageProfiles) {
+            params.storageProfile = storageProfiles;
 
             return this;
         }
 
         /** Builds parameters. */
-        public DataStorageParams build() {
-            DataStorageParams params0 = params;
+        public StorageProfileParams build() {
+            StorageProfileParams params0 = params;
 
             params = null;
 
diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/CatalogDataStorageDescriptor.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/CatalogDataStorageDescriptor.java
deleted file mode 100644
index 9842f31378..0000000000
--- a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/CatalogDataStorageDescriptor.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.catalog.descriptors;
-
-import static org.apache.ignite.internal.catalog.storage.serialization.CatalogSerializationUtils.readNullableString;
-import static org.apache.ignite.internal.catalog.storage.serialization.CatalogSerializationUtils.writeNullableString;
-
-import java.io.IOException;
-import org.apache.ignite.internal.catalog.storage.serialization.CatalogObjectSerializer;
-import org.apache.ignite.internal.tostring.S;
-import org.apache.ignite.internal.util.io.IgniteDataInput;
-import org.apache.ignite.internal.util.io.IgniteDataOutput;
-
-/**
- * Data storage descriptor.
- */
-// TODO: IGNITE-19719 Must be storage engine specific
-public class CatalogDataStorageDescriptor {
-    public static final CatalogObjectSerializer<CatalogDataStorageDescriptor> SERIALIZER = new DataStorageDescriptorSerializer();
-
-    private final String engine;
-
-    private final String dataRegion;
-
-    /**
-     * Constructor.
-     *
-     * @param engine Storage engine name.
-     * @param dataRegion Data region name within the storage engine.
-     */
-    public CatalogDataStorageDescriptor(String engine, String dataRegion) {
-        this.engine = engine;
-        this.dataRegion = dataRegion;
-    }
-
-    /**
-     * Returns the storage engine name.
-     */
-    public String engine() {
-        return engine;
-    }
-
-    /**
-     * Returns the data region name within the storage engine.
-     */
-    public String dataRegion() {
-        return dataRegion;
-    }
-
-    @Override
-    public String toString() {
-        return S.toString(this);
-    }
-
-    /**
-     * Serializer for {@link CatalogDataStorageDescriptor}.
-     */
-    private static class DataStorageDescriptorSerializer implements CatalogObjectSerializer<CatalogDataStorageDescriptor> {
-        @Override
-        public CatalogDataStorageDescriptor readFrom(IgniteDataInput input) throws IOException {
-            String engine = input.readUTF();
-            String region = readNullableString(input);
-
-            return new CatalogDataStorageDescriptor(engine, region);
-        }
-
-        @Override
-        public void writeTo(CatalogDataStorageDescriptor descriptor, IgniteDataOutput output) throws IOException {
-            output.writeUTF(descriptor.engine());
-            writeNullableString(descriptor.dataRegion(), output);
-        }
-    }
-}
diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/CatalogStorageProfileDescriptor.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/CatalogStorageProfileDescriptor.java
new file mode 100644
index 0000000000..aa7103e509
--- /dev/null
+++ b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/CatalogStorageProfileDescriptor.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.catalog.descriptors;
+
+import java.io.IOException;
+import org.apache.ignite.internal.catalog.storage.serialization.CatalogObjectSerializer;
+import org.apache.ignite.internal.tostring.S;
+import org.apache.ignite.internal.util.io.IgniteDataInput;
+import org.apache.ignite.internal.util.io.IgniteDataOutput;
+
+/**
+ * Storage profile descriptor.
+ */
+public class CatalogStorageProfileDescriptor {
+    public static final CatalogObjectSerializer<CatalogStorageProfileDescriptor> SERIALIZER = new StorageProfileDescriptorSerializer();
+
+    private final String storageProfile;
+
+    /**
+     * Constructor.
+     *
+     * @param storageProfile Storage profile name.
+     */
+    public CatalogStorageProfileDescriptor(String storageProfile) {
+        this.storageProfile = storageProfile;
+    }
+
+    @Override
+    public String toString() {
+        return S.toString(this);
+    }
+
+    /**
+     * Storage profile name.
+     *
+     * @return Name of the storage profile.
+     */
+    public String storageProfile() {
+        return storageProfile;
+    }
+
+    /**
+     * Serializer for {@link CatalogStorageProfilesDescriptor}.
+     */
+    private static class StorageProfileDescriptorSerializer implements CatalogObjectSerializer<CatalogStorageProfileDescriptor> {
+        @Override
+        public CatalogStorageProfileDescriptor readFrom(IgniteDataInput input) throws IOException {
+            String storageProfileDescriptor = input.readUTF();
+
+            return new CatalogStorageProfileDescriptor(storageProfileDescriptor);
+        }
+
+        @Override
+        public void writeTo(CatalogStorageProfileDescriptor descriptor, IgniteDataOutput output) throws IOException {
+            output.writeUTF(descriptor.storageProfile());
+        }
+    }
+}
diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/CatalogStorageProfilesDescriptor.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/CatalogStorageProfilesDescriptor.java
new file mode 100644
index 0000000000..16409d25b7
--- /dev/null
+++ b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/CatalogStorageProfilesDescriptor.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.catalog.descriptors;
+
+import static org.apache.ignite.internal.catalog.storage.serialization.CatalogSerializationUtils.readList;
+import static org.apache.ignite.internal.catalog.storage.serialization.CatalogSerializationUtils.writeList;
+
+import java.io.IOException;
+import java.util.List;
+import org.apache.ignite.internal.catalog.storage.serialization.CatalogObjectSerializer;
+import org.apache.ignite.internal.tostring.S;
+import org.apache.ignite.internal.util.io.IgniteDataInput;
+import org.apache.ignite.internal.util.io.IgniteDataOutput;
+
+/**
+ * Storage profiles descriptor.
+ */
+public class CatalogStorageProfilesDescriptor {
+    public static final CatalogObjectSerializer<CatalogStorageProfilesDescriptor> SERIALIZER = new StorageProfilesDescriptorSerializer();
+
+    private final List<CatalogStorageProfileDescriptor> storageProfiles;
+
+    private final CatalogStorageProfileDescriptor defaultStorageProfile;
+
+    /**
+     * Constructor.
+     *
+     * @param storageProfiles List of storage profile descriptors.
+     */
+    public CatalogStorageProfilesDescriptor(List<CatalogStorageProfileDescriptor> storageProfiles) {
+        this.storageProfiles = storageProfiles;
+        this.defaultStorageProfile = storageProfiles.isEmpty() ? null : storageProfiles.get(0);
+    }
+
+    /**
+     * List of storage profile descriptors.
+     *
+     * @return List of storage profile descriptors.
+     */
+    public List<CatalogStorageProfileDescriptor> profiles() {
+        return storageProfiles;
+    }
+
+    /**
+     * Default storage profile.
+     *
+     * @return Default storage profile.
+     */
+    public CatalogStorageProfileDescriptor defaultProfile() {
+        return defaultStorageProfile;
+    }
+
+    @Override
+    public String toString() {
+        return S.toString(this);
+    }
+
+    /**
+     * Serializer for {@link CatalogStorageProfilesDescriptor}.
+     */
+    private static class StorageProfilesDescriptorSerializer implements CatalogObjectSerializer<CatalogStorageProfilesDescriptor> {
+        @Override
+        public CatalogStorageProfilesDescriptor readFrom(IgniteDataInput input) throws IOException {
+            List<CatalogStorageProfileDescriptor> storageProfileDescriptors =
+                    readList(CatalogStorageProfileDescriptor.SERIALIZER, input);
+
+            return new CatalogStorageProfilesDescriptor(storageProfileDescriptors);
+        }
+
+        @Override
+        public void writeTo(CatalogStorageProfilesDescriptor descriptor, IgniteDataOutput output) throws IOException {
+            writeList(descriptor.storageProfiles, CatalogStorageProfileDescriptor.SERIALIZER, output);
+        }
+    }
+}
diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/CatalogTableDescriptor.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/CatalogTableDescriptor.java
index b8af6f49f8..e8f7b1da43 100644
--- a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/CatalogTableDescriptor.java
+++ b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/CatalogTableDescriptor.java
@@ -63,6 +63,8 @@ public class CatalogTableDescriptor extends CatalogObjectDescriptor {
 
     private long creationToken;
 
+    private String storageProfile;
+
     /**
      * Constructor for new table.
      *
@@ -72,6 +74,7 @@ public class CatalogTableDescriptor extends CatalogObjectDescriptor {
      * @param zoneId Distribution zone ID.
      * @param columns Table column descriptors.
      * @param pkCols Primary key column names.
+     * @param storageProfile Storage profile.
      */
     public CatalogTableDescriptor(
             int id,
@@ -81,10 +84,12 @@ public class CatalogTableDescriptor extends CatalogObjectDescriptor {
             int zoneId,
             List<CatalogTableColumnDescriptor> columns,
             List<String> pkCols,
-            @Nullable List<String> colocationCols
+            @Nullable List<String> colocationCols,
+            String storageProfile
     ) {
         this(id, schemaId, pkIndexId, name, zoneId, columns, pkCols, colocationCols,
-                new CatalogTableSchemaVersions(new TableVersion(columns)), INITIAL_CAUSALITY_TOKEN, INITIAL_CAUSALITY_TOKEN);
+                new CatalogTableSchemaVersions(new TableVersion(columns)),
+                storageProfile, INITIAL_CAUSALITY_TOKEN, INITIAL_CAUSALITY_TOKEN);
     }
 
     /**
@@ -96,6 +101,7 @@ public class CatalogTableDescriptor extends CatalogObjectDescriptor {
      * @param zoneId Distribution zone ID.
      * @param columns Table column descriptors.
      * @param pkCols Primary key column names.
+     * @param storageProfile Storage profile.
      * @param causalityToken Token of the update of the descriptor.
      * @param creationToken Token of the creation of the table descriptor.
      */
@@ -109,6 +115,7 @@ public class CatalogTableDescriptor extends CatalogObjectDescriptor {
             List<String> pkCols,
             @Nullable List<String> colocationCols,
             CatalogTableSchemaVersions schemaVersions,
+            String storageProfile,
             long causalityToken,
             long creationToken
     ) {
@@ -127,6 +134,8 @@ public class CatalogTableDescriptor extends CatalogObjectDescriptor {
 
         this.creationToken = creationToken;
 
+        this.storageProfile = storageProfile;
+
         // TODO: IGNITE-19082 Throw proper exceptions.
         assert !columnsMap.isEmpty() : "No columns.";
 
@@ -141,7 +150,8 @@ public class CatalogTableDescriptor extends CatalogObjectDescriptor {
             String name,
             int tableVersion,
             List<CatalogTableColumnDescriptor> columns,
-            long causalityToken
+            long causalityToken,
+            String storageProfile
     ) {
         CatalogTableSchemaVersions newSchemaVersions = tableVersion == schemaVersions.latestVersion()
                 ? schemaVersions
@@ -150,7 +160,7 @@ public class CatalogTableDescriptor extends CatalogObjectDescriptor {
         return new CatalogTableDescriptor(
                 id(), schemaId, pkIndexId, name, zoneId, columns, primaryKeyColumns, colocationColumns,
                 newSchemaVersions,
-                causalityToken, creationToken
+                storageProfile, causalityToken, creationToken
         );
     }
 
@@ -214,6 +224,10 @@ public class CatalogTableDescriptor extends CatalogObjectDescriptor {
         return creationToken;
     }
 
+    public String storageProfile() {
+        return storageProfile;
+    }
+
     @Override
     public void updateToken(long updateToken) {
         super.updateToken(updateToken);
@@ -233,6 +247,7 @@ public class CatalogTableDescriptor extends CatalogObjectDescriptor {
 
             CatalogTableSchemaVersions schemaVersions = CatalogTableSchemaVersions.SERIALIZER.readFrom(input);
             List<CatalogTableColumnDescriptor> columns = readList(CatalogTableColumnDescriptor.SERIALIZER, input);
+            String storageProfile = input.readUTF();
 
             int schemaId = input.readInt();
             int pkIndexId = input.readInt();
@@ -274,6 +289,7 @@ public class CatalogTableDescriptor extends CatalogObjectDescriptor {
                     primaryKeyColumns,
                     colocationColumns,
                     schemaVersions,
+                    storageProfile,
                     updateToken,
                     creationToken
             );
@@ -286,6 +302,7 @@ public class CatalogTableDescriptor extends CatalogObjectDescriptor {
             output.writeLong(descriptor.updateToken());
             CatalogTableSchemaVersions.SERIALIZER.writeTo(descriptor.schemaVersions(), output);
             writeList(descriptor.columns(), CatalogTableColumnDescriptor.SERIALIZER, output);
+            output.writeUTF(descriptor.storageProfile());
 
             output.writeInt(descriptor.schemaId());
             output.writeInt(descriptor.primaryKeyIndexId());
diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/CatalogZoneDescriptor.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/CatalogZoneDescriptor.java
index 45a7849cab..29b0f3246d 100644
--- a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/CatalogZoneDescriptor.java
+++ b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/CatalogZoneDescriptor.java
@@ -49,8 +49,8 @@ public class CatalogZoneDescriptor extends CatalogObjectDescriptor {
     /** Nodes filer. */
     private final String filter;
 
-    /** Data storage descriptor. */
-    private final CatalogDataStorageDescriptor dataStorage;
+    /** Storage profiles descriptor. */
+    private final CatalogStorageProfilesDescriptor storageProfiles;
 
     /**
      * Constructs a distribution zone descriptor.
@@ -63,7 +63,7 @@ public class CatalogZoneDescriptor extends CatalogObjectDescriptor {
      * @param dataNodesAutoAdjustScaleUp Data nodes auto adjust scale up timeout.
      * @param dataNodesAutoAdjustScaleDown Data nodes auto adjust scale down timeout.
      * @param filter Nodes filter.
-     * @param dataStorage Data storage descriptor.
+     * @param storageProfiles Storage profiles descriptor.
      */
     public CatalogZoneDescriptor(
             int id,
@@ -74,10 +74,10 @@ public class CatalogZoneDescriptor extends CatalogObjectDescriptor {
             int dataNodesAutoAdjustScaleUp,
             int dataNodesAutoAdjustScaleDown,
             String filter,
-            CatalogDataStorageDescriptor dataStorage
+            CatalogStorageProfilesDescriptor storageProfiles
     ) {
         this(id, name, partitions, replicas, dataNodesAutoAdjust, dataNodesAutoAdjustScaleUp, dataNodesAutoAdjustScaleDown,
-                filter, dataStorage, INITIAL_CAUSALITY_TOKEN);
+                filter, storageProfiles, INITIAL_CAUSALITY_TOKEN);
     }
 
     /**
@@ -91,7 +91,6 @@ public class CatalogZoneDescriptor extends CatalogObjectDescriptor {
      * @param dataNodesAutoAdjustScaleUp Data nodes auto adjust scale up timeout.
      * @param dataNodesAutoAdjustScaleDown Data nodes auto adjust scale down timeout.
      * @param filter Nodes filter.
-     * @param dataStorage Data storage descriptor.
      * @param causalityToken Token of the update of the descriptor.
      */
     private CatalogZoneDescriptor(
@@ -103,7 +102,7 @@ public class CatalogZoneDescriptor extends CatalogObjectDescriptor {
             int dataNodesAutoAdjustScaleUp,
             int dataNodesAutoAdjustScaleDown,
             String filter,
-            CatalogDataStorageDescriptor dataStorage,
+            CatalogStorageProfilesDescriptor storageProfiles,
             long causalityToken
     ) {
         super(id, Type.ZONE, name, causalityToken);
@@ -114,7 +113,7 @@ public class CatalogZoneDescriptor extends CatalogObjectDescriptor {
         this.dataNodesAutoAdjustScaleUp = dataNodesAutoAdjustScaleUp;
         this.dataNodesAutoAdjustScaleDown = dataNodesAutoAdjustScaleDown;
         this.filter = filter;
-        this.dataStorage = dataStorage;
+        this.storageProfiles = storageProfiles;
     }
 
     /**
@@ -166,11 +165,10 @@ public class CatalogZoneDescriptor extends CatalogObjectDescriptor {
     }
 
     /**
-     * Returns the data storage descriptor.
+     * Returns the storage profiles descriptor.
      */
-    // TODO: IGNITE-19719 Must be storage engine specific
-    public CatalogDataStorageDescriptor dataStorage() {
-        return dataStorage;
+    public CatalogStorageProfilesDescriptor storageProfiles() {
+        return storageProfiles;
     }
 
     @Override
@@ -188,7 +186,7 @@ public class CatalogZoneDescriptor extends CatalogObjectDescriptor {
             String name = input.readUTF();
             long updateToken = input.readLong();
 
-            CatalogDataStorageDescriptor dataStorageDescriptor = CatalogDataStorageDescriptor.SERIALIZER.readFrom(input);
+            CatalogStorageProfilesDescriptor catalogStorageProfilesDescriptor = CatalogStorageProfilesDescriptor.SERIALIZER.readFrom(input);
 
             int partitions = input.readInt();
             int replicas = input.readInt();
@@ -206,7 +204,7 @@ public class CatalogZoneDescriptor extends CatalogObjectDescriptor {
                     dataNodesAutoAdjustScaleUp,
                     dataNodesAutoAdjustScaleDown,
                     filter,
-                    dataStorageDescriptor,
+                    catalogStorageProfilesDescriptor,
                     updateToken
             );
         }
@@ -217,7 +215,7 @@ public class CatalogZoneDescriptor extends CatalogObjectDescriptor {
             output.writeUTF(descriptor.name());
             output.writeLong(descriptor.updateToken());
 
-            CatalogDataStorageDescriptor.SERIALIZER.writeTo(descriptor.dataStorage(), output);
+            CatalogStorageProfilesDescriptor.SERIALIZER.writeTo(descriptor.storageProfiles(), output);
 
             output.writeInt(descriptor.partitions());
             output.writeInt(descriptor.replicas());
diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/AlterColumnEntry.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/AlterColumnEntry.java
index 94a31540c5..01559774aa 100644
--- a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/AlterColumnEntry.java
+++ b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/AlterColumnEntry.java
@@ -99,7 +99,8 @@ public class AlterColumnEntry implements UpdateEntry, Fireable {
                 currentTableDescriptor.columns().stream()
                         .map(source -> source.name().equals(column.name()) ? column : source)
                         .collect(toList()),
-                causalityToken
+                causalityToken,
+                currentTableDescriptor.storageProfile()
         );
 
         return new Catalog(
diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/DropColumnsEntry.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/DropColumnsEntry.java
index 6b518a0475..99edb275c0 100644
--- a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/DropColumnsEntry.java
+++ b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/DropColumnsEntry.java
@@ -101,7 +101,8 @@ public class DropColumnsEntry implements UpdateEntry, Fireable {
                 currentTableDescriptor.columns().stream()
                         .filter(col -> !columns.contains(col.name()))
                         .collect(toList()),
-                causalityToken
+                causalityToken,
+                currentTableDescriptor.storageProfile()
         );
 
         return new Catalog(
diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/NewColumnsEntry.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/NewColumnsEntry.java
index 92de394533..6db12c99bd 100644
--- a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/NewColumnsEntry.java
+++ b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/NewColumnsEntry.java
@@ -97,7 +97,8 @@ public class NewColumnsEntry implements UpdateEntry, Fireable {
                 currentTableDescriptor.name(),
                 currentTableDescriptor.tableVersion() + 1,
                 CollectionUtils.concat(currentTableDescriptor.columns(), descriptors),
-                causalityToken
+                causalityToken,
+                currentTableDescriptor.storageProfile()
         );
 
         return new Catalog(
diff --git a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/RenameTableEntry.java b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/RenameTableEntry.java
index dde0cdae5b..f4ba1c6c67 100644
--- a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/RenameTableEntry.java
+++ b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/RenameTableEntry.java
@@ -71,7 +71,8 @@ public class RenameTableEntry implements UpdateEntry, Fireable {
                 newTableName,
                 tableDescriptor.tableVersion() + 1,
                 tableDescriptor.columns(),
-                causalityToken
+                causalityToken,
+                tableDescriptor.storageProfile()
         );
 
         return new Catalog(
diff --git a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogManagerDescriptorCausalityTokenTest.java b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogManagerDescriptorCausalityTokenTest.java
index 1ab979ce55..6dabac7392 100644
--- a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogManagerDescriptorCausalityTokenTest.java
+++ b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogManagerDescriptorCausalityTokenTest.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.catalog;
 
 import static org.apache.ignite.internal.catalog.CatalogManagerImpl.INITIAL_CAUSALITY_TOKEN;
 import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_SCHEMA_NAME;
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_ZONE_NAME;
 import static org.apache.ignite.internal.catalog.CatalogTestUtils.addColumnParams;
 import static org.apache.ignite.internal.catalog.CatalogTestUtils.columnParams;
@@ -44,6 +45,7 @@ import java.util.List;
 import org.apache.ignite.internal.catalog.commands.AlterZoneCommand;
 import org.apache.ignite.internal.catalog.commands.CreateZoneCommand;
 import org.apache.ignite.internal.catalog.commands.RenameZoneCommand;
+import org.apache.ignite.internal.catalog.commands.StorageProfileParams;
 import org.apache.ignite.internal.catalog.descriptors.CatalogHashIndexDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.CatalogSchemaDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.CatalogSortedIndexDescriptor;
@@ -342,7 +344,10 @@ public class CatalogManagerDescriptorCausalityTokenTest extends BaseCatalogManag
     public void testCreateZone() {
         String zoneName = ZONE_NAME + 1;
 
-        CatalogCommand cmd = CreateZoneCommand.builder().zoneName(zoneName).build();
+        CatalogCommand cmd = CreateZoneCommand.builder()
+                .zoneName(zoneName)
+                .storageProfilesParams(List.of(StorageProfileParams.builder().storageProfile(DEFAULT_STORAGE_PROFILE).build()))
+                .build();
 
         assertThat(manager.execute(cmd), willCompleteSuccessfully());
 
@@ -365,7 +370,10 @@ public class CatalogManagerDescriptorCausalityTokenTest extends BaseCatalogManag
     public void testRenameZone() {
         String zoneName = ZONE_NAME + 1;
 
-        CatalogCommand cmd = CreateZoneCommand.builder().zoneName(zoneName).build();
+        CatalogCommand cmd = CreateZoneCommand.builder()
+                .zoneName(zoneName)
+                .storageProfilesParams(List.of(StorageProfileParams.builder().storageProfile(DEFAULT_STORAGE_PROFILE).build()))
+                .build();
 
         assertThat(manager.execute(cmd), willCompleteSuccessfully());
 
@@ -411,9 +419,14 @@ public class CatalogManagerDescriptorCausalityTokenTest extends BaseCatalogManag
                 .dataNodesAutoAdjustScaleUp(3)
                 .dataNodesAutoAdjustScaleDown(4)
                 .filter("newExpression")
+                .storageProfilesParams(List.of(StorageProfileParams.builder().storageProfile(DEFAULT_STORAGE_PROFILE).build()))
                 .build();
 
-        CatalogCommand cmd = CreateZoneCommand.builder().zoneName(zoneName).filter("expression").build();
+        CatalogCommand cmd = CreateZoneCommand.builder()
+                .zoneName(zoneName)
+                .storageProfilesParams(List.of(StorageProfileParams.builder().storageProfile(DEFAULT_STORAGE_PROFILE).build()))
+                .filter("expression")
+                .build();
 
         assertThat(manager.execute(cmd), willCompleteSuccessfully());
         CatalogZoneDescriptor zone = manager.zone(zoneName, clock.nowLong());
diff --git a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogManagerSelfTest.java b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogManagerSelfTest.java
index 6b885f03e6..925118edf9 100644
--- a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogManagerSelfTest.java
+++ b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogManagerSelfTest.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.catalog;
 
 import static java.util.stream.Collectors.toList;
 import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_SCHEMA_NAME;
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_ZONE_NAME;
 import static org.apache.ignite.internal.catalog.CatalogService.SYSTEM_SCHEMA_NAME;
 import static org.apache.ignite.internal.catalog.CatalogTestUtils.addColumnParams;
@@ -28,13 +29,11 @@ import static org.apache.ignite.internal.catalog.CatalogTestUtils.columnParams;
 import static org.apache.ignite.internal.catalog.CatalogTestUtils.columnParamsBuilder;
 import static org.apache.ignite.internal.catalog.CatalogTestUtils.dropColumnParams;
 import static org.apache.ignite.internal.catalog.CatalogTestUtils.initializeColumnWithDefaults;
-import static org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_DATA_REGION;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_FILTER;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_PARTITION_COUNT;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_PRECISION;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_REPLICA_COUNT;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_SCALE;
-import static org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_STORAGE_ENGINE;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.IMMEDIATE_TIMER_VALUE;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.INFINITE_TIMER_VALUE;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.pkIndexName;
@@ -105,7 +104,6 @@ import org.apache.ignite.internal.catalog.commands.CatalogUtils;
 import org.apache.ignite.internal.catalog.commands.ColumnParams;
 import org.apache.ignite.internal.catalog.commands.ColumnParams.Builder;
 import org.apache.ignite.internal.catalog.commands.CreateZoneCommand;
-import org.apache.ignite.internal.catalog.commands.DataStorageParams;
 import org.apache.ignite.internal.catalog.commands.DefaultValue;
 import org.apache.ignite.internal.catalog.commands.DropIndexCommand;
 import org.apache.ignite.internal.catalog.commands.DropZoneCommand;
@@ -114,6 +112,7 @@ import org.apache.ignite.internal.catalog.commands.RemoveIndexCommand;
 import org.apache.ignite.internal.catalog.commands.RenameTableCommand;
 import org.apache.ignite.internal.catalog.commands.RenameZoneCommand;
 import org.apache.ignite.internal.catalog.commands.StartBuildingIndexCommand;
+import org.apache.ignite.internal.catalog.commands.StorageProfileParams;
 import org.apache.ignite.internal.catalog.descriptors.CatalogHashIndexDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.CatalogIndexDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.CatalogIndexDescriptor.CatalogIndexDescriptorType;
@@ -197,8 +196,6 @@ public class CatalogManagerSelfTest extends BaseCatalogManagerTest {
         assertEquals(INFINITE_TIMER_VALUE, zone.dataNodesAutoAdjust());
         assertEquals(IMMEDIATE_TIMER_VALUE, zone.dataNodesAutoAdjustScaleUp());
         assertEquals(INFINITE_TIMER_VALUE, zone.dataNodesAutoAdjustScaleDown());
-        assertEquals(DEFAULT_STORAGE_ENGINE, zone.dataStorage().engine());
-        assertEquals(DEFAULT_DATA_REGION, zone.dataStorage().dataRegion());
 
         // System schema should exist.
 
@@ -1324,7 +1321,7 @@ public class CatalogManagerSelfTest extends BaseCatalogManagerTest {
                 .replicas(15)
                 .dataNodesAutoAdjust(73)
                 .filter("expression")
-                .dataStorageParams(DataStorageParams.builder().engine("test_engine").dataRegion("test_region").build())
+                .storageProfilesParams(List.of(StorageProfileParams.builder().storageProfile("test_profile").build()))
                 .build();
 
         assertThat(manager.execute(cmd), willCompleteSuccessfully());
@@ -1351,15 +1348,17 @@ public class CatalogManagerSelfTest extends BaseCatalogManagerTest {
         assertEquals(INFINITE_TIMER_VALUE, zone.dataNodesAutoAdjustScaleUp());
         assertEquals(INFINITE_TIMER_VALUE, zone.dataNodesAutoAdjustScaleDown());
         assertEquals("expression", zone.filter());
-        assertEquals("test_engine", zone.dataStorage().engine());
-        assertEquals("test_region", zone.dataStorage().dataRegion());
+        assertEquals("test_profile", zone.storageProfiles().profiles().get(0).storageProfile());
     }
 
     @Test
     public void testDropZone() {
         String zoneName = ZONE_NAME + 1;
 
-        CatalogCommand cmd = CreateZoneCommand.builder().zoneName(zoneName).build();
+        CatalogCommand cmd = CreateZoneCommand.builder()
+                .zoneName(zoneName)
+                .storageProfilesParams(List.of(StorageProfileParams.builder().storageProfile(DEFAULT_STORAGE_PROFILE).build()))
+                .build();
 
         assertThat(manager.execute(cmd), willCompleteSuccessfully());
 
@@ -1397,6 +1396,7 @@ public class CatalogManagerSelfTest extends BaseCatalogManagerTest {
                 .zoneName(zoneName)
                 .partitions(42)
                 .replicas(15)
+                .storageProfilesParams(List.of(StorageProfileParams.builder().storageProfile(DEFAULT_STORAGE_PROFILE).build()))
                 .build();
 
         assertThat(manager.execute(cmd), willCompleteSuccessfully());
@@ -1441,6 +1441,7 @@ public class CatalogManagerSelfTest extends BaseCatalogManagerTest {
                 .zoneName(DEFAULT_ZONE_NAME)
                 .partitions(42)
                 .replicas(15)
+                .storageProfilesParams(List.of(StorageProfileParams.builder().storageProfile(DEFAULT_STORAGE_PROFILE).build()))
                 .build();
         assertThat(manager.execute(cmd), willThrow(IgniteInternalException.class));
 
@@ -1458,6 +1459,7 @@ public class CatalogManagerSelfTest extends BaseCatalogManagerTest {
                 .replicas(15)
                 .dataNodesAutoAdjust(73)
                 .filter("expression")
+                .storageProfilesParams(List.of(StorageProfileParams.builder().storageProfile(DEFAULT_STORAGE_PROFILE).build()))
                 .build();
 
         CatalogCommand alterCmd = AlterZoneCommand.builder()
@@ -1467,7 +1469,7 @@ public class CatalogManagerSelfTest extends BaseCatalogManagerTest {
                 .dataNodesAutoAdjustScaleUp(3)
                 .dataNodesAutoAdjustScaleDown(4)
                 .filter("newExpression")
-                .dataStorageParams(DataStorageParams.builder().engine("test_engine").dataRegion("test_region").build())
+                .storageProfilesParams(List.of(StorageProfileParams.builder().storageProfile("test_profile").build()))
                 .build();
 
         assertThat(manager.execute(cmd), willCompleteSuccessfully());
@@ -1485,8 +1487,7 @@ public class CatalogManagerSelfTest extends BaseCatalogManagerTest {
         assertEquals(3, zone.dataNodesAutoAdjustScaleUp());
         assertEquals(4, zone.dataNodesAutoAdjustScaleDown());
         assertEquals("newExpression", zone.filter());
-        assertEquals("test_engine", zone.dataStorage().engine());
-        assertEquals("test_region", zone.dataStorage().dataRegion());
+        assertEquals("test_profile", zone.storageProfiles().profiles().get(0).storageProfile());
     }
 
     @Test
@@ -1497,6 +1498,7 @@ public class CatalogManagerSelfTest extends BaseCatalogManagerTest {
                 .zoneName(zoneName)
                 .partitions(42)
                 .replicas(15)
+                .storageProfilesParams(List.of(StorageProfileParams.builder().storageProfile(DEFAULT_STORAGE_PROFILE).build()))
                 .build();
 
         assertThat(manager.execute(cmd), willCompleteSuccessfully());
@@ -1506,6 +1508,7 @@ public class CatalogManagerSelfTest extends BaseCatalogManagerTest {
                 .zoneName(zoneName)
                 .partitions(8)
                 .replicas(1)
+                .storageProfilesParams(List.of(StorageProfileParams.builder().storageProfile(DEFAULT_STORAGE_PROFILE).build()))
                 .build();
 
         assertThat(manager.execute(cmd), willThrowFast(DistributionZoneExistsValidationException.class));
@@ -1528,6 +1531,7 @@ public class CatalogManagerSelfTest extends BaseCatalogManagerTest {
 
         CatalogCommand cmd = CreateZoneCommand.builder()
                 .zoneName(zoneName)
+                .storageProfilesParams(List.of(StorageProfileParams.builder().storageProfile(DEFAULT_STORAGE_PROFILE).build()))
                 .build();
 
         EventListener<CatalogEventParameters> eventListener = mock(EventListener.class);
@@ -1869,7 +1873,16 @@ public class CatalogManagerSelfTest extends BaseCatalogManagerTest {
 
     @Test
     void testCreateZoneWithDefaults() {
-        assertThat(manager.execute(CreateZoneCommand.builder().zoneName(ZONE_NAME + 1).build()), willCompleteSuccessfully());
+        assertThat(
+                manager.execute(
+                        CreateZoneCommand.builder()
+                                .zoneName(ZONE_NAME + 1)
+                                .storageProfilesParams(
+                                        List.of(StorageProfileParams.builder().storageProfile(DEFAULT_STORAGE_PROFILE).build())
+                                ).build()
+                ),
+                willCompleteSuccessfully()
+        );
 
         CatalogZoneDescriptor zone = manager.zone(ZONE_NAME, clock.nowLong());
 
@@ -1879,8 +1892,7 @@ public class CatalogManagerSelfTest extends BaseCatalogManagerTest {
         assertEquals(IMMEDIATE_TIMER_VALUE, zone.dataNodesAutoAdjustScaleUp());
         assertEquals(INFINITE_TIMER_VALUE, zone.dataNodesAutoAdjustScaleDown());
         assertEquals(DEFAULT_FILTER, zone.filter());
-        assertEquals(DEFAULT_STORAGE_ENGINE, zone.dataStorage().engine());
-        assertEquals(DEFAULT_DATA_REGION, zone.dataStorage().dataRegion());
+        assertEquals(DEFAULT_STORAGE_PROFILE, zone.storageProfiles().defaultProfile().storageProfile());
     }
 
     @Test
diff --git a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/commands/AbstractCommandValidationTest.java b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/commands/AbstractCommandValidationTest.java
index 85338d2cfa..0c3ad29e3e 100644
--- a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/commands/AbstractCommandValidationTest.java
+++ b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/commands/AbstractCommandValidationTest.java
@@ -18,10 +18,12 @@
 package org.apache.ignite.internal.catalog.commands;
 
 import static org.apache.ignite.internal.catalog.CatalogManagerImpl.INITIAL_CAUSALITY_TOKEN;
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_LENGTH;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_PRECISION;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_SCALE;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.SYSTEM_SCHEMAS;
+import static org.apache.ignite.internal.catalog.commands.CatalogUtils.fromParams;
 import static org.apache.ignite.sql.ColumnType.INT32;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
@@ -32,6 +34,7 @@ import java.util.List;
 import java.util.NoSuchElementException;
 import java.util.Set;
 import java.util.function.Consumer;
+import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import org.apache.ignite.internal.catalog.Catalog;
 import org.apache.ignite.internal.catalog.CatalogCommand;
@@ -60,7 +63,8 @@ abstract class AbstractCommandValidationTest extends BaseIgniteAbstractTest {
             .build();
 
     private static final CatalogZoneDescriptor DEFAULT_ZONE = new CatalogZoneDescriptor(
-            0, ZONE_NAME, 1, -1, -1, -1, -1, "", null
+            0, ZONE_NAME, 1, -1, -1, -1, -1, "",
+            fromParams(List.of(StorageProfileParams.builder().storageProfile(DEFAULT_STORAGE_PROFILE).build()))
     );
 
     static Stream<Arguments> nullAndBlankStrings() {
@@ -146,6 +150,18 @@ abstract class AbstractCommandValidationTest extends BaseIgniteAbstractTest {
     static CatalogCommand createZoneCommand(String zoneName) {
         return CreateZoneCommand.builder()
                 .zoneName(zoneName)
+                .storageProfilesParams(List.of(StorageProfileParams.builder().storageProfile(DEFAULT_STORAGE_PROFILE).build()))
+                .build();
+    }
+
+    static CatalogCommand createZoneCommand(String zoneName, List<String> storageProfiles) {
+        List<StorageProfileParams> params = storageProfiles.stream()
+                .map(p -> StorageProfileParams.builder().storageProfile(p).build())
+                .collect(Collectors.toList());
+
+        return CreateZoneCommand.builder()
+                .zoneName(zoneName)
+                .storageProfilesParams(params)
                 .build();
     }
 
@@ -194,7 +210,8 @@ abstract class AbstractCommandValidationTest extends BaseIgniteAbstractTest {
                 zoneId,
                 List.of(tableColumn(columnName)),
                 List.of(columnName),
-                null
+                null,
+                DEFAULT_STORAGE_PROFILE
         );
     }
 
diff --git a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/commands/CatalogUtilsTest.java b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/commands/CatalogUtilsTest.java
index 210a45faf5..06b42faa43 100644
--- a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/commands/CatalogUtilsTest.java
+++ b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/commands/CatalogUtilsTest.java
@@ -317,7 +317,8 @@ public class CatalogUtilsTest extends BaseIgniteAbstractTest {
                 "baz",
                 fooTable.tableVersion(),
                 fooTable.columns(),
-                fooTable.updateToken()
+                fooTable.updateToken(),
+                fooTable.storageProfile()
         );
 
         CatalogSchemaDescriptor updatedSchema = replaceTable(schema, bazTable);
diff --git a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/commands/CreateTableCommandValidationTest.java b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/commands/CreateTableCommandValidationTest.java
index c13a2ee08f..0a852b482d 100644
--- a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/commands/CreateTableCommandValidationTest.java
+++ b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/commands/CreateTableCommandValidationTest.java
@@ -17,8 +17,10 @@
 
 package org.apache.ignite.internal.catalog.commands;
 
+import static org.apache.ignite.internal.lang.IgniteStringFormatter.format;
 import static org.apache.ignite.internal.testframework.IgniteTestUtils.assertThrowsWithCause;
 import static org.apache.ignite.sql.ColumnType.INT32;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
 
 import java.util.List;
 import java.util.stream.Stream;
@@ -417,4 +419,30 @@ public class CreateTableCommandValidationTest extends AbstractCommandValidationT
                 "Index with name 'PUBLIC.FOO_PK' already exists"
         );
     }
+
+    @Test
+    void exceptionIsThrownIfZoneDoesNotContainTableStorageProfile() {
+        CreateTableCommandBuilder builder = CreateTableCommand.builder();
+
+        String zoneName = "testZone";
+
+        Catalog catalog = catalog(createZoneCommand(zoneName, List.of("profile1, profile2")));
+
+        String tableProfile = "profile3";
+
+        CatalogCommand command = fillProperties(builder).zone(zoneName).storageProfile(tableProfile).build();
+
+        assertThrowsWithCause(
+                () -> command.get(catalog),
+                CatalogValidationException.class,
+                format("Zone with name '{}' does not contain table's storage profile [storageProfile='{}']", zoneName, tableProfile)
+        );
+
+        assertDoesNotThrow(() -> {
+            // Let's check the success case.
+            Catalog newCatalog = catalog(createZoneCommand(zoneName, List.of("profile1", "profile2", tableProfile)));
+
+            command.get(newCatalog);
+        });
+    }
 }
diff --git a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/commands/CreateZoneCommandValidationTest.java b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/commands/CreateZoneCommandValidationTest.java
index 1df59fb47b..8f18f9d44c 100644
--- a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/commands/CreateZoneCommandValidationTest.java
+++ b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/commands/CreateZoneCommandValidationTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.catalog.commands;
 
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.catalog.CatalogTestUtils.createZoneBuilder;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_FILTER;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_PARTITION_COUNT;
@@ -26,6 +27,7 @@ import static org.apache.ignite.internal.catalog.commands.CatalogUtils.INFINITE_
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.MAX_PARTITION_COUNT;
 import static org.apache.ignite.internal.testframework.IgniteTestUtils.assertThrows;
 
+import java.util.List;
 import org.apache.ignite.internal.catalog.Catalog;
 import org.apache.ignite.internal.catalog.CatalogCommand;
 import org.apache.ignite.internal.catalog.CatalogValidationException;
@@ -228,6 +230,25 @@ public class CreateZoneCommandValidationTest extends AbstractCommandValidationTe
         createZoneBuilder(ZONE_NAME + 1).filter(DEFAULT_FILTER).build();
     }
 
+    @Test
+    void zoneStorageProfiles() {
+        assertThrows(
+                CatalogValidationException.class,
+                () -> createZoneBuilder(ZONE_NAME).storageProfilesParams(List.of()).build(),
+                "Storage profile cannot be empty"
+        );
+
+        assertThrows(
+                CatalogValidationException.class,
+                () -> createZoneBuilder(ZONE_NAME).storageProfilesParams(null).build(),
+                "Storage profile cannot be null"
+        );
+
+        // Let's check the success case.
+        createZoneBuilder(ZONE_NAME + 0).storageProfilesParams(
+                List.of(StorageProfileParams.builder().storageProfile("lru_rocks").build())).build();
+    }
+
     @Test
     void exceptionIsThrownIfZoneAlreadyExist() {
         CreateZoneCommandBuilder builder = CreateZoneCommand.builder();
@@ -236,6 +257,7 @@ public class CreateZoneCommandValidationTest extends AbstractCommandValidationTe
 
         CatalogCommand command = builder
                 .zoneName("some_zone")
+                .storageProfilesParams(List.of(StorageProfileParams.builder().storageProfile(DEFAULT_STORAGE_PROFILE).build()))
                 .build();
 
         assertThrows(
diff --git a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/descriptors/CatalogDataStorageDescriptorTest.java b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/descriptors/CatalogDataStorageDescriptorTest.java
deleted file mode 100644
index 42a4735cc7..0000000000
--- a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/descriptors/CatalogDataStorageDescriptorTest.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.catalog.descriptors;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.containsString;
-import static org.hamcrest.Matchers.startsWith;
-
-import org.junit.jupiter.api.Test;
-
-class CatalogDataStorageDescriptorTest {
-    @Test
-    void toStringContainsTypeAndFields() {
-        var descriptor = new CatalogDataStorageDescriptor("the-engine", "the-region");
-
-        String toString = descriptor.toString();
-
-        assertThat(toString, startsWith("CatalogDataStorageDescriptor ["));
-        assertThat(toString, containsString("engine=the-engine"));
-        assertThat(toString, containsString("dataRegion=the-region"));
-    }
-}
diff --git a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/descriptors/CatalogTableDescriptorTest.java b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/descriptors/CatalogTableDescriptorTest.java
index 8393637cb6..6cdec50799 100644
--- a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/descriptors/CatalogTableDescriptorTest.java
+++ b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/descriptors/CatalogTableDescriptorTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.catalog.descriptors;
 
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.not;
@@ -37,7 +38,8 @@ class CatalogTableDescriptorTest {
                 4,
                 List.of(new CatalogTableColumnDescriptor("pkCol", ColumnType.STRING, false, 0, 0, 10, null)),
                 List.of("pkCol"),
-                null
+                null,
+                DEFAULT_STORAGE_PROFILE
         );
 
         String toString = descriptor.toString();
diff --git a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/descriptors/CatalogZoneDescriptorTest.java b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/descriptors/CatalogZoneDescriptorTest.java
index 503db1d6a2..e8a9cb3de1 100644
--- a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/descriptors/CatalogZoneDescriptorTest.java
+++ b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/descriptors/CatalogZoneDescriptorTest.java
@@ -17,10 +17,14 @@
 
 package org.apache.ignite.internal.catalog.descriptors;
 
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
+import static org.apache.ignite.internal.catalog.commands.CatalogUtils.fromParams;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.startsWith;
 
+import java.util.List;
+import org.apache.ignite.internal.catalog.commands.StorageProfileParams;
 import org.junit.jupiter.api.Test;
 
 class CatalogZoneDescriptorTest {
@@ -35,7 +39,7 @@ class CatalogZoneDescriptorTest {
                 5,
                 6,
                 "the-filter",
-                new CatalogDataStorageDescriptor("the-engine", "the-region")
+                fromParams(List.of(StorageProfileParams.builder().storageProfile(DEFAULT_STORAGE_PROFILE).build()))
         );
 
         String toString = descriptor.toString();
@@ -49,6 +53,6 @@ class CatalogZoneDescriptorTest {
         assertThat(toString, containsString("dataNodesAutoAdjustScaleUp=5"));
         assertThat(toString, containsString("dataNodesAutoAdjustScaleDown=6"));
         assertThat(toString, containsString("filter=the-filter"));
-        assertThat(toString, containsString("dataStorage=CatalogDataStorageDescriptor ["));
+        assertThat(toString, containsString("storageProfiles=CatalogStorageProfilesDescriptor ["));
     }
 }
diff --git a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/storage/CatalogEntrySerializationTest.java b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/storage/CatalogEntrySerializationTest.java
index ca881e1784..52e8b8f43f 100644
--- a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/storage/CatalogEntrySerializationTest.java
+++ b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/storage/CatalogEntrySerializationTest.java
@@ -29,13 +29,14 @@ import java.util.Set;
 import org.apache.ignite.internal.catalog.Catalog;
 import org.apache.ignite.internal.catalog.commands.DefaultValue;
 import org.apache.ignite.internal.catalog.descriptors.CatalogColumnCollation;
-import org.apache.ignite.internal.catalog.descriptors.CatalogDataStorageDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.CatalogHashIndexDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.CatalogIndexColumnDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.CatalogIndexDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.CatalogIndexStatus;
 import org.apache.ignite.internal.catalog.descriptors.CatalogSchemaDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.CatalogSortedIndexDescriptor;
+import org.apache.ignite.internal.catalog.descriptors.CatalogStorageProfileDescriptor;
+import org.apache.ignite.internal.catalog.descriptors.CatalogStorageProfilesDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.CatalogSystemViewDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.CatalogSystemViewDescriptor.SystemViewType;
 import org.apache.ignite.internal.catalog.descriptors.CatalogTableColumnDescriptor;
@@ -140,8 +141,9 @@ public class CatalogEntrySerializationTest extends BaseIgniteAbstractTest {
     }
 
     private void alterZoneEntry() {
-        CatalogDataStorageDescriptor storage = new CatalogDataStorageDescriptor("test-engine", "region");
-        UpdateEntry entry1 = new AlterZoneEntry(newCatalogZoneDescriptor("zone1", storage));
+        CatalogStorageProfilesDescriptor profiles =
+                new CatalogStorageProfilesDescriptor(List.of(new CatalogStorageProfileDescriptor("default")));
+        UpdateEntry entry1 = new AlterZoneEntry(newCatalogZoneDescriptor("zone1", profiles));
 
         VersionedUpdate update = newVersionedUpdate(entry1, entry1);
 
@@ -149,11 +151,11 @@ public class CatalogEntrySerializationTest extends BaseIgniteAbstractTest {
     }
 
     private void newZoneEntry() {
-        CatalogDataStorageDescriptor storage1 = new CatalogDataStorageDescriptor("test-engine1", "region");
-        CatalogDataStorageDescriptor storage2 = new CatalogDataStorageDescriptor("test-engine2", null);
+        CatalogStorageProfilesDescriptor profiles =
+                new CatalogStorageProfilesDescriptor(List.of(new CatalogStorageProfileDescriptor("default")));
 
-        UpdateEntry entry1 = new NewZoneEntry(newCatalogZoneDescriptor("zone1", storage1));
-        UpdateEntry entry2 = new NewZoneEntry(newCatalogZoneDescriptor("zone2", storage2));
+        UpdateEntry entry1 = new NewZoneEntry(newCatalogZoneDescriptor("zone1", profiles));
+        UpdateEntry entry2 = new NewZoneEntry(newCatalogZoneDescriptor("zone2", profiles));
         VersionedUpdate update = newVersionedUpdate(entry1, entry2);
 
         assertVersionedUpdate(update, serialize(update));
@@ -332,8 +334,11 @@ public class CatalogEntrySerializationTest extends BaseIgniteAbstractTest {
                 new CatalogSystemViewDescriptor(1, "view2", columns, SystemViewType.CLUSTER)
         };
 
+        CatalogStorageProfilesDescriptor profiles =
+                new CatalogStorageProfilesDescriptor(List.of(new CatalogStorageProfileDescriptor("default")));
+
         SnapshotEntry entry = new SnapshotEntry(new Catalog(2, 0L, 1,
-                List.of(newCatalogZoneDescriptor("zone1", new CatalogDataStorageDescriptor("test-engine1", "region"))),
+                List.of(newCatalogZoneDescriptor("zone1", profiles)),
                 List.of(new CatalogSchemaDescriptor(1, "desc", tables, indexes, views, 1))));
 
         SnapshotEntry deserialized = (SnapshotEntry) marshaller.unmarshall(marshaller.marshall(entry));
@@ -370,7 +375,8 @@ public class CatalogEntrySerializationTest extends BaseIgniteAbstractTest {
         }
     }
 
-    private static CatalogZoneDescriptor newCatalogZoneDescriptor(String zoneName, CatalogDataStorageDescriptor storage) {
+    private static CatalogZoneDescriptor newCatalogZoneDescriptor(
+            String zoneName, CatalogStorageProfilesDescriptor profiles) {
         int zoneId = 1;
         int partitions = 3;
 
@@ -383,7 +389,7 @@ public class CatalogEntrySerializationTest extends BaseIgniteAbstractTest {
                 2,
                 3,
                 DEFAULT_FILTER,
-                storage
+                profiles
         );
     }
 
@@ -431,7 +437,8 @@ public class CatalogEntrySerializationTest extends BaseIgniteAbstractTest {
                 17,
                 columns,
                 pkCols,
-                colCols
+                colCols,
+                "default"
         );
     }
 
diff --git a/modules/catalog/src/testFixtures/java/org/apache/ignite/internal/catalog/CatalogTestUtils.java b/modules/catalog/src/testFixtures/java/org/apache/ignite/internal/catalog/CatalogTestUtils.java
index c553dd96a2..5dbf147d28 100644
--- a/modules/catalog/src/testFixtures/java/org/apache/ignite/internal/catalog/CatalogTestUtils.java
+++ b/modules/catalog/src/testFixtures/java/org/apache/ignite/internal/catalog/CatalogTestUtils.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.catalog;
 
 import static java.util.concurrent.CompletableFuture.allOf;
 import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_SCHEMA_NAME;
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.util.CompletableFutures.falseCompletedFuture;
 import static org.apache.ignite.internal.util.CompletableFutures.nullCompletedFuture;
 import static org.apache.ignite.internal.util.CompletableFutures.trueCompletedFuture;
@@ -36,6 +37,7 @@ import org.apache.ignite.internal.catalog.commands.ColumnParams.Builder;
 import org.apache.ignite.internal.catalog.commands.CreateZoneCommand;
 import org.apache.ignite.internal.catalog.commands.CreateZoneCommandBuilder;
 import org.apache.ignite.internal.catalog.commands.DropTableCommand;
+import org.apache.ignite.internal.catalog.commands.StorageProfileParams;
 import org.apache.ignite.internal.catalog.descriptors.CatalogIndexDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.CatalogTableDescriptor;
 import org.apache.ignite.internal.catalog.storage.SnapshotEntry;
@@ -338,8 +340,16 @@ public class CatalogTestUtils {
         return AlterTableAddColumnCommand.builder().schemaName(DEFAULT_SCHEMA_NAME).tableName(tableName).columns(List.of(columns)).build();
     }
 
+    /**
+     * Builder for {@link CreateZoneCommand}.
+     *
+     * @param zoneName Zone name.
+     * @return Builder for {@link CreateZoneCommand}.
+     */
     public static CreateZoneCommandBuilder createZoneBuilder(String zoneName) {
-        return CreateZoneCommand.builder().zoneName(zoneName);
+        return CreateZoneCommand.builder()
+                .zoneName(zoneName)
+                .storageProfilesParams(List.of(StorageProfileParams.builder().storageProfile(DEFAULT_STORAGE_PROFILE).build()));
     }
 
     public static AlterZoneCommandBuilder alterZoneBuilder(String zoneName) {
diff --git a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/core/repl/executor/ItIgnitePicocliCommandsTest.java b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/core/repl/executor/ItIgnitePicocliCommandsTest.java
index 9efe7ebadc..ec10396fea 100644
--- a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/core/repl/executor/ItIgnitePicocliCommandsTest.java
+++ b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/core/repl/executor/ItIgnitePicocliCommandsTest.java
@@ -274,10 +274,7 @@ public class ItIgnitePicocliCommandsTest extends CliIntegrationTest {
                         "cluster",
                         "deployment",
                         "nodeAttributes",
-                        "aimem",
-                        "aipersist",
-                        "rocksDb",
-                        "storageProfiles",
+                        "storage",
                         "criticalWorkers",
                         "sql"
                 )
diff --git a/modules/client-handler/src/testFixtures/java/org/apache/ignite/client/handler/FakeCatalogService.java b/modules/client-handler/src/testFixtures/java/org/apache/ignite/client/handler/FakeCatalogService.java
index 2e74e02311..d6491b6bb7 100644
--- a/modules/client-handler/src/testFixtures/java/org/apache/ignite/client/handler/FakeCatalogService.java
+++ b/modules/client-handler/src/testFixtures/java/org/apache/ignite/client/handler/FakeCatalogService.java
@@ -17,9 +17,11 @@
 
 package org.apache.ignite.client.handler;
 
+import static org.apache.ignite.internal.catalog.commands.CatalogUtils.fromParams;
 import static org.mockito.Mockito.mock;
 
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
 import org.apache.ignite.internal.catalog.Catalog;
@@ -56,7 +58,7 @@ public class FakeCatalogService implements CatalogService {
     @Override
     public CatalogTableDescriptor table(int tableId, long timestamp) {
         return new CatalogTableDescriptor(
-                tableId, 0, 0, "table", 0, List.of(mock(CatalogTableColumnDescriptor.class)), List.of(), null);
+                tableId, 0, 0, "table", 0, List.of(mock(CatalogTableColumnDescriptor.class)), List.of(), null, DEFAULT_STORAGE_PROFILE);
     }
 
     @Override
@@ -116,7 +118,7 @@ public class FakeCatalogService implements CatalogService {
 
     @Override
     public CatalogZoneDescriptor zone(int zoneId, long timestamp) {
-        return new CatalogZoneDescriptor(zoneId, "zone", partitions, 0, 0, 0, 0, "", null);
+        return new CatalogZoneDescriptor(zoneId, "zone", partitions, 0, 0, 0, 0, "", fromParams(Collections.emptyList()));
     }
 
     @Override
diff --git a/modules/cluster-management/build.gradle b/modules/cluster-management/build.gradle
index 988af51217..809b2f21e0 100644
--- a/modules/cluster-management/build.gradle
+++ b/modules/cluster-management/build.gradle
@@ -37,6 +37,7 @@ dependencies {
     implementation project(':ignite-raft-api')
     implementation project(':ignite-vault')
     implementation project(':ignite-rocksdb-common')
+    implementation project(':ignite-storage-api')
     implementation project(':ignite-security')
     implementation libs.jetbrains.annotations
     implementation libs.fastutil.core
@@ -54,6 +55,7 @@ dependencies {
     testFixturesImplementation project(':ignite-core')
     testFixturesImplementation project(':ignite-raft')
     testFixturesImplementation project(':ignite-raft-api')
+    testFixturesImplementation project(':ignite-storage-api')
     testFixturesImplementation project(':ignite-vault')
     testFixturesImplementation project(':ignite-security')
     testFixturesImplementation testFixtures(project(':ignite-core'))
@@ -65,6 +67,7 @@ dependencies {
     integrationTestImplementation project(':ignite-rest')
     integrationTestImplementation project(':ignite-raft')
     integrationTestImplementation project(':ignite-raft-api')
+    integrationTestImplementation project(':ignite-catalog')
     integrationTestImplementation testFixtures(project)
     integrationTestImplementation testFixtures(project(':ignite-core'))
     integrationTestImplementation testFixtures(project(':ignite-configuration'))
diff --git a/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/topology/ItLogicalTopologyTest.java b/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/topology/ItLogicalTopologyTest.java
index ff6210a705..37b9b0fd0b 100644
--- a/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/topology/ItLogicalTopologyTest.java
+++ b/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/topology/ItLogicalTopologyTest.java
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.cluster.management.topology;
 import static org.apache.ignite.internal.testframework.IgniteTestUtils.testNodeName;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.empty;
+import static org.hamcrest.Matchers.hasItems;
 import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.not;
 import static org.hamcrest.Matchers.notNullValue;
@@ -62,7 +63,7 @@ class ItLogicalTopologyTest extends ClusterPerTestIntegrationTest {
 
     private static final Map<String, String> NODE_ATTRIBUTES_MAP = Map.of("region", "US", "storage", "SSD");
 
-    private static final Map<String, String> STORAGE_PROFILES_MAP = Map.of("lru_rocks", "rocksDb", "segmented_aipersist", "aipersist");
+    private static final String[] STORAGE_PROFILES_LIST = {"lru_rocks", "segmented_aipersist"};
 
     @Language("JSON")
     private static final String NODE_BOOTSTRAP_CFG_TEMPLATE_WITH_NODE_ATTRIBUTES_AND_STORAGE_PROFILES = "{\n"
@@ -75,8 +76,8 @@ class ItLogicalTopologyTest extends ClusterPerTestIntegrationTest {
             + "  nodeAttributes: {\n"
             + "    nodeAttributes: " + NODE_ATTRIBUTES
             + "  },\n"
-            + "  storageProfiles: {\n"
-            + "    storageProfiles: " + STORAGE_PROFILES
+            + "  storage: {\n"
+            + "    profiles: " + STORAGE_PROFILES
             + "  },\n"
             + "  clientConnector: { port:{} },\n"
             + "  rest.port: {}\n"
@@ -171,7 +172,7 @@ class ItLogicalTopologyTest extends ClusterPerTestIntegrationTest {
         assertThat(event.eventType, is(EventType.VALIDATED));
         assertThat(event.node.name(), is(secondIgnite.name()));
         assertThat(event.node.userAttributes(), is(NODE_ATTRIBUTES_MAP));
-        assertThat(event.node.storageProfiles(), is(STORAGE_PROFILES_MAP));
+        assertThat(event.node.storageProfiles(), hasItems(STORAGE_PROFILES_LIST));
 
         event = events.poll(10, TimeUnit.SECONDS);
 
@@ -180,7 +181,7 @@ class ItLogicalTopologyTest extends ClusterPerTestIntegrationTest {
         assertThat(event.node.name(), is(secondIgnite.name()));
         assertThat(event.topologyVersion, is(2L));
         assertThat(event.node.userAttributes(), is(NODE_ATTRIBUTES_MAP));
-        assertThat(event.node.storageProfiles(), is(STORAGE_PROFILES_MAP));
+        assertThat(event.node.storageProfiles(), hasItems(STORAGE_PROFILES_LIST));
 
         assertThat(events, is(empty()));
 
@@ -194,7 +195,7 @@ class ItLogicalTopologyTest extends ClusterPerTestIntegrationTest {
         assertThat(event.node.name(), is(secondIgnite.name()));
         assertThat(event.topologyVersion, is(3L));
         assertThat(event.node.userAttributes(), is(Collections.emptyMap()));
-        assertThat(event.node.storageProfiles(), is(Collections.emptyMap()));
+        assertThat(event.node.storageProfiles(), is(Collections.emptyList()));
 
         assertThat(events, is(empty()));
     }
@@ -218,7 +219,7 @@ class ItLogicalTopologyTest extends ClusterPerTestIntegrationTest {
         assertTrue(secondNode.isPresent());
 
         assertThat(secondNode.get().userAttributes(), is(NODE_ATTRIBUTES_MAP));
-        assertThat(secondNode.get().storageProfiles(), is(STORAGE_PROFILES_MAP));
+        assertThat(secondNode.get().storageProfiles(), hasItems(STORAGE_PROFILES_LIST));
     }
 
     @Test
diff --git a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/NodeAttributes.java b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/NodeAttributes.java
index 71e556d2d2..19024eacb8 100644
--- a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/NodeAttributes.java
+++ b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/NodeAttributes.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.cluster.management;
 
+import java.util.List;
 import java.util.Map;
 import org.apache.ignite.internal.cluster.management.topology.api.LogicalNode;
 
@@ -39,7 +40,7 @@ public interface NodeAttributes {
     Map<String, String> systemAttributes();
 
     /**
-     * TODO: add java doc https://issues.apache.org/jira/browse/IGNITE-20564
+     * List of storage profiles, which the node supports.
      */
-    Map<String, String> storageProfiles();
+    List<String> storageProfiles();
 }
diff --git a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/NodeAttributesCollector.java b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/NodeAttributesCollector.java
index 8cdf0d8647..6d67ef123d 100644
--- a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/NodeAttributesCollector.java
+++ b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/NodeAttributesCollector.java
@@ -25,8 +25,8 @@ import java.util.stream.Collectors;
 import org.apache.ignite.configuration.NamedListView;
 import org.apache.ignite.internal.cluster.management.configuration.NodeAttributeView;
 import org.apache.ignite.internal.cluster.management.configuration.NodeAttributesConfiguration;
-import org.apache.ignite.internal.cluster.management.configuration.StorageProfileView;
-import org.apache.ignite.internal.cluster.management.configuration.StorageProfilesConfiguration;
+import org.apache.ignite.internal.storage.configurations.StorageConfiguration;
+import org.apache.ignite.internal.storage.configurations.StorageProfileView;
 
 /**
  * This class is responsible for retrieving local node attributes
@@ -37,11 +37,11 @@ public class NodeAttributesCollector implements NodeAttributes {
 
     private final NodeAttributesConfiguration nodeAttributesConfiguration;
 
-    private final StorageProfilesConfiguration storageProfilesConfiguration;
+    private final StorageConfiguration storageProfilesConfiguration;
 
     public NodeAttributesCollector(
             NodeAttributesConfiguration nodeAttributesConfiguration,
-            StorageProfilesConfiguration storageProfilesConfiguration
+            StorageConfiguration storageProfilesConfiguration
     ) {
         this.nodeAttributesConfiguration = nodeAttributesConfiguration;
         this.storageProfilesConfiguration = storageProfilesConfiguration;
@@ -65,11 +65,12 @@ public class NodeAttributesCollector implements NodeAttributes {
 
     /** {@inheritDoc} */
     @Override
-    public Map<String, String> storageProfiles() {
-        NamedListView<StorageProfileView> storageProfiles = storageProfilesConfiguration.storageProfiles().value();
+    public List<String> storageProfiles() {
+        NamedListView<StorageProfileView> storageProfiles = storageProfilesConfiguration.profiles().value();
 
         return storageProfiles.stream()
-                .collect(Collectors.toUnmodifiableMap(StorageProfileView::name, StorageProfileView::engine));
+                .map(StorageProfileView::name)
+                .collect(Collectors.toList());
     }
 
     /** {@inheritDoc} */
diff --git a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/configuration/ClusterManagementConfigurationModule.java b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/configuration/ClusterManagementConfigurationModule.java
index a2eb334271..03abb39af8 100644
--- a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/configuration/ClusterManagementConfigurationModule.java
+++ b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/configuration/ClusterManagementConfigurationModule.java
@@ -36,6 +36,6 @@ public class ClusterManagementConfigurationModule implements ConfigurationModule
 
     @Override
     public Collection<RootKey<?, ?>> rootKeys() {
-        return List.of(ClusterManagementConfiguration.KEY, NodeAttributesConfiguration.KEY, StorageProfilesConfiguration.KEY);
+        return List.of(ClusterManagementConfiguration.KEY, NodeAttributesConfiguration.KEY);
     }
 }
diff --git a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/configuration/StorageProfileConfigurationSchema.java b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/configuration/StorageProfileConfigurationSchema.java
deleted file mode 100644
index af01ab2a6b..0000000000
--- a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/configuration/StorageProfileConfigurationSchema.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.cluster.management.configuration;
-
-import org.apache.ignite.configuration.annotation.Config;
-import org.apache.ignite.configuration.annotation.InjectedName;
-import org.apache.ignite.configuration.annotation.Value;
-
-/**
- * TODO: add java doc https://issues.apache.org/jira/browse/IGNITE-20564.
- */
-@Config
-public class StorageProfileConfigurationSchema {
-    /** TODO: add java doc https://issues.apache.org/jira/browse/IGNITE-20564. */
-    @InjectedName
-    public String name;
-
-    /** TODO: add java doc https://issues.apache.org/jira/browse/IGNITE-20564. */
-    @Value(hasDefault = true)
-    public String engine = "";
-}
diff --git a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/CmgRaftGroupListener.java b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/CmgRaftGroupListener.java
index 7ee6868cfe..dbc24580bc 100644
--- a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/CmgRaftGroupListener.java
+++ b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/CmgRaftGroupListener.java
@@ -229,7 +229,7 @@ public class CmgRaftGroupListener implements RaftGroupListener {
 
         // Nodes will be removed from a topology, so it is safe to set nodeAttributes to the default value
         Set<LogicalNode> logicalNodes = nodes.stream()
-                .map(n -> new LogicalNode(n, Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap()))
+                .map(n -> new LogicalNode(n, Collections.emptyMap(), Collections.emptyMap(), Collections.emptyList()))
                 .collect(Collectors.toSet());
 
         logicalTopology.removeNodes(logicalNodes);
diff --git a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/commands/ClusterNodeMessage.java b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/commands/ClusterNodeMessage.java
index f971a23523..c9cccf879c 100644
--- a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/commands/ClusterNodeMessage.java
+++ b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/commands/ClusterNodeMessage.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.internal.cluster.management.raft.commands;
 
 import java.io.Serializable;
+import java.util.List;
 import java.util.Map;
 import org.apache.ignite.internal.cluster.management.network.messages.CmgMessageGroup;
 import org.apache.ignite.internal.network.ClusterNodeImpl;
@@ -51,5 +52,5 @@ public interface ClusterNodeMessage extends NetworkMessage, Serializable {
     Map<String, String> systemAttributes();
 
     @Nullable
-    Map<String, String> storageProfiles();
+    List<String> storageProfiles();
 }
diff --git a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/topology/api/LogicalNode.java b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/topology/api/LogicalNode.java
index 30a147df50..3663713bf2 100644
--- a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/topology/api/LogicalNode.java
+++ b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/topology/api/LogicalNode.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.internal.cluster.management.topology.api;
 
 import java.util.Collections;
+import java.util.List;
 import java.util.Map;
 import org.apache.ignite.internal.network.ClusterNodeImpl;
 import org.apache.ignite.internal.tostring.IgniteToStringInclude;
@@ -41,9 +42,11 @@ public class LogicalNode extends ClusterNodeImpl {
     @IgniteToStringInclude
     private final Map<String, String> systemAttributes;
 
-    // TODO: add javadoc https://issues.apache.org/jira/browse/IGNITE-20564
+    /**
+     * List of storage profiles, which the node supports.
+     */
     @IgniteToStringInclude
-    private final Map<String, String> storageProfiles;
+    private final List<String> storageProfiles;
 
     /**
      * Constructor.
@@ -61,7 +64,7 @@ public class LogicalNode extends ClusterNodeImpl {
 
         this.userAttributes = Collections.emptyMap();
         this.systemAttributes = Collections.emptyMap();
-        this.storageProfiles = Collections.emptyMap();
+        this.storageProfiles = Collections.emptyList();
     }
 
     /**
@@ -71,7 +74,7 @@ public class LogicalNode extends ClusterNodeImpl {
      * @param userAttributes  Node attributes defined in configuration.
      */
     public LogicalNode(ClusterNode clusterNode, Map<String, String> userAttributes) {
-        this(clusterNode, userAttributes, Collections.emptyMap(), Collections.emptyMap());
+        this(clusterNode, userAttributes, Collections.emptyMap(), Collections.emptyList());
     }
 
     /**
@@ -80,19 +83,19 @@ public class LogicalNode extends ClusterNodeImpl {
      * @param clusterNode Represents a node in a cluster.
      * @param userAttributes Node attributes defined in configuration.
      * @param systemAttributes Internal node attributes provided by system components at startup.
-     * @param storageProfiles TODO: add javadoc https://issues.apache.org/jira/browse/IGNITE-20564
+     * @param storageProfiles List of storage profiles, which the node supports.
      */
     public LogicalNode(
             ClusterNode clusterNode,
             Map<String, String> userAttributes,
             Map<String, String> systemAttributes,
-            Map<String, String> storageProfiles
+            List<String> storageProfiles
     ) {
         super(clusterNode.id(), clusterNode.name(), clusterNode.address(), clusterNode.nodeMetadata());
 
         this.userAttributes = userAttributes == null ? Collections.emptyMap() : userAttributes;
         this.systemAttributes = systemAttributes == null ? Collections.emptyMap() : systemAttributes;
-        this.storageProfiles = storageProfiles == null ? Collections.emptyMap() : storageProfiles;
+        this.storageProfiles = storageProfiles;
     }
 
     /**
@@ -101,7 +104,7 @@ public class LogicalNode extends ClusterNodeImpl {
      * @param clusterNode    Represents a node in a cluster.
      */
     public LogicalNode(ClusterNode clusterNode) {
-        this(clusterNode, Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap());
+        this(clusterNode, Collections.emptyMap(), Collections.emptyMap(), Collections.emptyList());
     }
 
     /**
@@ -123,11 +126,11 @@ public class LogicalNode extends ClusterNodeImpl {
     }
 
     /**
-     * TODO: add java doc https://issues.apache.org/jira/browse/IGNITE-20564.
+     * Returns the list of storage profiles, which the node supports.
      *
-     * @return add java doc https://issues.apache.org/jira/browse/IGNITE-20564.
+     * @return List of storage profiles, which the node supports.
      */
-    public Map<String, String> storageProfiles() {
+    public List<String> storageProfiles() {
         return storageProfiles;
     }
 
diff --git a/modules/cluster-management/src/testFixtures/java/org/apache/ignite/internal/cluster/management/BaseItClusterManagementTest.java b/modules/cluster-management/src/testFixtures/java/org/apache/ignite/internal/cluster/management/BaseItClusterManagementTest.java
index 0128db0cb9..44a2ac4126 100644
--- a/modules/cluster-management/src/testFixtures/java/org/apache/ignite/internal/cluster/management/BaseItClusterManagementTest.java
+++ b/modules/cluster-management/src/testFixtures/java/org/apache/ignite/internal/cluster/management/BaseItClusterManagementTest.java
@@ -28,11 +28,11 @@ import java.util.stream.IntStream;
 import java.util.stream.Stream;
 import org.apache.ignite.internal.cluster.management.configuration.ClusterManagementConfiguration;
 import org.apache.ignite.internal.cluster.management.configuration.NodeAttributesConfiguration;
-import org.apache.ignite.internal.cluster.management.configuration.StorageProfilesConfiguration;
 import org.apache.ignite.internal.configuration.testframework.ConfigurationExtension;
 import org.apache.ignite.internal.configuration.testframework.InjectConfiguration;
 import org.apache.ignite.internal.network.StaticNodeFinder;
 import org.apache.ignite.internal.raft.configuration.RaftConfiguration;
+import org.apache.ignite.internal.storage.configurations.StorageConfiguration;
 import org.apache.ignite.internal.testframework.BaseIgniteAbstractTest;
 import org.apache.ignite.internal.util.IgniteUtils;
 import org.apache.ignite.network.NetworkAddress;
@@ -56,7 +56,7 @@ public abstract class BaseItClusterManagementTest extends BaseIgniteAbstractTest
     private static NodeAttributesConfiguration userNodeAttributes;
 
     @InjectConfiguration
-    private static StorageProfilesConfiguration storageProfilesConfiguration;
+    private static StorageConfiguration storageConfiguration;
 
     protected static List<MockNode> createNodes(int numNodes, TestInfo testInfo, Path workDir) {
         StaticNodeFinder nodeFinder = createNodeFinder(numNodes);
@@ -70,7 +70,7 @@ public abstract class BaseItClusterManagementTest extends BaseIgniteAbstractTest
                         raftConfiguration,
                         cmgConfiguration,
                         userNodeAttributes,
-                        storageProfilesConfiguration
+                        storageConfiguration
 
                 ))
                 .collect(toList());
@@ -85,7 +85,7 @@ public abstract class BaseItClusterManagementTest extends BaseIgniteAbstractTest
                 raftConfiguration,
                 cmgConfiguration,
                 userNodeAttributes,
-                storageProfilesConfiguration
+                storageConfiguration
         );
 
         cluster.add(node);
diff --git a/modules/cluster-management/src/testFixtures/java/org/apache/ignite/internal/cluster/management/MockNode.java b/modules/cluster-management/src/testFixtures/java/org/apache/ignite/internal/cluster/management/MockNode.java
index 5652010d7e..4eb9fe2895 100644
--- a/modules/cluster-management/src/testFixtures/java/org/apache/ignite/internal/cluster/management/MockNode.java
+++ b/modules/cluster-management/src/testFixtures/java/org/apache/ignite/internal/cluster/management/MockNode.java
@@ -27,7 +27,6 @@ import java.util.Set;
 import java.util.concurrent.CompletableFuture;
 import org.apache.ignite.internal.cluster.management.configuration.ClusterManagementConfiguration;
 import org.apache.ignite.internal.cluster.management.configuration.NodeAttributesConfiguration;
-import org.apache.ignite.internal.cluster.management.configuration.StorageProfilesConfiguration;
 import org.apache.ignite.internal.cluster.management.raft.RocksDbClusterStateStorage;
 import org.apache.ignite.internal.cluster.management.topology.LogicalTopologyImpl;
 import org.apache.ignite.internal.cluster.management.topology.api.LogicalNode;
@@ -40,6 +39,7 @@ import org.apache.ignite.internal.network.NodeFinder;
 import org.apache.ignite.internal.network.utils.ClusterServiceTestUtils;
 import org.apache.ignite.internal.raft.Loza;
 import org.apache.ignite.internal.raft.configuration.RaftConfiguration;
+import org.apache.ignite.internal.storage.configurations.StorageConfiguration;
 import org.apache.ignite.internal.util.ReverseIterator;
 import org.apache.ignite.internal.vault.VaultManager;
 import org.apache.ignite.internal.vault.persistence.PersistentVaultService;
@@ -84,7 +84,7 @@ public class MockNode {
             RaftConfiguration raftConfiguration,
             ClusterManagementConfiguration cmgConfiguration,
             NodeAttributesConfiguration nodeAttributes,
-            StorageProfilesConfiguration storageProfilesConfiguration
+            StorageConfiguration storageProfilesConfiguration
     ) {
         this.testInfo = testInfo;
         this.nodeFinder = nodeFinder;
diff --git a/modules/compute/build.gradle b/modules/compute/build.gradle
index 5e3fc9041c..4e69e03b8a 100644
--- a/modules/compute/build.gradle
+++ b/modules/compute/build.gradle
@@ -54,6 +54,7 @@ dependencies {
     integrationTestImplementation project(':ignite-cluster-management')
     integrationTestImplementation project(':ignite-table')
     integrationTestImplementation project(':ignite-placement-driver-api')
+    integrationTestImplementation project(':ignite-catalog')
     integrationTestImplementation project(':ignite-client')
     integrationTestImplementation testFixtures(project(':ignite-core'))
     integrationTestImplementation testFixtures(project(':ignite-runner'))
diff --git a/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItWorkerShutdownTest.java b/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItWorkerShutdownTest.java
index 12d867d7fa..db3b98df19 100644
--- a/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItWorkerShutdownTest.java
+++ b/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItWorkerShutdownTest.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.internal.compute;
 
 import static org.apache.ignite.internal.TestWrappers.unwrapTableImpl;
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.greaterThan;
@@ -372,7 +373,7 @@ public abstract class ItWorkerShutdownTest extends ClusterPerTestIntegrationTest
     private void createReplicatedTestTableWithOneRow() {
         // Number of replicas == number of nodes and number of partitions == 1. This gives us the majority on primary replica stop.
         // After the primary replica is stopped we still be able to select new primary replica selected.
-        executeSql("CREATE ZONE TEST_ZONE WITH REPLICAS=3, PARTITIONS=1");
+        executeSql("CREATE ZONE TEST_ZONE WITH REPLICAS=3, PARTITIONS=1, STORAGE_PROFILES='" + DEFAULT_STORAGE_PROFILE + "'");
         executeSql("CREATE TABLE test (k int, v int, CONSTRAINT PK PRIMARY KEY (k)) WITH PRIMARY_ZONE='TEST_ZONE'");
         executeSql("INSERT INTO test(k, v) VALUES (1, 101)");
     }
diff --git a/modules/configuration-api/src/main/java/org/apache/ignite/configuration/ConfigurationModule.java b/modules/configuration-api/src/main/java/org/apache/ignite/configuration/ConfigurationModule.java
index 9e53703dba..e94a7993f8 100644
--- a/modules/configuration-api/src/main/java/org/apache/ignite/configuration/ConfigurationModule.java
+++ b/modules/configuration-api/src/main/java/org/apache/ignite/configuration/ConfigurationModule.java
@@ -97,7 +97,10 @@ public interface ConfigurationModule {
 
     /**
      * Patches the provided configuration with dynamic default values. This method is called
-     * only for cluster-wide configuration on cluster initialization.
+     * <ul>
+     *     <li>for cluster-wide configuration on cluster initialization.</li>
+     *     <li>for node-local configuration on the node start during the process of local configs reading.</li>
+     * </ul>
      *
      * <p>Dynamic defaults are default values that are not specified in the configuration source,
      * but are added to the configuration on-the-fly, based on some external conditions.
diff --git a/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/ConfigurationTreeGenerator.java b/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/ConfigurationTreeGenerator.java
index 13d7761d65..b8447ff8e6 100644
--- a/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/ConfigurationTreeGenerator.java
+++ b/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/ConfigurationTreeGenerator.java
@@ -30,7 +30,6 @@ import static org.apache.ignite.internal.configuration.util.ConfigurationUtil.po
 import static org.apache.ignite.internal.configuration.util.ConfigurationUtil.schemaExtensions;
 import static org.apache.ignite.internal.configuration.util.ConfigurationUtil.schemaFields;
 import static org.apache.ignite.internal.util.CollectionUtils.difference;
-import static org.apache.ignite.internal.util.CollectionUtils.first;
 
 import java.lang.reflect.Field;
 import java.util.Collection;
@@ -222,10 +221,7 @@ public class ConfigurationTreeGenerator implements ManuallyCloseable {
 
         Set<Class<?>> notInAllSchemas = difference(polymorphicExtensionsByParent.keySet(), allSchemas);
 
-        // TODO: IGNTIE-20263 Return commented condition
-        // if (!notInAllSchemas.isEmpty()) {
-        if (!notInAllSchemas.isEmpty()
-                && (notInAllSchemas.size() == 1 && !first(notInAllSchemas).getSimpleName().equals("DataStorageConfigurationSchema"))) {
+        if (!notInAllSchemas.isEmpty()) {
             throw new IllegalArgumentException(
                     "Polymorphic extensions for which no polymorphic configuration schemas were found: " + notInAllSchemas
             );
diff --git a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/ConfigurationTestUtils.java b/modules/configuration/src/testFixtures/java/org/apache/ignite/internal/configuration/ConfigurationTestUtils.java
similarity index 100%
rename from modules/configuration/src/test/java/org/apache/ignite/internal/configuration/ConfigurationTestUtils.java
rename to modules/configuration/src/testFixtures/java/org/apache/ignite/internal/configuration/ConfigurationTestUtils.java
diff --git a/modules/api/src/main/java/org/apache/ignite/catalog/ZoneEngine.java b/modules/core/src/main/java/org/apache/ignite/internal/replicator/ReplicatorConstants.java
similarity index 72%
copy from modules/api/src/main/java/org/apache/ignite/catalog/ZoneEngine.java
copy to modules/core/src/main/java/org/apache/ignite/internal/replicator/ReplicatorConstants.java
index 4e33a6d770..967161b2f3 100644
--- a/modules/api/src/main/java/org/apache/ignite/catalog/ZoneEngine.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/replicator/ReplicatorConstants.java
@@ -15,11 +15,14 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.catalog;
+package org.apache.ignite.internal.replicator;
 
 /**
- * Engine to use for distribution zone.
+ * Constants for replication protocol.
  */
-public enum ZoneEngine {
-    AIMEM, ROCKSDB, DEFAULT
+public final class ReplicatorConstants {
+    /** Default Idle safe time propagation period. */
+    public static final int DEFAULT_IDLE_SAFE_TIME_PROPAGATION_PERIOD_MILLISECONDS = 1000;
+
+    private ReplicatorConstants() {}
 }
diff --git a/modules/core/src/testFixtures/java/org/apache/ignite/internal/testframework/TestIgnitionManager.java b/modules/core/src/testFixtures/java/org/apache/ignite/internal/testframework/TestIgnitionManager.java
index ea9150887f..50f78bdcda 100644
--- a/modules/core/src/testFixtures/java/org/apache/ignite/internal/testframework/TestIgnitionManager.java
+++ b/modules/core/src/testFixtures/java/org/apache/ignite/internal/testframework/TestIgnitionManager.java
@@ -61,9 +61,12 @@ public class TestIgnitionManager {
     /** Map with default node configuration values. */
     private static final Map<String, String> DEFAULT_NODE_CONFIG = Map.of(
             "network.membership.scaleCube.metadataTimeout", Integer.toString(DEFAULT_SCALECUBE_METADATA_TIMEOUT),
-            "aipersist.defaultRegion.size", Integer.toString(256 * MiB),
-            "aimem.defaultRegion.initSize", Integer.toString(256 * MiB),
-            "aimem.defaultRegion.maxSize", Integer.toString(256 * MiB)
+            "storage.profiles.default_aipersist.engine", "aipersist",
+            "storage.profiles.default_aipersist.size", Integer.toString(256 * MiB),
+            "storage.profiles.default_aimem.engine", "aimem",
+            "storage.profiles.default_aimem.initSize", Integer.toString(256 * MiB),
+            "storage.profiles.default_aimem.maxSize", Integer.toString(256 * MiB),
+            "storage.profiles.default.engine", "aipersist"
     );
 
     /** Map with default cluster configuration values. */
diff --git a/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/distributionzones/ItDistributionZonesFilterTest.java b/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/distributionzones/ItDistributionZonesFiltersTest.java
similarity index 86%
rename from modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/distributionzones/ItDistributionZonesFilterTest.java
rename to modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/distributionzones/ItDistributionZonesFiltersTest.java
index ae190e4a41..e676b39c85 100644
--- a/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/distributionzones/ItDistributionZonesFilterTest.java
+++ b/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/distributionzones/ItDistributionZonesFiltersTest.java
@@ -18,6 +18,8 @@
 package org.apache.ignite.internal.distributionzones;
 
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static org.apache.ignite.internal.TestDefaultProfilesNames.DEFAULT_AIPERSIST_PROFILE_NAME;
+import static org.apache.ignite.internal.TestDefaultProfilesNames.DEFAULT_ROCKSDB_PROFILE_NAME;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_FILTER;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.IMMEDIATE_TIMER_VALUE;
 import static org.apache.ignite.internal.distributionzones.DistributionZonesTestUtil.assertValueInStorage;
@@ -48,12 +50,13 @@ import org.apache.ignite.internal.table.TableViewInternal;
 import org.apache.ignite.internal.table.distributed.TableManager;
 import org.apache.ignite.internal.testframework.IgniteTestUtils;
 import org.intellij.lang.annotations.Language;
+import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 
 /**
  * Integration test for data nodes' filters functionality.
  */
-public class ItDistributionZonesFilterTest extends ClusterPerTestIntegrationTest {
+public class ItDistributionZonesFiltersTest extends ClusterPerTestIntegrationTest {
     private static final String ZONE_NAME = "TEST_ZONE";
 
     private static final String TABLE_NAME = "table1";
@@ -61,6 +64,15 @@ public class ItDistributionZonesFilterTest extends ClusterPerTestIntegrationTest
     @Language("JSON")
     private static final String NODE_ATTRIBUTES = "{region:{attribute:\"US\"},storage:{attribute:\"SSD\"}}";
 
+    private static final String STORAGE_PROFILES = String.format("'%s, %s'", DEFAULT_ROCKSDB_PROFILE_NAME, DEFAULT_AIPERSIST_PROFILE_NAME);
+
+    @Language("JSON")
+    private static final String STORAGE_PROFILES_CONFIGS = String.format(
+            "{%s:{engine:\"rocksDb\"}, %s:{engine:\"aipersist\"}}",
+            DEFAULT_ROCKSDB_PROFILE_NAME,
+            DEFAULT_AIPERSIST_PROFILE_NAME
+    );
+
     private static final String COLUMN_KEY = "key";
 
     private static final String COLUMN_VAL = "val";
@@ -68,7 +80,7 @@ public class ItDistributionZonesFilterTest extends ClusterPerTestIntegrationTest
     private static final int TIMEOUT_MILLIS = 10_000;
 
     @Language("JSON")
-    private static String createStartConfig(@Language("JSON") String nodeAttributes) {
+    private static String createStartConfig(@Language("JSON") String nodeAttributes, @Language("JSON") String storageProfiles) {
         return "{\n"
                 + "  network: {\n"
                 + "    port: {},\n"
@@ -79,6 +91,9 @@ public class ItDistributionZonesFilterTest extends ClusterPerTestIntegrationTest
                 + "  nodeAttributes: {\n"
                 + "    nodeAttributes: " + nodeAttributes
                 + "  },\n"
+                + "  storage: {\n"
+                + "    profiles: " + storageProfiles
+                + "  },\n"
                 + "  clientConnector: { port:{} },\n"
                 + "  rest.port: {}\n"
                 + "}";
@@ -86,7 +101,7 @@ public class ItDistributionZonesFilterTest extends ClusterPerTestIntegrationTest
 
     @Override
     protected String getNodeBootstrapConfigTemplate() {
-        return createStartConfig(NODE_ATTRIBUTES);
+        return createStartConfig(NODE_ATTRIBUTES, STORAGE_PROFILES_CONFIGS);
     }
 
     @Override
@@ -99,16 +114,16 @@ public class ItDistributionZonesFilterTest extends ClusterPerTestIntegrationTest
      *
      * @throws Exception If failed.
      */
-    @Test
+    @Disabled("https://issues.apache.org/jira/browse/IGNITE-21387")
     void testFilteredDataNodesPropagatedToStable() throws Exception {
         String filter = "$[?(@.region == \"US\" && @.storage == \"SSD\")]";
 
         // This node do not pass the filter
         @Language("JSON") String firstNodeAttributes = "{region:{attribute:\"EU\"},storage:{attribute:\"SSD\"}}";
 
-        IgniteImpl node = startNode(1, createStartConfig(firstNodeAttributes));
+        IgniteImpl node = startNode(1, createStartConfig(firstNodeAttributes, STORAGE_PROFILES_CONFIGS));
 
-        node.sql().execute(null, createZoneSql(2, 3, IMMEDIATE_TIMER_VALUE, IMMEDIATE_TIMER_VALUE, filter));
+        node.sql().execute(null, createZoneSql(2, 3, IMMEDIATE_TIMER_VALUE, IMMEDIATE_TIMER_VALUE, filter, STORAGE_PROFILES));
 
         node.sql().execute(null, createTableSql());
 
@@ -131,8 +146,14 @@ public class ItDistributionZonesFilterTest extends ClusterPerTestIntegrationTest
 
         @Language("JSON") String secondNodeAttributes = "{region:{attribute:\"US\"},storage:{attribute:\"SSD\"}}";
 
-        // This node pass the filter
-        startNode(2, createStartConfig(secondNodeAttributes));
+        // This node pass the filter but storage profiles of a node do not match zone's storage profiles.
+        // TODO: https://issues.apache.org/jira/browse/IGNITE-21387 recovery of this node is failing,
+        // TODO: because there are no appropriate storage profile on the node
+        @Language("JSON") String notMatchingProfiles = "{dummy:{engine:\"dummy\"},another_dummy:{engine:\"dummy\"}}";
+        startNode(2, createStartConfig(secondNodeAttributes, notMatchingProfiles));
+
+        // This node pass the filter and storage profiles of a node match zone's storage profiles.
+        startNode(3, createStartConfig(secondNodeAttributes, STORAGE_PROFILES_CONFIGS));
 
         int zoneId = getZoneId(node);
 
@@ -140,7 +161,7 @@ public class ItDistributionZonesFilterTest extends ClusterPerTestIntegrationTest
                 metaStorageManager,
                 zoneDataNodesKey(zoneId),
                 (v) -> ((Map<Node, Integer>) fromBytes(v)).size(),
-                3,
+                4,
                 TIMEOUT_MILLIS
         );
 
@@ -148,13 +169,13 @@ public class ItDistributionZonesFilterTest extends ClusterPerTestIntegrationTest
 
         assertTrue(waitForCondition(() -> metaStorageManager.appliedRevision() >= dataNodesEntry1.revision(), TIMEOUT_MILLIS));
 
-        // We check that two nodes that pass the filter are presented in the stable key.
+        // We check that two nodes that pass the filter and storage profiles are presented in the stable key.
         assertValueInStorage(
                 metaStorageManager,
                 stablePartAssignmentsKey(partId),
                 (v) -> Assignments.fromBytes(v).nodes()
                         .stream().map(Assignment::consistentId).collect(Collectors.toSet()),
-                Set.of(node(0).name(), node(2).name()),
+                Set.of(node(0).name(), node(3).name()),
                 TIMEOUT_MILLIS * 2
         );
     }
@@ -171,7 +192,7 @@ public class ItDistributionZonesFilterTest extends ClusterPerTestIntegrationTest
 
         IgniteImpl node0 = node(0);
 
-        node0.sql().execute(null, createZoneSql(2, 3, 10_000, 10_000, filter));
+        node0.sql().execute(null, createZoneSql(2, 3, 10_000, 10_000, filter, STORAGE_PROFILES));
 
         node0.sql().execute(null, createTableSql());
 
@@ -196,7 +217,7 @@ public class ItDistributionZonesFilterTest extends ClusterPerTestIntegrationTest
         @Language("JSON") String firstNodeAttributes = "{region:{attribute:\"US\"},storage:{attribute:\"SSD\"}}";
 
         // This node pass the filter
-        startNode(1, createStartConfig(firstNodeAttributes));
+        startNode(1, createStartConfig(firstNodeAttributes, STORAGE_PROFILES_CONFIGS));
 
         // Expected size is 1 because we have timers equals to 10000, so no scale up will be propagated.
         waitDataNodeAndListenersAreHandled(metaStorageManager, 1, getZoneId(node0));
@@ -226,7 +247,7 @@ public class ItDistributionZonesFilterTest extends ClusterPerTestIntegrationTest
 
         IgniteImpl node0 = node(0);
 
-        node0.sql().execute(null, createZoneSql(2, 3, 10_000, 10_000, filter));
+        node0.sql().execute(null, createZoneSql(2, 3, 10_000, 10_000, filter, STORAGE_PROFILES));
 
         node0.sql().execute(null, createTableSql());
 
@@ -251,7 +272,7 @@ public class ItDistributionZonesFilterTest extends ClusterPerTestIntegrationTest
         @Language("JSON") String firstNodeAttributes = "{region:{attribute:\"US\"},storage:{attribute:\"SSD\"}}";
 
         // This node pass the filter
-        startNode(1, createStartConfig(firstNodeAttributes));
+        startNode(1, createStartConfig(firstNodeAttributes, STORAGE_PROFILES_CONFIGS));
 
         int zoneId = getZoneId(node0);
 
@@ -291,9 +312,9 @@ public class ItDistributionZonesFilterTest extends ClusterPerTestIntegrationTest
         // This node passes the filter
         @Language("JSON") String firstNodeAttributes = "{region:{attribute:\"EU\"},storage:{attribute:\"HDD\"}}";
 
-        IgniteImpl node1 = startNode(1, createStartConfig(firstNodeAttributes));
+        IgniteImpl node1 = startNode(1, createStartConfig(firstNodeAttributes, STORAGE_PROFILES_CONFIGS));
 
-        node1.sql().execute(null, createZoneSql(1, 1, IMMEDIATE_TIMER_VALUE, IMMEDIATE_TIMER_VALUE, filter));
+        node1.sql().execute(null, createZoneSql(1, 1, IMMEDIATE_TIMER_VALUE, IMMEDIATE_TIMER_VALUE, filter, STORAGE_PROFILES));
 
         MetaStorageManager metaStorageManager = (MetaStorageManager) IgniteTestUtils.getFieldValue(
                 node0,
@@ -335,9 +356,9 @@ public class ItDistributionZonesFilterTest extends ClusterPerTestIntegrationTest
         // This node passes the filter
         @Language("JSON") String firstNodeAttributes = "{region:{attribute:\"EU\"},storage:{attribute:\"HDD\"}}";
 
-        startNode(1, createStartConfig(firstNodeAttributes));
+        startNode(1, createStartConfig(firstNodeAttributes, STORAGE_PROFILES_CONFIGS));
 
-        node0.sql().execute(null, createZoneSql(1, 1, IMMEDIATE_TIMER_VALUE, IMMEDIATE_TIMER_VALUE, filter));
+        node0.sql().execute(null, createZoneSql(1, 1, IMMEDIATE_TIMER_VALUE, IMMEDIATE_TIMER_VALUE, filter, STORAGE_PROFILES));
 
         MetaStorageManager metaStorageManager = (MetaStorageManager) IgniteTestUtils.getFieldValue(
                 node0,
@@ -427,15 +448,16 @@ public class ItDistributionZonesFilterTest extends ClusterPerTestIntegrationTest
         assertTrue(metaStorageManager.get(pendingPartAssignmentsKey(partId)).get().empty());
     }
 
-    private static String createZoneSql(int partitions, int replicas, int scaleUp, int scaleDown, String filter) {
+    private static String createZoneSql(int partitions, int replicas, int scaleUp, int scaleDown, String filter, String storageProfiles) {
         String sqlFormat = "CREATE ZONE \"%s\" WITH "
                 + "\"REPLICAS\" = %s, "
                 + "\"PARTITIONS\" = %s, "
                 + "\"DATA_NODES_FILTER\" = '%s', "
                 + "\"DATA_NODES_AUTO_ADJUST_SCALE_UP\" = %s, "
-                + "\"DATA_NODES_AUTO_ADJUST_SCALE_DOWN\" = %s";
+                + "\"DATA_NODES_AUTO_ADJUST_SCALE_DOWN\" = %s, "
+                + "\"STORAGE_PROFILES\" = %s";
 
-        return String.format(sqlFormat, ZONE_NAME, replicas, partitions, filter, scaleUp, scaleDown);
+        return String.format(sqlFormat, ZONE_NAME, replicas, partitions, filter, scaleUp, scaleDown, storageProfiles);
     }
 
     private static String alterZoneSql(String filter) {
@@ -448,8 +470,8 @@ public class ItDistributionZonesFilterTest extends ClusterPerTestIntegrationTest
 
     private static String createTableSql() {
         return String.format(
-                "CREATE TABLE %s(%s INT PRIMARY KEY, %s VARCHAR) WITH PRIMARY_ZONE='%s'",
-                TABLE_NAME, COLUMN_KEY, COLUMN_VAL, ZONE_NAME
+                "CREATE TABLE %s(%s INT PRIMARY KEY, %s VARCHAR) WITH STORAGE_PROFILE='%s',PRIMARY_ZONE='%s'",
+                TABLE_NAME, COLUMN_KEY, COLUMN_VAL, DEFAULT_AIPERSIST_PROFILE_NAME, ZONE_NAME
         );
     }
 
diff --git a/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/distributionzones/ItIgniteDistributionZoneManagerNodeRestartTest.java b/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/distributionzones/ItIgniteDistributionZoneManagerNodeRestartTest.java
index a65c7b340e..adf26389da 100644
--- a/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/distributionzones/ItIgniteDistributionZoneManagerNodeRestartTest.java
+++ b/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/distributionzones/ItIgniteDistributionZoneManagerNodeRestartTest.java
@@ -21,12 +21,14 @@ import static java.util.Collections.emptySet;
 import static java.util.concurrent.CompletableFuture.completedFuture;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.stream.Collectors.toSet;
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_ZONE_NAME;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.IMMEDIATE_TIMER_VALUE;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.INFINITE_TIMER_VALUE;
 import static org.apache.ignite.internal.distributionzones.DistributionZonesTestUtil.assertDataNodesFromManager;
 import static org.apache.ignite.internal.distributionzones.DistributionZonesTestUtil.assertLogicalTopologyInMetastorage;
 import static org.apache.ignite.internal.distributionzones.DistributionZonesTestUtil.assertValueInStorage;
+import static org.apache.ignite.internal.distributionzones.DistributionZonesTestUtil.createZone;
 import static org.apache.ignite.internal.distributionzones.DistributionZonesUtil.dataNodes;
 import static org.apache.ignite.internal.distributionzones.DistributionZonesUtil.toDataNodesMap;
 import static org.apache.ignite.internal.distributionzones.DistributionZonesUtil.zoneDataNodesKey;
@@ -130,17 +132,23 @@ import org.junit.jupiter.params.provider.MethodSource;
 public class ItIgniteDistributionZoneManagerNodeRestartTest extends BaseIgniteRestartTest {
     private static final LogicalNode A = new LogicalNode(
             new ClusterNodeImpl("1", "A", new NetworkAddress("localhost", 123)),
-            Map.of("region", "US", "storage", "SSD", "dataRegionSize", "10")
+            Map.of("region", "US", "storage", "SSD", "dataRegionSize", "10"),
+            Map.of(),
+            List.of(DEFAULT_STORAGE_PROFILE)
     );
 
     private static final LogicalNode B = new LogicalNode(
             new ClusterNodeImpl("2", "B", new NetworkAddress("localhost", 123)),
-            Map.of("region", "EU", "storage", "HHD", "dataRegionSize", "30")
+            Map.of("region", "EU", "storage", "HHD", "dataRegionSize", "30"),
+            Map.of(),
+            List.of(DEFAULT_STORAGE_PROFILE)
     );
 
     private static final LogicalNode C = new LogicalNode(
             new ClusterNodeImpl("3", "C", new NetworkAddress("localhost", 123)),
-            Map.of("region", "CN", "storage", "SSD", "dataRegionSize", "20")
+            Map.of("region", "CN", "storage", "SSD", "dataRegionSize", "20"),
+            Map.of(),
+            List.of(DEFAULT_STORAGE_PROFILE)
     );
 
     private static final String ZONE_NAME = "zone1";
@@ -186,7 +194,7 @@ public class ItIgniteDistributionZoneManagerNodeRestartTest extends BaseIgniteRe
 
         var nodeCfgMgr = new ConfigurationManager(
                 modules.local().rootKeys(),
-                new LocalFileConfigurationStorage(configFile, localConfigurationGenerator),
+                new LocalFileConfigurationStorage(configFile, localConfigurationGenerator, modules.local()),
                 localConfigurationGenerator,
                 ConfigurationValidatorImpl.withDefaultValidators(localConfigurationGenerator, modules.local().validators())
         );
@@ -327,7 +335,7 @@ public class ItIgniteDistributionZoneManagerNodeRestartTest extends BaseIgniteRe
         node.logicalTopology().putNode(B);
         node.logicalTopology().putNode(C);
 
-        createZone(node, ZONE_NAME, IMMEDIATE_TIMER_VALUE, IMMEDIATE_TIMER_VALUE);
+        createZone(getCatalogManager(node), ZONE_NAME, IMMEDIATE_TIMER_VALUE, IMMEDIATE_TIMER_VALUE, null, DEFAULT_STORAGE_PROFILE);
 
         int zoneId = getZoneId(node, ZONE_NAME);
 
@@ -337,7 +345,7 @@ public class ItIgniteDistributionZoneManagerNodeRestartTest extends BaseIgniteRe
         assertDataNodesFromManager(distributionZoneManager, metastore::appliedRevision, catalogManager::latestCatalogVersion, zoneId,
                 Set.of(A, B, C), TIMEOUT_MILLIS);
 
-        Map<String, Map<String, String>> nodeAttributesBeforeRestart = distributionZoneManager.nodesAttributes();
+        Map<String, NodeWithAttributes> nodeAttributesBeforeRestart = distributionZoneManager.nodesAttributes();
 
         node.stop();
 
@@ -345,7 +353,7 @@ public class ItIgniteDistributionZoneManagerNodeRestartTest extends BaseIgniteRe
 
         distributionZoneManager = getDistributionZoneManager(node);
 
-        Map<String, Map<String, String>> nodeAttributesAfterRestart = distributionZoneManager.nodesAttributes();
+        Map<String, NodeWithAttributes> nodeAttributesAfterRestart = distributionZoneManager.nodesAttributes();
 
         assertEquals(3, nodeAttributesAfterRestart.size());
 
@@ -407,7 +415,7 @@ public class ItIgniteDistributionZoneManagerNodeRestartTest extends BaseIgniteRe
         node.logicalTopology().putNode(C);
 
         Set<NodeWithAttributes> logicalTopology = Stream.of(A, B, C)
-                .map(n -> new NodeWithAttributes(n.name(), n.id(), n.userAttributes()))
+                .map(n -> new NodeWithAttributes(n.name(), n.id(), n.userAttributes(), n.storageProfiles()))
                 .collect(toSet());
 
         DistributionZoneManager distributionZoneManager = getDistributionZoneManager(node);
@@ -434,7 +442,7 @@ public class ItIgniteDistributionZoneManagerNodeRestartTest extends BaseIgniteRe
         node.logicalTopology().putNode(B);
 
         Set<NodeWithAttributes> logicalTopology = Stream.of(A, B)
-                .map(n -> new NodeWithAttributes(n.name(), n.id(), n.userAttributes()))
+                .map(n -> new NodeWithAttributes(n.name(), n.id(), n.userAttributes(), n.storageProfiles()))
                 .collect(toSet());
 
         DistributionZoneManager distributionZoneManager = getDistributionZoneManager(node);
@@ -464,7 +472,7 @@ public class ItIgniteDistributionZoneManagerNodeRestartTest extends BaseIgniteRe
         node.logicalTopology().putNode(C);
 
         Set<NodeWithAttributes> newLogicalTopology = Stream.of(A, B, C)
-                .map(n -> new NodeWithAttributes(n.name(), n.id(), n.userAttributes()))
+                .map(n -> new NodeWithAttributes(n.name(), n.id(), n.userAttributes(), n.storageProfiles()))
                 .collect(toSet());
 
         assertTrue(waitForCondition(() -> newLogicalTopology.equals(finalDistributionZoneManager.logicalTopology()), TIMEOUT_MILLIS));
@@ -514,7 +522,7 @@ public class ItIgniteDistributionZoneManagerNodeRestartTest extends BaseIgniteRe
         node.logicalTopology().putNode(C);
 
         Set<NodeWithAttributes> newLogicalTopology = Stream.of(C)
-                .map(n -> new NodeWithAttributes(n.name(), n.id(), n.userAttributes()))
+                .map(n -> new NodeWithAttributes(n.name(), n.id(), n.userAttributes(), n.storageProfiles()))
                 .collect(toSet());
 
         assertTrue(waitForCondition(() -> newLogicalTopology.equals(finalDistributionZoneManager.logicalTopology()), TIMEOUT_MILLIS));
@@ -557,7 +565,7 @@ public class ItIgniteDistributionZoneManagerNodeRestartTest extends BaseIgniteRe
         node.logicalTopology().putNode(C);
 
         Set<NodeWithAttributes> logicalTopology = Stream.of(A, B, C)
-                .map(n -> new NodeWithAttributes(n.name(), n.id(), n.userAttributes()))
+                .map(n -> new NodeWithAttributes(n.name(), n.id(), n.userAttributes(), n.storageProfiles()))
                 .collect(toSet());
 
         DistributionZoneManager distributionZoneManager = getDistributionZoneManager(node);
@@ -605,7 +613,7 @@ public class ItIgniteDistributionZoneManagerNodeRestartTest extends BaseIgniteRe
             return dataNodeKeyOptional.isPresent();
         }));
 
-        createZone(node, "zone1", INFINITE_TIMER_VALUE, INFINITE_TIMER_VALUE);
+        createZone(getCatalogManager(node), "zone1", INFINITE_TIMER_VALUE, INFINITE_TIMER_VALUE, null, DEFAULT_STORAGE_PROFILE);
 
         // Assert that after creation of a zone, data nodes are still tombstone, but not the logical topology, as for default zone.
         assertThat(metastore.get(new ByteArray(dataNodeKey[0])).thenApply(Entry::tombstone), willBe(true));
@@ -805,7 +813,7 @@ public class ItIgniteDistributionZoneManagerNodeRestartTest extends BaseIgniteRe
                 assertTrue(waitForCondition(() -> zoneState.scaleDownTask().isDone(), TIMEOUT_MILLIS));
             }
         } else {
-            createZone(node, ZONE_NAME, scaleUp, scaleDown);
+            createZone(getCatalogManager(node), ZONE_NAME, scaleUp, scaleDown, null, DEFAULT_STORAGE_PROFILE);
         }
     }
 
@@ -848,10 +856,6 @@ public class ItIgniteDistributionZoneManagerNodeRestartTest extends BaseIgniteRe
         return DistributionZonesTestUtil.getZoneId(getCatalogManager(node), zoneName, node.clock().nowLong());
     }
 
-    private static void createZone(PartialNode node, String zoneName, int scaleUp, int scaleDown) {
-        DistributionZonesTestUtil.createZone(getCatalogManager(node), zoneName, scaleUp, scaleDown, null);
-    }
-
     private static void alterZone(
             PartialNode node,
             String zoneName,
diff --git a/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/DistributionZoneManager.java b/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/DistributionZoneManager.java
index 5fc800f549..67b685d878 100644
--- a/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/DistributionZoneManager.java
+++ b/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/DistributionZoneManager.java
@@ -181,7 +181,7 @@ public class DistributionZoneManager implements IgniteComponent {
      *
      * @see <a href="https://github.com/apache/ignite-3/blob/main/modules/distribution-zones/tech-notes/filters.md">Filter documentation</a>
      */
-    private Map<String, Map<String, String>> nodesAttributes = new ConcurrentHashMap<>();
+    private Map<String, NodeWithAttributes> nodesAttributes = new ConcurrentHashMap<>();
 
     /** Watch listener for logical topology keys. */
     private final WatchListener topologyWatchListener;
@@ -766,7 +766,7 @@ public class DistributionZoneManager implements IgniteComponent {
             zoneIds.add(zone.id());
         }
 
-        newLogicalTopology.forEach(n -> nodesAttributes.put(n.nodeId(), n.nodeAttributes()));
+        newLogicalTopology.forEach(n -> nodesAttributes.put(n.nodeId(), n));
 
         logicalTopology = newLogicalTopology;
 
@@ -1372,7 +1372,7 @@ public class DistributionZoneManager implements IgniteComponent {
      *
      * @return Mapping {@code nodeId} -> node's attributes.
      */
-    public Map<String, Map<String, String>> nodesAttributes() {
+    public Map<String, NodeWithAttributes> nodesAttributes() {
         return nodesAttributes;
     }
 
diff --git a/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/DistributionZonesUtil.java b/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/DistributionZonesUtil.java
index 7e65b874c7..8882a5e862 100644
--- a/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/DistributionZonesUtil.java
+++ b/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/DistributionZonesUtil.java
@@ -37,13 +37,18 @@ import static org.apache.ignite.internal.util.ByteUtils.fromBytes;
 import com.jayway.jsonpath.Configuration;
 import com.jayway.jsonpath.JsonPath;
 import com.jayway.jsonpath.Option;
+import java.util.Arrays;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ThreadPoolExecutor;
 import org.apache.ignite.internal.catalog.CatalogService;
+import org.apache.ignite.internal.catalog.commands.StorageProfileParams;
+import org.apache.ignite.internal.catalog.descriptors.CatalogStorageProfileDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.CatalogTableDescriptor;
+import org.apache.ignite.internal.catalog.descriptors.CatalogZoneDescriptor;
 import org.apache.ignite.internal.cluster.management.topology.api.LogicalNode;
 import org.apache.ignite.internal.distributionzones.DistributionZoneManager.ZoneState;
 import org.apache.ignite.internal.lang.ByteArray;
@@ -377,9 +382,9 @@ public class DistributionZonesUtil {
      * @param topologyVersion Logical topology version.
      * @return Update command for the meta storage.
      */
-    public static Update updateLogicalTopologyAndVersion(Set<LogicalNode> logicalTopology, long topologyVersion) {
+    static Update updateLogicalTopologyAndVersion(Set<LogicalNode> logicalTopology, long topologyVersion) {
         Set<NodeWithAttributes> topologyFromCmg = logicalTopology.stream()
-                .map(n -> new NodeWithAttributes(n.name(), n.id(), n.userAttributes()))
+                .map(n -> new NodeWithAttributes(n.name(), n.id(), n.userAttributes(), n.storageProfiles()))
                 .collect(toSet());
 
         return ops(
@@ -469,7 +474,7 @@ public class DistributionZonesUtil {
      * @param filter Valid {@link JsonPath} filter of JSON fields.
      * @return True if {@code nodeAttributes} satisfy {@code filter}, false otherwise. Returns true if {@code nodeAttributes} is empty.
      */
-    public static boolean filter(Map<String, String> nodeAttributes, String filter) {
+    public static boolean filterNodeAttributes(Map<String, String> nodeAttributes, String filter) {
         if (filter.equals(DEFAULT_FILTER)) {
             return true;
         }
@@ -502,25 +507,63 @@ public class DistributionZonesUtil {
     }
 
     /**
-     * Filters {@code dataNodes} according to the provided {@code filter}.
-     * Nodes' attributes are taken from {@code nodesAttributes} map.
+     * Filters storage profiles.
+     *
+     * @param node Node with storage profile attributes.
+     * @param zoneStorageProfiles Zone's storage profiles.
+     * @return True, if matches, false otherwise.
+     */
+    public static boolean filterStorageProfiles(
+            NodeWithAttributes node,
+            List<CatalogStorageProfileDescriptor> zoneStorageProfiles
+    ) {
+        if (node.storageProfiles() == null) {
+            return false;
+        }
+
+        List<String> zoneStorageProfilesNames = zoneStorageProfiles.stream()
+                .map(CatalogStorageProfileDescriptor::storageProfile)
+                .collect(toList());
+
+        return new HashSet<>(node.storageProfiles()).containsAll(zoneStorageProfilesNames);
+    }
+
+    /**
+     * Filters {@code dataNodes} according to the provided filter and storage profiles from {@code zoneDescriptor}.
+     * Nodes' attributes and storage profiles are taken from {@code nodesAttributes} map.
      *
      * @param dataNodes Data nodes.
-     * @param filter Filter for data nodes.
+     * @param zoneDescriptor Zone descriptor.
      * @param nodesAttributes Nodes' attributes which used for filtering.
      * @return Filtered data nodes.
      */
     public static Set<String> filterDataNodes(
             Set<Node> dataNodes,
-            String filter,
-            Map<String, Map<String, String>> nodesAttributes
+            CatalogZoneDescriptor zoneDescriptor,
+            Map<String, NodeWithAttributes> nodesAttributes
     ) {
+
         return dataNodes.stream()
-                .filter(n -> filter(nodesAttributes.get(n.nodeId()), filter))
+                .filter(n -> filterNodeAttributes(nodesAttributes.get(n.nodeId()).userAttributes(), zoneDescriptor.filter()))
+                .filter(n -> filterStorageProfiles(nodesAttributes.get(n.nodeId()), zoneDescriptor.storageProfiles().profiles()))
                 .map(Node::nodeName)
                 .collect(toSet());
     }
 
+    /**
+     * Parse string representation of storage profiles.
+     *
+     * @param storageProfiles String representation of storage profiles.
+     * @return List of storage profile params
+     */
+    public static List<StorageProfileParams> parseStorageProfiles(String storageProfiles) {
+        List<String> items = Arrays.asList(storageProfiles.split("\\s*,\\s*"));
+
+        return items.stream()
+                .map(p -> StorageProfileParams.builder().storageProfile(p).build())
+                .collect(toList());
+    }
+
     /**
      * Create an executor for the zone manager.
      * Used a striped thread executor to avoid concurrent executing several tasks for the same zone.
diff --git a/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/NodeWithAttributes.java b/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/NodeWithAttributes.java
index eb11971d4b..82b6f67520 100644
--- a/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/NodeWithAttributes.java
+++ b/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/NodeWithAttributes.java
@@ -18,8 +18,10 @@
 package org.apache.ignite.internal.distributionzones;
 
 import java.io.Serializable;
+import java.util.List;
 import java.util.Map;
 import org.apache.ignite.internal.cluster.management.topology.api.LogicalNode;
+import org.jetbrains.annotations.Nullable;
 
 /**
  * Structure that represents node with the attributes and which we store in Meta Storage when we store logical topology.
@@ -30,11 +32,37 @@ public class NodeWithAttributes implements Serializable {
 
     private final Node node;
 
-    private final Map<String, String> nodeAttributes;
+    private final Map<String, String> userAttributes;
 
-    public NodeWithAttributes(String nodeName, String nodeId, Map<String, String> nodeAttributes) {
+    private final List<String> storageProfiles;
+
+    /**
+     * Constructor.
+     *
+     * @param nodeName Node name.
+     * @param nodeId Node consistent identifier.
+     * @param userAttributes Key value map of user's node's attributes.
+     */
+    public NodeWithAttributes(String nodeName, String nodeId, @Nullable Map<String, String> userAttributes) {
+        this(nodeName, nodeId, userAttributes, List.of());
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param nodeName Node name.
+     * @param nodeId Node consistent identifier.
+     * @param userAttributes Key value map of user's node's attributes.
+     * @param storageProfiles List of supported storage profiles on the node.
+     */
+    public NodeWithAttributes(
+            String nodeName,
+            String nodeId,
+            @Nullable Map<String, String> userAttributes,
+            @Nullable List<String> storageProfiles) {
         this.node = new Node(nodeName, nodeId);
-        this.nodeAttributes = nodeAttributes;
+        this.userAttributes = userAttributes == null ? Map.of() : userAttributes;
+        this.storageProfiles = storageProfiles == null ? List.of() : storageProfiles;
     }
 
     @Override
@@ -54,7 +82,9 @@ public class NodeWithAttributes implements Serializable {
 
         NodeWithAttributes that = (NodeWithAttributes) obj;
 
-        return node.equals(that.node);
+        return node.equals(that.node)
+                && this.userAttributes.equals(that.userAttributes)
+                && this.storageProfiles.equals(that.storageProfiles);
     }
 
     public String nodeName() {
@@ -69,8 +99,12 @@ public class NodeWithAttributes implements Serializable {
         return node;
     }
 
-    public Map<String, String> nodeAttributes() {
-        return nodeAttributes;
+    public Map<String, String> userAttributes() {
+        return userAttributes;
+    }
+
+    public List<String> storageProfiles() {
+        return storageProfiles;
     }
 
     @Override
diff --git a/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/causalitydatanodes/CausalityDataNodesEngine.java b/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/causalitydatanodes/CausalityDataNodesEngine.java
index 40bd117016..d41d9ffd08 100644
--- a/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/causalitydatanodes/CausalityDataNodesEngine.java
+++ b/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/causalitydatanodes/CausalityDataNodesEngine.java
@@ -167,8 +167,6 @@ public class CausalityDataNodesEngine {
 
             long descLastUpdateRevision = zoneDescriptor.updateToken();
 
-            String filter = zoneDescriptor.filter();
-
             // Get revisions of the last scale up and scale down event which triggered immediate data nodes recalculation.
             long lastScaleUpRevision = getRevisionsOfLastScaleUpEvent(causalityToken, catalogVersion, zoneId);
             long lastScaleDownRevision = getRevisionsOfLastScaleDownEvent(causalityToken, catalogVersion, zoneId);
@@ -194,7 +192,7 @@ public class CausalityDataNodesEngine {
 
                 Set<Node> logicalTopologyNodes = logicalTopology.stream().map(n -> n.node()).collect(toSet());
 
-                return filterDataNodes(logicalTopologyNodes, filter, distributionZoneManager.nodesAttributes());
+                return filterDataNodes(logicalTopologyNodes, zoneDescriptor, distributionZoneManager.nodesAttributes());
             }
 
             ZoneState zoneState = zonesState.get(zoneId);
@@ -255,7 +253,7 @@ public class CausalityDataNodesEngine {
             }
 
             // Apply the filter to get the final data nodes set.
-            return filterDataNodes(finalDataNodes, filter, distributionZoneManager.nodesAttributes());
+            return filterDataNodes(finalDataNodes, zoneDescriptor, distributionZoneManager.nodesAttributes());
         }));
     }
 
diff --git a/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/rebalance/DistributionZoneRebalanceEngine.java b/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/rebalance/DistributionZoneRebalanceEngine.java
index f537868a64..39448ae24f 100644
--- a/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/rebalance/DistributionZoneRebalanceEngine.java
+++ b/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/rebalance/DistributionZoneRebalanceEngine.java
@@ -216,7 +216,7 @@ public class DistributionZoneRebalanceEngine {
 
                     Set<String> filteredDataNodes = filterDataNodes(
                             dataNodes,
-                            zoneDescriptor.filter(),
+                            zoneDescriptor,
                             distributionZoneManager.nodesAttributes()
                     );
 
diff --git a/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/BaseDistributionZoneManagerTest.java b/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/BaseDistributionZoneManagerTest.java
index 0a34a29c95..40e2783e77 100644
--- a/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/BaseDistributionZoneManagerTest.java
+++ b/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/BaseDistributionZoneManagerTest.java
@@ -160,6 +160,23 @@ public abstract class BaseDistributionZoneManagerTest extends BaseIgniteAbstract
         );
     }
 
+    protected void createZone(
+            String zoneName,
+            @Nullable Integer dataNodesAutoAdjustScaleUp,
+            @Nullable Integer dataNodesAutoAdjustScaleDown,
+            @Nullable String filter,
+            String storageProfiles
+    ) {
+        DistributionZonesTestUtil.createZone(
+                catalogManager,
+                zoneName,
+                dataNodesAutoAdjustScaleUp,
+                dataNodesAutoAdjustScaleDown,
+                filter,
+                storageProfiles
+        );
+    }
+
     protected void alterZone(
             String zoneName,
             @Nullable Integer dataNodesAutoAdjustScaleUp,
diff --git a/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneFiltersTest.java b/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneAttributeFiltersTest.java
similarity index 79%
rename from modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneFiltersTest.java
rename to modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneAttributeFiltersTest.java
index 6c4c57c34f..18e85e9f1b 100644
--- a/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneFiltersTest.java
+++ b/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneAttributeFiltersTest.java
@@ -18,7 +18,7 @@
 package org.apache.ignite.internal.distributionzones;
 
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_FILTER;
-import static org.apache.ignite.internal.distributionzones.DistributionZonesUtil.filter;
+import static org.apache.ignite.internal.distributionzones.DistributionZonesUtil.filterNodeAttributes;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
@@ -28,14 +28,14 @@ import org.junit.jupiter.api.Test;
 /**
  * Tests scenarios for filtering attributes of a node.
  */
-public class DistributionZoneFiltersTest {
+public class DistributionZoneAttributeFiltersTest {
     @Test
     void testNodeAttributesFilterScenario1() {
         Map<String, String> newAttributesMap = Map.of("region", "US", "storage", "SSD", "dataRegionSize", "10");
 
         String filter = "$[?(@.dataRegionSize == 10)]";
 
-        assertTrue(filter(newAttributesMap, filter));
+        assertTrue(filterNodeAttributes(newAttributesMap, filter));
     }
 
     @Test
@@ -44,7 +44,7 @@ public class DistributionZoneFiltersTest {
 
         String filter = "$[?(@.region == 'US')]";
 
-        assertTrue(filter(newAttributesMap, filter));
+        assertTrue(filterNodeAttributes(newAttributesMap, filter));
     }
 
     @Test
@@ -53,7 +53,7 @@ public class DistributionZoneFiltersTest {
 
         String filter = "$[?(@.dataRegionSize == 10 && @.region == 'US')]";
 
-        assertTrue(filter(newAttributesMap, filter));
+        assertTrue(filterNodeAttributes(newAttributesMap, filter));
     }
 
     @Test
@@ -62,7 +62,7 @@ public class DistributionZoneFiltersTest {
 
         String filter = "$[?(@.dataRegionSize == 10 && @.region == 'US')]";
 
-        assertFalse(filter(newAttributesMap, filter));
+        assertFalse(filterNodeAttributes(newAttributesMap, filter));
     }
 
     @Test
@@ -71,7 +71,7 @@ public class DistributionZoneFiltersTest {
 
         String filter = "$[?(@.dataRegionSize == 10 && @.region == 'US')]";
 
-        assertFalse(filter(newAttributesMap, filter));
+        assertFalse(filterNodeAttributes(newAttributesMap, filter));
     }
 
     @Test
@@ -80,21 +80,21 @@ public class DistributionZoneFiltersTest {
 
         String filter = "$[?(@.storage == 'SSD' && @.region == 'US')]";
 
-        assertFalse(filter(newAttributesMap, filter));
+        assertFalse(filterNodeAttributes(newAttributesMap, filter));
     }
 
     @Test
     void testNodeAttributesFilterScenario7() {
         Map<String, String> newAttributesMap = Map.of("region", "US", "storage", "SSD", "dataRegionSize", "10");
 
-        assertTrue(filter(newAttributesMap, DEFAULT_FILTER));
+        assertTrue(filterNodeAttributes(newAttributesMap, DEFAULT_FILTER));
     }
 
     @Test
     void testNodeAttributesFilterScenario8() {
         Map<String, String> newAttributesMap = Map.of();
 
-        assertTrue(filter(newAttributesMap, DEFAULT_FILTER));
+        assertTrue(filterNodeAttributes(newAttributesMap, DEFAULT_FILTER));
     }
 
     @Test
@@ -103,7 +103,7 @@ public class DistributionZoneFiltersTest {
 
         String filter = "$.[?(@.newValue == 100)]";
 
-        assertFalse(filter(newAttributesMap, filter));
+        assertFalse(filterNodeAttributes(newAttributesMap, filter));
     }
 
     @Test
@@ -112,7 +112,7 @@ public class DistributionZoneFiltersTest {
 
         String filter = "$.[?(@.newValue != 100)]";
 
-        assertTrue(filter(newAttributesMap, filter));
+        assertTrue(filterNodeAttributes(newAttributesMap, filter));
     }
 
     @Test
@@ -121,7 +121,7 @@ public class DistributionZoneFiltersTest {
 
         String filter = "$.[?(@.newValue && @.newValue != 100)]";
 
-        assertFalse(filter(newAttributesMap, filter));
+        assertFalse(filterNodeAttributes(newAttributesMap, filter));
     }
 
     @Test
@@ -130,7 +130,7 @@ public class DistributionZoneFiltersTest {
 
         String filter = "$[?(@.dataRegionSize != 10)]";
 
-        assertFalse(filter(newAttributesMap, filter));
+        assertFalse(filterNodeAttributes(newAttributesMap, filter));
     }
 
     @Test
@@ -139,7 +139,7 @@ public class DistributionZoneFiltersTest {
 
         String filter = "$[?(@.region != 'EU')]";
 
-        assertTrue(filter(newAttributesMap, filter));
+        assertTrue(filterNodeAttributes(newAttributesMap, filter));
     }
 
     @Test
@@ -148,7 +148,7 @@ public class DistributionZoneFiltersTest {
 
         String filter = "$[?(@.region != 'EU' && @.dataRegionSize > 5)]";
 
-        assertTrue(filter(newAttributesMap, filter));
+        assertTrue(filterNodeAttributes(newAttributesMap, filter));
     }
 
     @Test
@@ -157,7 +157,7 @@ public class DistributionZoneFiltersTest {
 
         String filter = "$[?(@.region != 'EU' && @.dataRegionSize < 5)]";
 
-        assertFalse(filter(newAttributesMap, filter));
+        assertFalse(filterNodeAttributes(newAttributesMap, filter));
     }
 
     @Test
@@ -166,7 +166,7 @@ public class DistributionZoneFiltersTest {
 
         String filter = "$[?(@.dataRegionSize > 5 && @.dataRegionSize < 5)]";
 
-        assertFalse(filter(newAttributesMap, filter));
+        assertFalse(filterNodeAttributes(newAttributesMap, filter));
     }
 
     @Test
@@ -175,7 +175,7 @@ public class DistributionZoneFiltersTest {
 
         String filter = "$[?(@.region == 'US' && @.region == 'EU')]";
 
-        assertFalse(filter(newAttributesMap, filter));
+        assertFalse(filterNodeAttributes(newAttributesMap, filter));
     }
 
     @Test
@@ -184,7 +184,7 @@ public class DistributionZoneFiltersTest {
 
         String filter = "$[?(@.region == 'EU' || @.dataRegionSize > 5)]";
 
-        assertTrue(filter(newAttributesMap, filter));
+        assertTrue(filterNodeAttributes(newAttributesMap, filter));
     }
 
     @Test
@@ -193,7 +193,7 @@ public class DistributionZoneFiltersTest {
 
         String filter = "region";
 
-        assertTrue(filter(newAttributesMap, filter));
+        assertTrue(filterNodeAttributes(newAttributesMap, filter));
     }
 
     @Test
@@ -202,6 +202,6 @@ public class DistributionZoneFiltersTest {
 
         String filter = "region";
 
-        assertFalse(filter(newAttributesMap, filter));
+        assertFalse(filterNodeAttributes(newAttributesMap, filter));
     }
 }
diff --git a/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerAlterFilterTest.java b/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerAlterFilterTest.java
index f6c9438a6f..d8d6427c4a 100644
--- a/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerAlterFilterTest.java
+++ b/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerAlterFilterTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.distributionzones;
 
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_ZONE_NAME;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.IMMEDIATE_TIMER_VALUE;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.INFINITE_TIMER_VALUE;
@@ -30,6 +31,7 @@ import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doAnswer;
 
 import java.util.Arrays;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import org.apache.ignite.internal.cluster.management.topology.api.LogicalNode;
@@ -47,22 +49,30 @@ public class DistributionZoneManagerAlterFilterTest extends BaseDistributionZone
 
     private static final LogicalNode A = new LogicalNode(
             new ClusterNodeImpl("1", "A", new NetworkAddress("localhost", 123)),
-            Map.of("region", "US", "storage", "SSD", "dataRegionSize", "10")
+            Map.of("region", "US", "storage", "SSD", "dataRegionSize", "10"),
+            Map.of(),
+            List.of(DEFAULT_STORAGE_PROFILE)
     );
 
     private static final LogicalNode B = new LogicalNode(
             new ClusterNodeImpl("2", "B", new NetworkAddress("localhost", 123)),
-            Map.of("region", "EU", "storage", "HHD", "dataRegionSize", "30")
+            Map.of("region", "EU", "storage", "HHD", "dataRegionSize", "30"),
+            Map.of(),
+            List.of(DEFAULT_STORAGE_PROFILE)
     );
 
     private static final LogicalNode C = new LogicalNode(
             new ClusterNodeImpl("3", "C", new NetworkAddress("localhost", 123)),
-            Map.of("region", "CN", "storage", "SSD", "dataRegionSize", "20")
+            Map.of("region", "CN", "storage", "SSD", "dataRegionSize", "20"),
+            Map.of(),
+            List.of(DEFAULT_STORAGE_PROFILE)
     );
 
     private static final LogicalNode D = new LogicalNode(
             new ClusterNodeImpl("4", "D", new NetworkAddress("localhost", 123)),
-            Map.of("region", "CN", "storage", "HDD", "dataRegionSize", "20")
+            Map.of("region", "CN", "storage", "HDD", "dataRegionSize", "20"),
+            Map.of(),
+            List.of(DEFAULT_STORAGE_PROFILE)
     );
 
     /**
@@ -195,7 +205,9 @@ public class DistributionZoneManagerAlterFilterTest extends BaseDistributionZone
 
         LogicalNode e = new LogicalNode(
                 new ClusterNodeImpl("5", "E", new NetworkAddress("localhost", 123)),
-                Map.of("region", "CN", "storage", "HDD", "dataRegionSize", "20")
+                Map.of("region", "CN", "storage", "HDD", "dataRegionSize", "20"),
+                Map.of(),
+                List.of(DEFAULT_STORAGE_PROFILE)
         );
 
         doAnswer(invocation -> {
@@ -252,7 +264,7 @@ public class DistributionZoneManagerAlterFilterTest extends BaseDistributionZone
         if (DEFAULT_ZONE_NAME.equals(zoneName)) {
             alterZone(DEFAULT_ZONE_NAME, scaleUpTimer, scaleDownTimer, FILTER);
         } else {
-            createZone(ZONE_NAME, scaleUpTimer, scaleDownTimer, FILTER);
+            createZone(ZONE_NAME, scaleUpTimer, scaleDownTimer, FILTER, DEFAULT_STORAGE_PROFILE);
         }
 
         assertDataNodesFromManager(distributionZoneManager, metaStorageManager::appliedRevision, catalogManager::latestCatalogVersion,
diff --git a/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerConfigurationChangesTest.java b/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerConfigurationChangesTest.java
index 882291c548..260a191723 100644
--- a/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerConfigurationChangesTest.java
+++ b/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerConfigurationChangesTest.java
@@ -19,7 +19,7 @@ package org.apache.ignite.internal.distributionzones;
 
 import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_ZONE_NAME;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.INFINITE_TIMER_VALUE;
-import static org.apache.ignite.internal.distributionzones.DistributionZonesTestUtil.assertDataNodesForZone;
+import static org.apache.ignite.internal.distributionzones.DistributionZonesTestUtil.assertDataNodesFromLogicalNodesInStorage;
 import static org.apache.ignite.internal.distributionzones.DistributionZonesTestUtil.assertLogicalTopology;
 import static org.apache.ignite.internal.distributionzones.DistributionZonesUtil.zoneScaleDownChangeTriggerKey;
 import static org.apache.ignite.internal.distributionzones.DistributionZonesUtil.zoneScaleUpChangeTriggerKey;
@@ -55,7 +55,7 @@ public class DistributionZoneManagerConfigurationChangesTest extends BaseDistrib
 
         assertLogicalTopology(nodes, keyValueStorage);
 
-        assertDataNodesForZone(getZoneId(DEFAULT_ZONE_NAME), nodes, keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(getZoneId(DEFAULT_ZONE_NAME), nodes, keyValueStorage);
     }
 
     @Test
@@ -73,7 +73,7 @@ public class DistributionZoneManagerConfigurationChangesTest extends BaseDistrib
 
         int zoneId = getZoneId(ZONE_NAME);
 
-        assertDataNodesForZone(zoneId, nodes, keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(zoneId, nodes, keyValueStorage);
 
         dropZone(ZONE_NAME);
 
@@ -94,7 +94,7 @@ public class DistributionZoneManagerConfigurationChangesTest extends BaseDistrib
     }
 
     private void assertZonesKeysInMetaStorage(int zoneId, @Nullable Set<LogicalNode> clusterNodes) throws InterruptedException {
-        assertDataNodesForZone(zoneId, clusterNodes, keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(zoneId, clusterNodes, keyValueStorage);
 
         if (clusterNodes != null) {
             assertTrue(waitForCondition(() -> keyValueStorage.get(zoneScaleUpChangeTriggerKey(zoneId).bytes()).value() != null, 5000));
diff --git a/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerFilterTest.java b/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerFilterTest.java
index 8e2be2ccd8..d3e8352297 100644
--- a/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerFilterTest.java
+++ b/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerFilterTest.java
@@ -17,9 +17,11 @@
 
 package org.apache.ignite.internal.distributionzones;
 
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.IMMEDIATE_TIMER_VALUE;
 import static org.apache.ignite.internal.distributionzones.DistributionZonesTestUtil.assertDataNodesFromManager;
 
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import org.apache.ignite.internal.cluster.management.topology.api.LogicalNode;
@@ -33,22 +35,30 @@ import org.junit.jupiter.api.Test;
 public class DistributionZoneManagerFilterTest extends BaseDistributionZoneManagerTest {
     private static final LogicalNode A = new LogicalNode(
             new ClusterNodeImpl("1", "A", new NetworkAddress("localhost", 123)),
-            Map.of("region", "US", "storage", "SSD", "dataRegionSize", "10")
+            Map.of("region", "US", "storage", "SSD", "dataRegionSize", "10"),
+            Map.of(),
+            List.of(DEFAULT_STORAGE_PROFILE)
     );
 
     private static final LogicalNode B = new LogicalNode(
             new ClusterNodeImpl("2", "B", new NetworkAddress("localhost", 123)),
-            Map.of("region", "EU", "storage", "HHD", "dataRegionSize", "30")
+            Map.of("region", "EU", "storage", "HHD", "dataRegionSize", "30"),
+            Map.of(),
+            List.of(DEFAULT_STORAGE_PROFILE)
     );
 
     private static final LogicalNode C = new LogicalNode(
             new ClusterNodeImpl("3", "C", new NetworkAddress("localhost", 123)),
-            Map.of("region", "CN", "storage", "SSD", "dataRegionSize", "20")
+            Map.of("region", "CN", "storage", "SSD", "dataRegionSize", "20"),
+            Map.of(),
+            List.of(DEFAULT_STORAGE_PROFILE)
     );
 
     private static final LogicalNode D = new LogicalNode(
             new ClusterNodeImpl("4", "D", new NetworkAddress("localhost", 123)),
-            Map.of("region", "CN", "storage", "SSD", "dataRegionSize", "20")
+            Map.of("region", "CN", "storage", "SSD", "dataRegionSize", "20"),
+            Map.of(),
+            List.of(DEFAULT_STORAGE_PROFILE)
     );
 
     @Test
@@ -79,7 +89,9 @@ public class DistributionZoneManagerFilterTest extends BaseDistributionZoneManag
 
         LogicalNode newB = new LogicalNode(
                 new ClusterNodeImpl("2", "newB", new NetworkAddress("localhost", 123)),
-                Map.of("region", "US", "storage", "HHD", "dataRegionSize", "30")
+                Map.of("region", "US", "storage", "HHD", "dataRegionSize", "30"),
+                Map.of(),
+                List.of(DEFAULT_STORAGE_PROFILE)
         );
 
         topology.putNode(newB);
@@ -103,7 +115,7 @@ public class DistributionZoneManagerFilterTest extends BaseDistributionZoneManag
         topology.putNode(B);
         topology.putNode(C);
 
-        createZone(ZONE_NAME, IMMEDIATE_TIMER_VALUE, IMMEDIATE_TIMER_VALUE, filter);
+        createZone(ZONE_NAME, IMMEDIATE_TIMER_VALUE, IMMEDIATE_TIMER_VALUE, filter, DEFAULT_STORAGE_PROFILE);
 
         assertDataNodesFromManager(distributionZoneManager, metaStorageManager::appliedRevision, catalogManager::latestCatalogVersion,
                 getZoneId(ZONE_NAME), Set.of(A, C), ZONE_MODIFICATION_AWAIT_TIMEOUT);
diff --git a/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerScaleUpScaleDownTest.java b/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerScaleUpScaleDownTest.java
index 77ada19e63..7c4f81d614 100644
--- a/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerScaleUpScaleDownTest.java
+++ b/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerScaleUpScaleDownTest.java
@@ -20,8 +20,7 @@ package org.apache.ignite.internal.distributionzones;
 import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_ZONE_NAME;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.IMMEDIATE_TIMER_VALUE;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.INFINITE_TIMER_VALUE;
-import static org.apache.ignite.internal.distributionzones.DistributionZonesTestUtil.assertDataNodesForZone;
-import static org.apache.ignite.internal.distributionzones.DistributionZonesTestUtil.assertDataNodesForZoneWithAttributes;
+import static org.apache.ignite.internal.distributionzones.DistributionZonesTestUtil.assertDataNodesFromLogicalNodesInStorage;
 import static org.apache.ignite.internal.distributionzones.DistributionZonesTestUtil.assertLogicalTopology;
 import static org.apache.ignite.internal.distributionzones.DistributionZonesTestUtil.assertZoneScaleDownChangeTriggerKey;
 import static org.apache.ignite.internal.distributionzones.DistributionZonesTestUtil.assertZoneScaleUpChangeTriggerKey;
@@ -90,7 +89,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
 
         int defaultZoneId = getZoneId(DEFAULT_ZONE_NAME);
 
-        assertDataNodesForZone(defaultZoneId, clusterNodes, keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(defaultZoneId, clusterNodes, keyValueStorage);
 
         topology.putNode(NODE_2);
 
@@ -102,7 +101,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
 
         int zoneId = getZoneId(ZONE_NAME);
 
-        assertDataNodesForZone(zoneId, clusterNodes2, keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(zoneId, clusterNodes2, keyValueStorage);
 
         topology.putNode(NODE_3);
 
@@ -110,8 +109,8 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
 
         assertLogicalTopology(clusterNodes3, keyValueStorage);
 
-        assertDataNodesForZone(zoneId, clusterNodes3, keyValueStorage);
-        assertDataNodesForZone(defaultZoneId, clusterNodes3, keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(zoneId, clusterNodes3, keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(defaultZoneId, clusterNodes3, keyValueStorage);
     }
 
     @Test
@@ -124,8 +123,8 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
 
         topology.putNode(NODE_1);
 
-        assertDataNodesForZone(getZoneId(DEFAULT_ZONE_NAME), Set.of(NODE_1), keyValueStorage);
-        assertDataNodesForZone(getZoneId(ZONE_NAME), Set.of(NODE_1), keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(getZoneId(DEFAULT_ZONE_NAME), Set.of(NODE_1), keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(getZoneId(ZONE_NAME), Set.of(NODE_1), keyValueStorage);
     }
 
     @Test
@@ -140,13 +139,13 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
 
         int defaultZoneId = getZoneId(DEFAULT_ZONE_NAME);
 
-        assertDataNodesForZone(defaultZoneId, clusterNodes, keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(defaultZoneId, clusterNodes, keyValueStorage);
 
         createZone(ZONE_NAME, null, IMMEDIATE_TIMER_VALUE, null);
 
         int zoneId = getZoneId(ZONE_NAME);
 
-        assertDataNodesForZone(zoneId, clusterNodes, keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(zoneId, clusterNodes, keyValueStorage);
 
         topology.removeNodes(Set.of(NODE_2));
 
@@ -154,10 +153,10 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
 
         assertLogicalTopology(clusterNodes2, keyValueStorage);
 
-        assertDataNodesForZone(zoneId, clusterNodes2, keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(zoneId, clusterNodes2, keyValueStorage);
 
         // Check that default zone still has both node1 and node2 because dafault zones' scaleDown is INF.
-        assertDataNodesForZone(defaultZoneId, clusterNodes, keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(defaultZoneId, clusterNodes, keyValueStorage);
     }
 
     @Test
@@ -170,7 +169,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
 
         int defaultZoneId = getZoneId(DEFAULT_ZONE_NAME);
 
-        assertDataNodesForZone(defaultZoneId, clusterNodes, keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(defaultZoneId, clusterNodes, keyValueStorage);
 
         alterZone(DEFAULT_ZONE_NAME, INFINITE_TIMER_VALUE, INFINITE_TIMER_VALUE, null);
 
@@ -182,7 +181,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
 
         alterZone(DEFAULT_ZONE_NAME, IMMEDIATE_TIMER_VALUE, INFINITE_TIMER_VALUE, null);
 
-        assertDataNodesForZone(defaultZoneId, clusterNodes2, keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(defaultZoneId, clusterNodes2, keyValueStorage);
     }
 
     @Test
@@ -197,7 +196,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
 
         int defaultZoneId = getZoneId(DEFAULT_ZONE_NAME);
 
-        assertDataNodesForZone(defaultZoneId, clusterNodes, keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(defaultZoneId, clusterNodes, keyValueStorage);
 
         alterZone(DEFAULT_ZONE_NAME, INFINITE_TIMER_VALUE, INFINITE_TIMER_VALUE, null);
 
@@ -209,7 +208,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
 
         alterZone(DEFAULT_ZONE_NAME, INFINITE_TIMER_VALUE, IMMEDIATE_TIMER_VALUE, null);
 
-        assertDataNodesForZone(defaultZoneId, clusterNodes2, keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(defaultZoneId, clusterNodes2, keyValueStorage);
     }
 
     @Test
@@ -228,7 +227,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
 
         int zoneId = getZoneId(ZONE_NAME);
 
-        assertDataNodesForZone(zoneId, clusterNodes2, keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(zoneId, clusterNodes2, keyValueStorage);
 
         assertNotNull(keyValueStorage.get(zoneScaleUpChangeTriggerKey(zoneId).bytes()).value(),
                 "zoneScaleUpChangeTriggerKey must be not null.");
@@ -237,7 +236,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
 
         dropZone(ZONE_NAME);
 
-        assertDataNodesForZone(zoneId, null, keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(zoneId, null, keyValueStorage);
         assertZoneScaleUpChangeTriggerKey(null, zoneId, keyValueStorage);
         assertZoneScaleDownChangeTriggerKey(null, zoneId, keyValueStorage);
     }
@@ -260,7 +259,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
 
         int zoneId = getZoneId(ZONE_NAME);
 
-        assertDataNodesForZone(zoneId, clusterNodes2, keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(zoneId, clusterNodes2, keyValueStorage);
 
         assertNotNull(keyValueStorage.get(zoneScaleUpChangeTriggerKey(zoneId).bytes()).value(),
                 "zoneScaleUpChangeTriggerKey must be not null.");
@@ -269,7 +268,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
 
         dropZone(ZONE_NAME);
 
-        assertDataNodesForZone(zoneId, null, keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(zoneId, null, keyValueStorage);
         assertZoneScaleUpChangeTriggerKey(null, zoneId, keyValueStorage);
         assertZoneScaleDownChangeTriggerKey(null, zoneId, keyValueStorage);
     }
@@ -282,13 +281,13 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
 
         int zoneId = getZoneId(ZONE_NAME);
 
-        assertDataNodesForZone(zoneId, Set.of(), keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(zoneId, Set.of(), keyValueStorage);
 
         topology.putNode(NODE_1);
 
         assertLogicalTopology(Set.of(NODE_1), keyValueStorage);
 
-        assertDataNodesForZone(zoneId, Set.of(NODE_1), keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(zoneId, Set.of(NODE_1), keyValueStorage);
     }
 
     @Test
@@ -299,17 +298,17 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
 
         int zoneId = getZoneId(ZONE_NAME);
 
-        assertDataNodesForZone(zoneId, Set.of(), keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(zoneId, Set.of(), keyValueStorage);
 
         topology.putNode(NODE_1);
 
         assertLogicalTopology(Set.of(NODE_1), keyValueStorage);
 
-        assertDataNodesForZone(zoneId, Set.of(), keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(zoneId, Set.of(), keyValueStorage);
 
         alterZone(ZONE_NAME, IMMEDIATE_TIMER_VALUE, null, null);
 
-        assertDataNodesForZone(zoneId, Set.of(NODE_1), keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(zoneId, Set.of(NODE_1), keyValueStorage);
     }
 
     @Test
@@ -324,15 +323,15 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
 
         int zoneId = getZoneId(ZONE_NAME);
 
-        assertDataNodesForZone(zoneId, Set.of(NODE_1), keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(zoneId, Set.of(NODE_1), keyValueStorage);
 
         topology.removeNodes(Set.of(NODE_1));
 
-        assertDataNodesForZone(zoneId, Set.of(NODE_1), keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(zoneId, Set.of(NODE_1), keyValueStorage);
 
         alterZone(ZONE_NAME, null, IMMEDIATE_TIMER_VALUE, null);
 
-        assertDataNodesForZone(zoneId, Set.of(), keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(zoneId, Set.of(), keyValueStorage);
     }
 
     @Test
@@ -368,7 +367,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleUp(zoneId, 1015);
 
         assertTrue(zoneState.topologyAugmentationMap().isEmpty());
-        assertDataNodesForZoneWithAttributes(zoneId, Set.of(A, B, D, E), keyValueStorage);
+        DistributionZonesTestUtil.assertDataNodesInStorage(zoneId, Set.of(A, B, D, E), keyValueStorage);
     }
 
     @Test
@@ -379,7 +378,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
 
         int zoneId = getZoneId(ZONE_NAME);
 
-        assertDataNodesForZone(zoneId, Set.of(), keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(zoneId, Set.of(), keyValueStorage);
 
         ZoneState zoneState = distributionZoneManager.zonesState().get(zoneId);
 
@@ -408,7 +407,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
 
         int zoneId = getZoneId(ZONE_NAME);
 
-        assertDataNodesForZone(zoneId, Set.of(NODE_1), keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(zoneId, Set.of(NODE_1), keyValueStorage);
 
         ZoneState zoneState = distributionZoneManager.zonesState().get(zoneId);
 
@@ -431,7 +430,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
 
         int zoneId = getZoneId(ZONE_NAME);
 
-        assertDataNodesForZone(zoneId, Set.of(), keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(zoneId, Set.of(), keyValueStorage);
 
         assertTrue(waitForCondition(() -> keyValueStorage.get(zoneScaleUpChangeTriggerKey(zoneId).bytes()).value() != null, 5000));
 
@@ -462,7 +461,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
 
         assertZoneScaleUpChangeTriggerKey(revisionOfScaleUp + 100L, zoneId, keyValueStorage);
 
-        assertDataNodesForZone(zoneId, Set.of(), keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(zoneId, Set.of(), keyValueStorage);
     }
 
     @Test
@@ -475,13 +474,13 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
 
         int defaultZoneId = getZoneId(DEFAULT_ZONE_NAME);
 
-        assertDataNodesForZone(defaultZoneId, Set.of(NODE_1), keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(defaultZoneId, Set.of(NODE_1), keyValueStorage);
 
         createZone(ZONE_NAME, null, IMMEDIATE_TIMER_VALUE, null);
 
         int zoneId = getZoneId(ZONE_NAME);
 
-        assertDataNodesForZone(zoneId, Set.of(NODE_1), keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(zoneId, Set.of(NODE_1), keyValueStorage);
 
         assertTrue(waitForCondition(() -> keyValueStorage.get(zoneScaleDownChangeTriggerKey(zoneId).bytes()).value() != null, 5000));
 
@@ -508,7 +507,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
 
         topology.removeNodes(Set.of(NODE_1));
 
-        assertDataNodesForZone(zoneId, Set.of(NODE_1), keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(zoneId, Set.of(NODE_1), keyValueStorage);
 
         assertZoneScaleDownChangeTriggerKey(revisionOfScaleDown + 100L, zoneId, keyValueStorage);
     }
@@ -527,7 +526,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleUp(zoneId, 1003);
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleDown(zoneId, 1007);
 
-        assertDataNodesForZoneWithAttributes(zoneId, Set.of(A, B, D), keyValueStorage);
+        DistributionZonesTestUtil.assertDataNodesInStorage(zoneId, Set.of(A, B, D), keyValueStorage);
     }
 
     @Test
@@ -544,7 +543,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleDown(zoneId, 1007);
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleUp(zoneId, 1003);
 
-        assertDataNodesForZoneWithAttributes(zoneId, Set.of(A, B, D), keyValueStorage);
+        DistributionZonesTestUtil.assertDataNodesInStorage(zoneId, Set.of(A, B, D), keyValueStorage);
     }
 
     @Test
@@ -561,7 +560,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleDown(zoneId, 1003);
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleUp(zoneId, 1007);
 
-        assertDataNodesForZoneWithAttributes(zoneId, Set.of(A, B, D), keyValueStorage);
+        DistributionZonesTestUtil.assertDataNodesInStorage(zoneId, Set.of(A, B, D), keyValueStorage);
     }
 
     @Test
@@ -578,7 +577,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleUp(zoneId, 1007);
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleDown(zoneId, 1003);
 
-        assertDataNodesForZoneWithAttributes(zoneId, Set.of(A, B, D), keyValueStorage);
+        DistributionZonesTestUtil.assertDataNodesInStorage(zoneId, Set.of(A, B, D), keyValueStorage);
     }
 
     @Test
@@ -593,10 +592,10 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
         zoneState.nodesToRemoveFromDataNodes(Set.of(D), 1007);
 
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleUp(zoneId, 1003);
-        assertDataNodesForZoneWithAttributes(zoneId, Set.of(A, B, C, D), keyValueStorage);
+        DistributionZonesTestUtil.assertDataNodesInStorage(zoneId, Set.of(A, B, C, D), keyValueStorage);
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleDown(zoneId, 1007);
 
-        assertDataNodesForZoneWithAttributes(zoneId, Set.of(A, B, C), keyValueStorage);
+        DistributionZonesTestUtil.assertDataNodesInStorage(zoneId, Set.of(A, B, C), keyValueStorage);
     }
 
     @Test
@@ -613,7 +612,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleDown(zoneId, 1007);
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleUp(zoneId, 1003);
 
-        assertDataNodesForZoneWithAttributes(zoneId, Set.of(A, B, C), keyValueStorage);
+        DistributionZonesTestUtil.assertDataNodesInStorage(zoneId, Set.of(A, B, C), keyValueStorage);
     }
 
     @Test
@@ -630,7 +629,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleDown(zoneId, 1003);
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleUp(zoneId, 1007);
 
-        assertDataNodesForZoneWithAttributes(zoneId, Set.of(A, B, C), keyValueStorage);
+        DistributionZonesTestUtil.assertDataNodesInStorage(zoneId, Set.of(A, B, C), keyValueStorage);
     }
 
     @Test
@@ -647,7 +646,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleUp(zoneId, 1007);
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleDown(zoneId, 1003);
 
-        assertDataNodesForZoneWithAttributes(zoneId, Set.of(A, B, C), keyValueStorage);
+        DistributionZonesTestUtil.assertDataNodesInStorage(zoneId, Set.of(A, B, C), keyValueStorage);
     }
 
     @Test
@@ -665,7 +664,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleUp(zoneId, 1009);
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleDown(zoneId, 1007);
 
-        assertDataNodesForZoneWithAttributes(zoneId, Set.of(A, B, C, D), keyValueStorage);
+        DistributionZonesTestUtil.assertDataNodesInStorage(zoneId, Set.of(A, B, C, D), keyValueStorage);
     }
 
     @Test
@@ -683,7 +682,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleDown(zoneId, 1007);
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleUp(zoneId, 1009);
 
-        assertDataNodesForZoneWithAttributes(zoneId, Set.of(A, B, C, D), keyValueStorage);
+        DistributionZonesTestUtil.assertDataNodesInStorage(zoneId, Set.of(A, B, C, D), keyValueStorage);
     }
 
     @Test
@@ -703,7 +702,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
 
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleUp(zoneId, 1009);
 
-        assertDataNodesForZoneWithAttributes(zoneId, Set.of(A, B, C, D), keyValueStorage);
+        DistributionZonesTestUtil.assertDataNodesInStorage(zoneId, Set.of(A, B, C, D), keyValueStorage);
     }
 
     @Test
@@ -721,7 +720,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleDown(zoneId, 1009);
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleUp(zoneId, 1007);
 
-        assertDataNodesForZoneWithAttributes(zoneId, Set.of(A, B), keyValueStorage);
+        DistributionZonesTestUtil.assertDataNodesInStorage(zoneId, Set.of(A, B), keyValueStorage);
     }
 
     @Test
@@ -739,7 +738,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleUp(zoneId, 1007);
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleDown(zoneId, 1009);
 
-        assertDataNodesForZoneWithAttributes(zoneId, Set.of(A, B), keyValueStorage);
+        DistributionZonesTestUtil.assertDataNodesInStorage(zoneId, Set.of(A, B), keyValueStorage);
     }
 
     @Test
@@ -757,7 +756,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
         zoneState.nodesToRemoveFromDataNodes(Set.of(C), 1009);
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleDown(zoneId, 1009);
 
-        assertDataNodesForZoneWithAttributes(zoneId, Set.of(A, B), keyValueStorage);
+        DistributionZonesTestUtil.assertDataNodesInStorage(zoneId, Set.of(A, B), keyValueStorage);
     }
 
     @Test
@@ -776,7 +775,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
 
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleDown(zoneId, 1007);
 
-        assertDataNodesForZoneWithAttributes(zoneId, Set.of(A, B, C, E), keyValueStorage);
+        DistributionZonesTestUtil.assertDataNodesInStorage(zoneId, Set.of(A, B, C, E), keyValueStorage);
     }
 
     @Test
@@ -794,7 +793,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleDown(zoneId, 1007);
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleUp(zoneId, 1009);
 
-        assertDataNodesForZoneWithAttributes(zoneId, Set.of(A, B, C, E), keyValueStorage);
+        DistributionZonesTestUtil.assertDataNodesInStorage(zoneId, Set.of(A, B, C, E), keyValueStorage);
     }
 
     @Test
@@ -812,7 +811,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
         zoneState.nodesToAddToDataNodes(Set.of(E), 1009);
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleUp(zoneId, 1009);
 
-        assertDataNodesForZoneWithAttributes(zoneId, Set.of(A, B, C, E), keyValueStorage);
+        DistributionZonesTestUtil.assertDataNodesInStorage(zoneId, Set.of(A, B, C, E), keyValueStorage);
     }
 
     @Test
@@ -830,7 +829,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleDown(zoneId, 1009);
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleUp(zoneId, 1007);
 
-        assertDataNodesForZoneWithAttributes(zoneId, Set.of(A, C), keyValueStorage);
+        DistributionZonesTestUtil.assertDataNodesInStorage(zoneId, Set.of(A, C), keyValueStorage);
     }
 
     @Test
@@ -848,7 +847,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleUp(zoneId, 1007);
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleDown(zoneId, 1009);
 
-        assertDataNodesForZoneWithAttributes(zoneId, Set.of(A, C), keyValueStorage);
+        DistributionZonesTestUtil.assertDataNodesInStorage(zoneId, Set.of(A, C), keyValueStorage);
     }
 
     @Test
@@ -866,7 +865,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
         zoneState.nodesToRemoveFromDataNodes(Set.of(B), 1009);
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleDown(zoneId, 1009);
 
-        assertDataNodesForZoneWithAttributes(zoneId, Set.of(A, C), keyValueStorage);
+        DistributionZonesTestUtil.assertDataNodesInStorage(zoneId, Set.of(A, C), keyValueStorage);
     }
 
     @Test
@@ -884,7 +883,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleUp(zoneId, 1009);
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleDown(zoneId, 1007);
 
-        assertDataNodesForZoneWithAttributes(zoneId, Set.of(A, B, C, D), keyValueStorage);
+        DistributionZonesTestUtil.assertDataNodesInStorage(zoneId, Set.of(A, B, C, D), keyValueStorage);
     }
 
     @Test
@@ -902,7 +901,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleDown(zoneId, 1007);
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleUp(zoneId, 1009);
 
-        assertDataNodesForZoneWithAttributes(zoneId, Set.of(A, B, C, D), keyValueStorage);
+        DistributionZonesTestUtil.assertDataNodesInStorage(zoneId, Set.of(A, B, C, D), keyValueStorage);
     }
 
     @Test
@@ -920,7 +919,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
         zoneState.nodesToAddToDataNodes(Set.of(C), 1009);
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleUp(zoneId, 1009);
 
-        assertDataNodesForZoneWithAttributes(zoneId, Set.of(A, B, C, D), keyValueStorage);
+        DistributionZonesTestUtil.assertDataNodesInStorage(zoneId, Set.of(A, B, C, D), keyValueStorage);
     }
 
     @Test
@@ -938,7 +937,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleDown(zoneId, 1009);
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleUp(zoneId, 1007);
 
-        assertDataNodesForZoneWithAttributes(zoneId, Set.of(A, B), keyValueStorage);
+        DistributionZonesTestUtil.assertDataNodesInStorage(zoneId, Set.of(A, B), keyValueStorage);
     }
 
     @Test
@@ -956,7 +955,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleUp(zoneId, 1007);
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleDown(zoneId, 1009);
 
-        assertDataNodesForZoneWithAttributes(zoneId, Set.of(A, B), keyValueStorage);
+        DistributionZonesTestUtil.assertDataNodesInStorage(zoneId, Set.of(A, B), keyValueStorage);
     }
 
     @Test
@@ -974,7 +973,7 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
         zoneState.nodesToRemoveFromDataNodes(Set.of(D), 1009);
         distributionZoneManager.saveDataNodesToMetaStorageOnScaleDown(zoneId, 1009);
 
-        assertDataNodesForZoneWithAttributes(zoneId, Set.of(A, B), keyValueStorage);
+        DistributionZonesTestUtil.assertDataNodesInStorage(zoneId, Set.of(A, B), keyValueStorage);
     }
 
     @Test
@@ -1021,23 +1020,35 @@ public class DistributionZoneManagerScaleUpScaleDownTest extends BaseDistributio
     private void preparePrerequisites(@Nullable String filter) throws Exception {
         startDistributionZoneManager();
 
-        LogicalNode a = new LogicalNode("1", "A", new NetworkAddress("localhost", 123));
+        LogicalNode a = new LogicalNode(A.nodeId(), A.nodeName(), new NetworkAddress("localhost", 123));
 
-        LogicalNode b = new LogicalNode("2", "B", new NetworkAddress("localhost", 123));
+        LogicalNode b = new LogicalNode(B.nodeId(), B.nodeName(), new NetworkAddress("localhost", 123));
 
-        LogicalNode c = new LogicalNode("3", "C", new NetworkAddress("localhost", 123));
+        LogicalNode c = new LogicalNode(C.nodeId(), C.nodeName(), new NetworkAddress("localhost", 123));
+
+        LogicalNode d = new LogicalNode(D.nodeId(), D.nodeName(), new NetworkAddress("localhost", 123));
+
+        LogicalNode e = new LogicalNode(E.nodeId(), E.nodeName(), new NetworkAddress("localhost", 123));
 
         topology.putNode(a);
         topology.putNode(b);
         topology.putNode(c);
 
+        // This is done because we need to have node's D and E attributes in the DistributionZoneManager.nodeAttributes, so won't be
+        // any NPE when we add or remove these nodes manually from manager's state.
+        // (see testVariousScaleUpScaleDownScenarios*)
+        topology.putNode(d);
+        topology.removeNodes(Set.of(d));
+        topology.putNode(e);
+        topology.removeNodes(Set.of(e));
+
         Set<LogicalNode> clusterNodes = Set.of(a, b, c);
 
         createZone(ZONE_NAME, IMMEDIATE_TIMER_VALUE, IMMEDIATE_TIMER_VALUE, filter);
 
         int zoneId = getZoneId(ZONE_NAME);
 
-        assertDataNodesForZone(zoneId, clusterNodes, keyValueStorage);
+        assertDataNodesFromLogicalNodesInStorage(zoneId, clusterNodes, keyValueStorage);
 
         long scaleUpChangeTriggerKey = bytesToLong(
                 keyValueStorage.get(zoneScaleUpChangeTriggerKey(zoneId).bytes()).value()
diff --git a/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerFilterTest.java b/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerStorageProfilesFilterTest.java
similarity index 71%
copy from modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerFilterTest.java
copy to modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerStorageProfilesFilterTest.java
index 8e2be2ccd8..84d63d5356 100644
--- a/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerFilterTest.java
+++ b/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneManagerStorageProfilesFilterTest.java
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.distributionzones;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.IMMEDIATE_TIMER_VALUE;
 import static org.apache.ignite.internal.distributionzones.DistributionZonesTestUtil.assertDataNodesFromManager;
 
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import org.apache.ignite.internal.cluster.management.topology.api.LogicalNode;
@@ -28,27 +29,35 @@ import org.apache.ignite.network.NetworkAddress;
 import org.junit.jupiter.api.Test;
 
 /**
- * Tests distribution zone manager interactions with data nodes filtering.
+ * Tests distribution zone manager interactions with storage profiles filtering.
  */
-public class DistributionZoneManagerFilterTest extends BaseDistributionZoneManagerTest {
+public class DistributionZoneManagerStorageProfilesFilterTest extends BaseDistributionZoneManagerTest {
     private static final LogicalNode A = new LogicalNode(
             new ClusterNodeImpl("1", "A", new NetworkAddress("localhost", 123)),
-            Map.of("region", "US", "storage", "SSD", "dataRegionSize", "10")
+            Map.of(),
+            Map.of(),
+            List.of("clock_rocks", "segmented_aipersist")
     );
 
     private static final LogicalNode B = new LogicalNode(
             new ClusterNodeImpl("2", "B", new NetworkAddress("localhost", 123)),
-            Map.of("region", "EU", "storage", "HHD", "dataRegionSize", "30")
+            Map.of(),
+            Map.of(),
+            List.of("lru_rocks", "clock_rocks", "segmented_aipersist")
     );
 
     private static final LogicalNode C = new LogicalNode(
             new ClusterNodeImpl("3", "C", new NetworkAddress("localhost", 123)),
-            Map.of("region", "CN", "storage", "SSD", "dataRegionSize", "20")
+            Map.of(),
+            Map.of(),
+            List.of("lru_rocks")
     );
 
     private static final LogicalNode D = new LogicalNode(
             new ClusterNodeImpl("4", "D", new NetworkAddress("localhost", 123)),
-            Map.of("region", "CN", "storage", "SSD", "dataRegionSize", "20")
+            Map.of(),
+            Map.of(),
+            List.of("clock_rocks", "segmented_aipersist")
     );
 
     @Test
@@ -58,54 +67,54 @@ public class DistributionZoneManagerFilterTest extends BaseDistributionZoneManag
         topology.putNode(D);
 
         assertDataNodesFromManager(distributionZoneManager, metaStorageManager::appliedRevision, catalogManager::latestCatalogVersion,
-                getZoneId(ZONE_NAME), Set.of(A, C, D), ZONE_MODIFICATION_AWAIT_TIMEOUT);
+                getZoneId(ZONE_NAME), Set.of(A, B, D), ZONE_MODIFICATION_AWAIT_TIMEOUT);
     }
 
     @Test
     void testFilterOnScaleDown() throws Exception {
         preparePrerequisites();
 
-        topology.removeNodes(Set.of(C));
+        topology.removeNodes(Set.of(A));
 
         assertDataNodesFromManager(distributionZoneManager, metaStorageManager::appliedRevision, catalogManager::latestCatalogVersion,
-                getZoneId(ZONE_NAME), Set.of(A), ZONE_MODIFICATION_AWAIT_TIMEOUT);
+                getZoneId(ZONE_NAME), Set.of(B), ZONE_MODIFICATION_AWAIT_TIMEOUT);
     }
 
     @Test
     void testFilterOnScaleUpWithNewAttributesAfterRestart() throws Exception {
         preparePrerequisites();
 
-        topology.removeNodes(Set.of(B));
+        topology.removeNodes(Set.of(C));
 
-        LogicalNode newB = new LogicalNode(
-                new ClusterNodeImpl("2", "newB", new NetworkAddress("localhost", 123)),
-                Map.of("region", "US", "storage", "HHD", "dataRegionSize", "30")
+        LogicalNode newC = new LogicalNode(
+                new ClusterNodeImpl("3", "newC", new NetworkAddress("localhost", 123)),
+                Map.of(),
+                Map.of(),
+                List.of("clock_rocks", "segmented_aipersist")
         );
 
-        topology.putNode(newB);
+        topology.putNode(newC);
 
         assertDataNodesFromManager(distributionZoneManager, metaStorageManager::appliedRevision, catalogManager::latestCatalogVersion,
-                getZoneId(ZONE_NAME), Set.of(A, newB, C), ZONE_MODIFICATION_AWAIT_TIMEOUT);
+                getZoneId(ZONE_NAME), Set.of(A, B, newC), ZONE_MODIFICATION_AWAIT_TIMEOUT);
     }
 
     /**
-     * Starts distribution zone manager with a zone and checks that two out of three nodes, which match filter,
-     * are presented in the zones data nodes.
+     * Starts distribution zone manager with a zone and checks that one out of three nodes, which match filter and storage profile,
+     * is presented in the zones data nodes.
      *
      * @throws Exception If failed
      */
     private void preparePrerequisites() throws Exception {
-        String filter = "$[?(@.storage == 'SSD' || @.region == 'US')]";
-
         startDistributionZoneManager();
 
         topology.putNode(A);
         topology.putNode(B);
         topology.putNode(C);
 
-        createZone(ZONE_NAME, IMMEDIATE_TIMER_VALUE, IMMEDIATE_TIMER_VALUE, filter);
+        createZone(ZONE_NAME, IMMEDIATE_TIMER_VALUE, IMMEDIATE_TIMER_VALUE, null, "clock_rocks,segmented_aipersist");
 
         assertDataNodesFromManager(distributionZoneManager, metaStorageManager::appliedRevision, catalogManager::latestCatalogVersion,
-                getZoneId(ZONE_NAME), Set.of(A, C), ZONE_MODIFICATION_AWAIT_TIMEOUT);
+                getZoneId(ZONE_NAME), Set.of(A, B), ZONE_MODIFICATION_AWAIT_TIMEOUT);
     }
 }
diff --git a/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneStorageProfilesFilterTest.java b/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneStorageProfilesFilterTest.java
new file mode 100644
index 0000000000..0f2246f6fe
--- /dev/null
+++ b/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/DistributionZoneStorageProfilesFilterTest.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.distributionzones;
+
+import static org.apache.ignite.internal.catalog.commands.CatalogUtils.fromParams;
+import static org.apache.ignite.internal.distributionzones.DistributionZonesUtil.filterStorageProfiles;
+import static org.apache.ignite.internal.distributionzones.DistributionZonesUtil.parseStorageProfiles;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.List;
+import java.util.Map;
+import org.junit.jupiter.api.Test;
+
+/** Tests storage profiles filtering. */
+public class DistributionZoneStorageProfilesFilterTest {
+    @Test
+    void testStorageProfilesScenario1() {
+        List<String> nodeStorageProfiles = List.of("qwe", "asd", "zxc");
+        NodeWithAttributes node = new NodeWithAttributes("n", "id", Map.of(), nodeStorageProfiles);
+
+        String zoneStorageProfiles = "qwe,asd";
+
+        assertTrue(filterStorageProfiles(node, fromParams(parseStorageProfiles(zoneStorageProfiles)).profiles()));
+    }
+
+    @Test
+    void testStorageProfilesScenario2() {
+        List<String> nodeStorageProfiles = List.of("asd", "zxc");
+        NodeWithAttributes node = new NodeWithAttributes("n", "id", Map.of(), nodeStorageProfiles);
+
+        String zoneStorageProfiles = "qwe,asd";
+
+        assertFalse(filterStorageProfiles(node, fromParams(parseStorageProfiles(zoneStorageProfiles)).profiles()));
+    }
+
+    @Test
+    void testStorageProfilesScenario3() {
+        List<String> nodeStorageProfiles = List.of("asd", "zxc");
+        NodeWithAttributes node = new NodeWithAttributes("n", "id", Map.of(), nodeStorageProfiles);
+
+        String zoneStorageProfiles = "zxc,asd";
+
+        assertTrue(filterStorageProfiles(node, fromParams(parseStorageProfiles(zoneStorageProfiles)).profiles()));
+    }
+
+    @Test
+    void testStorageProfilesScenario4() {
+        List<String> nodeStorageProfiles = List.of("asd", "zxc");
+        NodeWithAttributes node = new NodeWithAttributes("n", "id", Map.of(), nodeStorageProfiles);
+
+        String zoneStorageProfiles = "zxc,   asd";
+
+        assertTrue(filterStorageProfiles(node, fromParams(parseStorageProfiles(zoneStorageProfiles)).profiles()));
+    }
+}
diff --git a/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/causalitydatanodes/DistributionZoneCausalityDataNodesTest.java b/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/causalitydatanodes/DistributionZoneCausalityDataNodesTest.java
index 4aef7de87e..633673aaff 100644
--- a/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/causalitydatanodes/DistributionZoneCausalityDataNodesTest.java
+++ b/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/causalitydatanodes/DistributionZoneCausalityDataNodesTest.java
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.distributionzones.causalitydatanodes;
 import static java.util.Collections.emptySet;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.stream.Collectors.toSet;
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_ZONE_NAME;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.IMMEDIATE_TIMER_VALUE;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.INFINITE_TIMER_VALUE;
@@ -53,6 +54,7 @@ import static org.mockito.Mockito.doAnswer;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.CompletableFuture;
@@ -80,6 +82,7 @@ import org.apache.ignite.internal.metastorage.WatchEvent;
 import org.apache.ignite.internal.metastorage.WatchListener;
 import org.apache.ignite.internal.metastorage.server.If;
 import org.apache.ignite.internal.metastorage.server.raft.MetaStorageWriteHandler;
+import org.apache.ignite.internal.network.ClusterNodeImpl;
 import org.apache.ignite.internal.util.ByteUtils;
 import org.apache.ignite.network.ClusterNode;
 import org.apache.ignite.network.NetworkAddress;
@@ -102,14 +105,26 @@ public class DistributionZoneCausalityDataNodesTest extends BaseDistributionZone
 
     private static final String ZONE_NAME_4 = "zone4";
 
-    private static final LogicalNode NODE_0 =
-            new LogicalNode("node_id_0", "node_name_0", new NetworkAddress("localhost", 123));
-
-    private static final LogicalNode NODE_1 =
-            new LogicalNode("node_id_1", "node_name_1", new NetworkAddress("localhost", 123));
-
-    private static final LogicalNode NODE_2 =
-            new LogicalNode("node_id_2", "node_name_2", new NetworkAddress("localhost", 123));
+    private static final LogicalNode NODE_0 = new LogicalNode(
+            new ClusterNodeImpl("node_id_0", "node_name_0", new NetworkAddress("localhost", 123)),
+            Map.of(),
+            Map.of(),
+            List.of(DEFAULT_STORAGE_PROFILE)
+    );
+
+    private static final LogicalNode NODE_1 = new LogicalNode(
+            new ClusterNodeImpl("node_id_1", "node_name_1", new NetworkAddress("localhost", 123)),
+            Map.of(),
+            Map.of(),
+            List.of(DEFAULT_STORAGE_PROFILE)
+    );
+
+    private static final LogicalNode NODE_2 = new LogicalNode(
+            new ClusterNodeImpl("node_id_2", "node_name_2", new NetworkAddress("localhost", 123)),
+            Map.of(),
+            Map.of(),
+            List.of(DEFAULT_STORAGE_PROFILE)
+    );
 
     private static final Set<LogicalNode> ONE_NODE = Set.of(NODE_0);
     private static final Set<String> ONE_NODE_NAME = Set.of(NODE_0.name());
diff --git a/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/rebalance/DistributionZoneRebalanceEngineTest.java b/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/rebalance/DistributionZoneRebalanceEngineTest.java
index 0f93112a20..a92a29e567 100644
--- a/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/rebalance/DistributionZoneRebalanceEngineTest.java
+++ b/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/rebalance/DistributionZoneRebalanceEngineTest.java
@@ -23,6 +23,7 @@ import static java.util.concurrent.CompletableFuture.completedFuture;
 import static java.util.stream.Collectors.toSet;
 import static org.apache.ignite.internal.affinity.AffinityUtils.calculateAssignmentForPartition;
 import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_SCHEMA_NAME;
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_ZONE_NAME;
 import static org.apache.ignite.internal.catalog.CatalogTestUtils.createTestCatalogManager;
 import static org.apache.ignite.internal.distributionzones.DistributionZonesTestUtil.getZoneIdStrict;
@@ -73,6 +74,7 @@ import org.apache.ignite.internal.catalog.descriptors.CatalogZoneDescriptor;
 import org.apache.ignite.internal.distributionzones.DistributionZoneManager;
 import org.apache.ignite.internal.distributionzones.DistributionZonesTestUtil;
 import org.apache.ignite.internal.distributionzones.Node;
+import org.apache.ignite.internal.distributionzones.NodeWithAttributes;
 import org.apache.ignite.internal.hlc.HybridClock;
 import org.apache.ignite.internal.hlc.HybridClockImpl;
 import org.apache.ignite.internal.lang.ByteArray;
@@ -146,6 +148,17 @@ public class DistributionZoneRebalanceEngineTest extends IgniteAbstractTest {
         createZone(ZONE_NAME_0, 1, 128);
         createZone(ZONE_NAME_1, 2, 128);
 
+        Map<String, NodeWithAttributes> nodeWithAttributesMap = Map.of(
+                "node0",  new NodeWithAttributes("node0", "node0", Map.of(), List.of(DEFAULT_STORAGE_PROFILE)),
+                "node1",  new NodeWithAttributes("node1", "node1", Map.of(), List.of(DEFAULT_STORAGE_PROFILE)),
+                "node2",  new NodeWithAttributes("node2", "node2", Map.of(), List.of(DEFAULT_STORAGE_PROFILE)),
+                "node3",  new NodeWithAttributes("node3", "node3", Map.of(), List.of(DEFAULT_STORAGE_PROFILE)),
+                "node4",  new NodeWithAttributes("node4", "node4", Map.of(), List.of(DEFAULT_STORAGE_PROFILE)),
+                "node5",  new NodeWithAttributes("node5", "node5", Map.of(), List.of(DEFAULT_STORAGE_PROFILE))
+        );
+
+        when(distributionZoneManager.nodesAttributes()).thenReturn(nodeWithAttributesMap);
+
         doAnswer(invocation -> {
             ByteArray key = invocation.getArgument(0);
 
diff --git a/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/rebalance/RebalanceUtilUpdateAssignmentsTest.java b/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/rebalance/RebalanceUtilUpdateAssignmentsTest.java
index 6089ee9fd4..184f3c6223 100644
--- a/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/rebalance/RebalanceUtilUpdateAssignmentsTest.java
+++ b/modules/distribution-zones/src/test/java/org/apache/ignite/internal/distributionzones/rebalance/RebalanceUtilUpdateAssignmentsTest.java
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.distributionzones.rebalance;
 import static java.util.stream.Collectors.toSet;
 import static org.apache.ignite.internal.affinity.AffinityUtils.calculateAssignmentForPartition;
 import static org.apache.ignite.internal.affinity.Assignments.toBytes;
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
@@ -92,7 +93,8 @@ public class RebalanceUtilUpdateAssignmentsTest extends IgniteAbstractTest {
             0,
             List.of(new CatalogTableColumnDescriptor("k1", ColumnType.INT32, false, 0, 0, 0, null)),
             List.of("k1"),
-            null
+            null,
+            DEFAULT_STORAGE_PROFILE
     );
 
     private static final int partNum = 2;
diff --git a/modules/distribution-zones/src/testFixtures/java/org/apache/ignite/internal/distributionzones/DistributionZonesTestUtil.java b/modules/distribution-zones/src/testFixtures/java/org/apache/ignite/internal/distributionzones/DistributionZonesTestUtil.java
index ca19111afa..519ae87518 100644
--- a/modules/distribution-zones/src/testFixtures/java/org/apache/ignite/internal/distributionzones/DistributionZonesTestUtil.java
+++ b/modules/distribution-zones/src/testFixtures/java/org/apache/ignite/internal/distributionzones/DistributionZonesTestUtil.java
@@ -18,27 +18,23 @@
 package org.apache.ignite.internal.distributionzones;
 
 import static java.util.stream.Collectors.toSet;
-import static org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_FILTER;
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
+import static org.apache.ignite.internal.distributionzones.DistributionZonesUtil.parseStorageProfiles;
 import static org.apache.ignite.internal.distributionzones.DistributionZonesUtil.zoneDataNodesKey;
 import static org.apache.ignite.internal.distributionzones.DistributionZonesUtil.zoneScaleDownChangeTriggerKey;
 import static org.apache.ignite.internal.distributionzones.DistributionZonesUtil.zoneScaleUpChangeTriggerKey;
 import static org.apache.ignite.internal.distributionzones.DistributionZonesUtil.zonesLogicalTopologyKey;
 import static org.apache.ignite.internal.distributionzones.DistributionZonesUtil.zonesLogicalTopologyVersionKey;
-import static org.apache.ignite.internal.distributionzones.DistributionZonesUtil.zonesNodesAttributes;
 import static org.apache.ignite.internal.testframework.IgniteTestUtils.waitForCondition;
 import static org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully;
 import static org.apache.ignite.internal.util.ByteUtils.fromBytes;
-import static org.apache.ignite.internal.util.ByteUtils.longToBytes;
-import static org.apache.ignite.internal.util.ByteUtils.toBytes;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.fail;
 
-import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
@@ -51,7 +47,6 @@ import org.apache.ignite.internal.catalog.commands.AlterZoneCommand;
 import org.apache.ignite.internal.catalog.commands.AlterZoneCommandBuilder;
 import org.apache.ignite.internal.catalog.commands.CreateZoneCommand;
 import org.apache.ignite.internal.catalog.commands.CreateZoneCommandBuilder;
-import org.apache.ignite.internal.catalog.commands.DataStorageParams;
 import org.apache.ignite.internal.catalog.commands.DropZoneCommand;
 import org.apache.ignite.internal.catalog.descriptors.CatalogZoneDescriptor;
 import org.apache.ignite.internal.cluster.management.topology.api.LogicalNode;
@@ -74,16 +69,16 @@ public class DistributionZonesTestUtil {
      * @param zoneName Zone name.
      * @param partitions Zone number of partitions.
      * @param replicas Zone number of replicas.
-     * @param dataStorage Data storage, {@code null} if not set.
+     * @param storageProfile Data storage, {@code null} if not set.
      */
-    public static void createZoneWithDataStorage(
+    public static void createZoneWithStorageProfile(
             CatalogManager catalogManager,
             String zoneName,
             int partitions,
             int replicas,
-            @Nullable String dataStorage
+            @Nullable String storageProfile
     ) {
-        createZone(catalogManager, zoneName, partitions, replicas, null, null, null, dataStorage);
+        createZone(catalogManager, zoneName, partitions, replicas, null, null, null, storageProfile);
     }
 
     /**
@@ -95,7 +90,7 @@ public class DistributionZonesTestUtil {
      * @param replicas Zone number of replicas.
      */
     public static void createZone(CatalogManager catalogManager, String zoneName, int partitions, int replicas) {
-        createZone(catalogManager, zoneName, partitions, replicas, null, null, null, null);
+        createZone(catalogManager, zoneName, partitions, replicas, null, null, null, DEFAULT_STORAGE_PROFILE);
     }
 
     /**
@@ -116,7 +111,48 @@ public class DistributionZonesTestUtil {
             @Nullable Integer dataNodesAutoAdjustScaleDown,
             @Nullable String filter
     ) {
-        createZone(catalogManager, zoneName, null, null, dataNodesAutoAdjustScaleUp, dataNodesAutoAdjustScaleDown, filter, null);
+        createZone(
+                catalogManager,
+                zoneName,
+                null,
+                null,
+                dataNodesAutoAdjustScaleUp,
+                dataNodesAutoAdjustScaleDown,
+                filter,
+                DEFAULT_STORAGE_PROFILE
+        );
+    }
+
+    /**
+     * Creates a distribution zone in the catalog.
+     *
+     * @param catalogManager Catalog manager.
+     * @param zoneName Zone name.
+     * @param dataNodesAutoAdjustScaleUp Timeout in seconds between node added topology event itself and data nodes switch,
+     *         {@code null} if not set.
+     * @param dataNodesAutoAdjustScaleDown Timeout in seconds between node left topology event itself and data nodes switch,
+     *         {@code null} if not set.
+     * @param filter Nodes filter, {@code null} if not set.
+     * @param storageProfiles Storage profiles.
+     */
+    public static void createZone(
+            CatalogManager catalogManager,
+            String zoneName,
+            @Nullable Integer dataNodesAutoAdjustScaleUp,
+            @Nullable Integer dataNodesAutoAdjustScaleDown,
+            @Nullable String filter,
+            String storageProfiles
+    ) {
+        createZone(
+                catalogManager,
+                zoneName,
+                null,
+                null,
+                dataNodesAutoAdjustScaleUp,
+                dataNodesAutoAdjustScaleDown,
+                filter,
+                storageProfiles
+        );
     }
 
     private static void createZone(
@@ -127,7 +163,7 @@ public class DistributionZonesTestUtil {
             @Nullable Integer dataNodesAutoAdjustScaleUp,
             @Nullable Integer dataNodesAutoAdjustScaleDown,
             @Nullable String filter,
-            @Nullable String dataStorage
+            String storageProfiles
     ) {
         CreateZoneCommandBuilder builder = CreateZoneCommand.builder().zoneName(zoneName);
 
@@ -151,22 +187,22 @@ public class DistributionZonesTestUtil {
             builder.filter(filter);
         }
 
-        if (dataStorage != null) {
-            builder.dataStorageParams(DataStorageParams.builder().engine(dataStorage).build());
-        }
+        assertNotNull(storageProfiles);
+
+        builder.storageProfilesParams(parseStorageProfiles(storageProfiles));
 
         assertThat(catalogManager.execute(builder.build()), willCompleteSuccessfully());
     }
 
     /**
-     * Asserts data nodes from {@link DistributionZonesUtil#zoneDataNodesKey(int)}.
+     * Asserts data nodes from {@link DistributionZonesUtil#zoneDataNodesKey(int)} in storage with set of LogicalNodes as input.
      *
      * @param zoneId Zone id.
      * @param clusterNodes Data nodes.
      * @param keyValueStorage Key-value storage.
      * @throws InterruptedException If thread was interrupted.
      */
-    public static void assertDataNodesForZone(
+    public static void assertDataNodesFromLogicalNodesInStorage(
             int zoneId,
             @Nullable Set<LogicalNode> clusterNodes,
             KeyValueStorage keyValueStorage
@@ -185,35 +221,17 @@ public class DistributionZonesTestUtil {
     }
 
     /**
-     * Asserts data nodes from {@link DistributionZonesUtil#zoneDataNodesKey(int)}.
+     * Asserts data nodes from {@link DistributionZonesUtil#zoneDataNodesKey(int)} in storage.
      *
      * @param zoneId Zone id.
      * @param nodes Data nodes.
      * @param keyValueStorage Key-value storage.
      * @throws InterruptedException If thread was interrupted.
      */
-    public static void assertDataNodesForZoneWithAttributes(
+    public static void assertDataNodesInStorage(
             int zoneId,
             @Nullable Set<Node> nodes,
             KeyValueStorage keyValueStorage
-    ) throws InterruptedException {
-        assertDataNodesForZoneWithAttributes(zoneId, nodes, keyValueStorage, DEFAULT_FILTER);
-    }
-
-    /**
-     * Asserts data nodes from {@link DistributionZonesUtil#zoneDataNodesKey(int)} and with provided {@code filter}.
-     *
-     * @param zoneId Zone id.
-     * @param nodes Data nodes.
-     * @param keyValueStorage Key-value storage.
-     * @param filter Filter for data nodes.
-     * @throws InterruptedException If thread was interrupted.
-     */
-    public static void assertDataNodesForZoneWithAttributes(
-            int zoneId,
-            @Nullable Set<Node> nodes,
-            KeyValueStorage keyValueStorage,
-            String filter
     ) throws InterruptedException {
         assertValueInStorage(
                 keyValueStorage,
@@ -305,7 +323,9 @@ public class DistributionZonesTestUtil {
     ) throws InterruptedException {
         Set<NodeWithAttributes> nodes = clusterNodes == null
                 ? null
-                : clusterNodes.stream().map(n -> new NodeWithAttributes(n.name(), n.id(), n.userAttributes())).collect(toSet());
+                : clusterNodes.stream()
+                        .map(n -> new NodeWithAttributes(n.name(), n.id(), n.userAttributes(), n.storageProfiles()))
+                        .collect(toSet());
 
         assertValueInStorage(
                 metaStorageManager,
@@ -333,30 +353,6 @@ public class DistributionZonesTestUtil {
         );
     }
 
-    /**
-     * Sets logical topology to Vault.
-     *
-     * @param nodes Logical topology
-     * @param metaStorageManager Meta storage manager
-     */
-    public static void mockZonesLogicalTopologyAndAttributes(
-            Set<LogicalNode> nodes,
-            MetaStorageManager metaStorageManager
-    ) {
-        Set<NodeWithAttributes> nodesWithAttributes = nodes.stream()
-                .map(n -> new NodeWithAttributes(n.name(), n.id(), n.userAttributes()))
-                .collect(toSet());
-
-        byte[] newLogicalTopology = toBytes(nodesWithAttributes);
-
-        Map<String, Map<String, String>> nodesAttributes = new ConcurrentHashMap<>();
-        nodesWithAttributes.forEach(n -> nodesAttributes.put(n.nodeId(), n.nodeAttributes()));
-        assertThat(metaStorageManager.put(zonesNodesAttributes(), toBytes(nodesAttributes)), willCompleteSuccessfully());
-
-        assertThat(metaStorageManager.put(zonesLogicalTopologyKey(), newLogicalTopology), willCompleteSuccessfully());
-        assertThat(metaStorageManager.put(zonesLogicalTopologyVersionKey(), longToBytes(1L)), willCompleteSuccessfully());
-    }
-
     /**
      * Asserts value from the storage.
      *
diff --git a/modules/index/src/integrationTest/java/org/apache/ignite/internal/index/ItBuildIndexOneNodeTest.java b/modules/index/src/integrationTest/java/org/apache/ignite/internal/index/ItBuildIndexOneNodeTest.java
index bacb210f36..a3160aad0b 100644
--- a/modules/index/src/integrationTest/java/org/apache/ignite/internal/index/ItBuildIndexOneNodeTest.java
+++ b/modules/index/src/integrationTest/java/org/apache/ignite/internal/index/ItBuildIndexOneNodeTest.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.index;
 
 import static java.util.concurrent.CompletableFuture.failedFuture;
 import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_SCHEMA_NAME;
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.lang.IgniteStringFormatter.format;
 import static org.apache.ignite.internal.sql.engine.util.QueryChecker.containsIndexScan;
 import static org.apache.ignite.internal.testframework.IgniteTestUtils.runAsync;
@@ -336,7 +337,7 @@ public class ItBuildIndexOneNodeTest extends BaseSqlIntegrationTest {
     }
 
     private static void createTableAndInsertManyPeople(AtomicInteger nextPersonId) {
-        createZoneOnlyIfNotExists(ZONE_NAME, 1, 1, null);
+        createZoneOnlyIfNotExists(ZONE_NAME, 1, 1, DEFAULT_STORAGE_PROFILE);
         // Use hash index for primary key, otherwise if sorted index exists,
         // the optimizer might choose it (the primary key index) instead of an existing sorted one.
         sql(format(
diff --git a/modules/index/src/integrationTest/java/org/apache/ignite/internal/index/ItBuildIndexTest.java b/modules/index/src/integrationTest/java/org/apache/ignite/internal/index/ItBuildIndexTest.java
index 7a9438a9e1..4b64802172 100644
--- a/modules/index/src/integrationTest/java/org/apache/ignite/internal/index/ItBuildIndexTest.java
+++ b/modules/index/src/integrationTest/java/org/apache/ignite/internal/index/ItBuildIndexTest.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.index;
 
 import static java.util.stream.Collectors.joining;
 import static org.apache.ignite.internal.TestWrappers.unwrapTableViewInternal;
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.catalog.descriptors.CatalogIndexStatus.AVAILABLE;
 import static org.apache.ignite.internal.lang.IgniteStringFormatter.format;
 import static org.apache.ignite.internal.raft.util.OptimizedMarshaller.NO_POOL;
@@ -179,8 +180,8 @@ public class ItBuildIndexTest extends BaseSqlIntegrationTest {
     }
 
     private static void createAndPopulateTable(int replicas, int partitions) {
-        sql(format("CREATE ZONE IF NOT EXISTS {} WITH REPLICAS={}, PARTITIONS={}",
-                ZONE_NAME, replicas, partitions
+        sql(format("CREATE ZONE IF NOT EXISTS {} WITH REPLICAS={}, PARTITIONS={}, STORAGE_PROFILES='{}'",
+                ZONE_NAME, replicas, partitions, DEFAULT_STORAGE_PROFILE
         ));
 
         sql(format(
diff --git a/modules/index/src/integrationTest/java/org/apache/ignite/internal/index/ItIndexNodeFinishedRwTransactionsCheckerTest.java b/modules/index/src/integrationTest/java/org/apache/ignite/internal/index/ItIndexNodeFinishedRwTransactionsCheckerTest.java
index 51f3114d78..d6c9a40d68 100644
--- a/modules/index/src/integrationTest/java/org/apache/ignite/internal/index/ItIndexNodeFinishedRwTransactionsCheckerTest.java
+++ b/modules/index/src/integrationTest/java/org/apache/ignite/internal/index/ItIndexNodeFinishedRwTransactionsCheckerTest.java
@@ -40,7 +40,7 @@ import org.apache.ignite.internal.lang.IgniteSystemProperties;
 import org.apache.ignite.internal.network.NetworkMessage;
 import org.apache.ignite.internal.storage.MvPartitionStorage;
 import org.apache.ignite.internal.storage.engine.MvTableStorage;
-import org.apache.ignite.internal.storage.impl.TestStorageEngine;
+import org.apache.ignite.internal.storage.impl.schema.TestProfileConfigurationSchema;
 import org.apache.ignite.internal.table.InternalTable;
 import org.apache.ignite.internal.table.TableImpl;
 import org.apache.ignite.internal.testframework.IgniteTestUtils;
@@ -72,8 +72,8 @@ public class ItIndexNodeFinishedRwTransactionsCheckerTest extends ClusterPerClas
     @BeforeEach
     void setUp() {
         if (node() != null) {
-            createZoneOnlyIfNotExists(zoneName(TABLE_NAME), 1, 2, TestStorageEngine.ENGINE_NAME);
-            createZoneOnlyIfNotExists(zoneNameForUpdateCatalogVersionOnly, 1, 1, TestStorageEngine.ENGINE_NAME);
+            createZoneOnlyIfNotExists(zoneName(TABLE_NAME), 1, 2, TestProfileConfigurationSchema.TEST_PROFILE_NAME);
+            createZoneOnlyIfNotExists(zoneNameForUpdateCatalogVersionOnly, 1, 1, TestProfileConfigurationSchema.TEST_PROFILE_NAME);
             createTableOnly(TABLE_NAME, zoneName(TABLE_NAME));
         }
     }
diff --git a/modules/index/src/integrationTest/java/org/apache/ignite/internal/index/ItRwTransactionAndIndexesTest.java b/modules/index/src/integrationTest/java/org/apache/ignite/internal/index/ItRwTransactionAndIndexesTest.java
index c196b4fa70..d971dc7552 100644
--- a/modules/index/src/integrationTest/java/org/apache/ignite/internal/index/ItRwTransactionAndIndexesTest.java
+++ b/modules/index/src/integrationTest/java/org/apache/ignite/internal/index/ItRwTransactionAndIndexesTest.java
@@ -18,9 +18,9 @@
 package org.apache.ignite.internal.index;
 
 import static org.apache.ignite.internal.IndexTestUtils.waitForIndexToAppearInAnyState;
+import static org.apache.ignite.internal.TestDefaultProfilesNames.DEFAULT_TEST_PROFILE_NAME;
 import static org.apache.ignite.internal.TestWrappers.unwrapTableImpl;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.pkIndexName;
-import static org.apache.ignite.internal.storage.impl.TestStorageEngine.ENGINE_NAME;
 import static org.apache.ignite.internal.testframework.IgniteTestUtils.runAsync;
 import static org.apache.ignite.internal.testframework.IgniteTestUtils.waitForCondition;
 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
@@ -79,7 +79,7 @@ public class ItRwTransactionAndIndexesTest extends ClusterPerClassIntegrationTes
 
     @Test
     void testDropIndexInsideRwTransaction() {
-        TableImpl table = unwrapTableImpl(createZoneAndTable(ZONE_NAME, TABLE_NAME, 1, 1, ENGINE_NAME));
+        TableImpl table = unwrapTableImpl(createZoneAndTable(ZONE_NAME, TABLE_NAME, 1, 1, DEFAULT_TEST_PROFILE_NAME));
 
         createIndex(TABLE_NAME, INDEX_NAME, COLUMN_NAME);
 
@@ -127,7 +127,7 @@ public class ItRwTransactionAndIndexesTest extends ClusterPerClassIntegrationTes
 
     @Test
     void testCreateIndexInsideRwTransaction() throws Exception {
-        TableImpl table = unwrapTableImpl(createZoneAndTable(ZONE_NAME, TABLE_NAME, 1, 1, ENGINE_NAME));
+        TableImpl table = unwrapTableImpl(createZoneAndTable(ZONE_NAME, TABLE_NAME, 1, 1, DEFAULT_TEST_PROFILE_NAME));
 
         dropAnyBuildIndexMessages();
 
diff --git a/modules/index/src/test/java/org/apache/ignite/internal/index/IndexManagerTest.java b/modules/index/src/test/java/org/apache/ignite/internal/index/IndexManagerTest.java
index 285d0ea72b..80b3815337 100644
--- a/modules/index/src/test/java/org/apache/ignite/internal/index/IndexManagerTest.java
+++ b/modules/index/src/test/java/org/apache/ignite/internal/index/IndexManagerTest.java
@@ -20,9 +20,9 @@ package org.apache.ignite.internal.index;
 import static java.util.concurrent.CompletableFuture.allOf;
 import static java.util.concurrent.CompletableFuture.completedFuture;
 import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_SCHEMA_NAME;
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_ZONE_NAME;
 import static org.apache.ignite.internal.catalog.CatalogTestUtils.createTestCatalogManager;
-import static org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_DATA_REGION;
 import static org.apache.ignite.internal.index.TestIndexManagementUtils.COLUMN_NAME;
 import static org.apache.ignite.internal.index.TestIndexManagementUtils.INDEX_NAME;
 import static org.apache.ignite.internal.index.TestIndexManagementUtils.NODE_NAME;
@@ -177,7 +177,7 @@ public class IndexManagerTest extends BaseIgniteAbstractTest {
 
         assertNotNull(zone);
 
-        StorageTableDescriptor storageTableDescriptor = new StorageTableDescriptor(tableId, zone.partitions(), DEFAULT_DATA_REGION);
+        StorageTableDescriptor storageTableDescriptor = new StorageTableDescriptor(tableId, zone.partitions(), DEFAULT_STORAGE_PROFILE);
 
         MvTableStorage mvTableStorage = mock(MvTableStorage.class);
 
diff --git a/modules/low-watermark/build.gradle b/modules/low-watermark/build.gradle
index 70d84debdc..99dd52976b 100644
--- a/modules/low-watermark/build.gradle
+++ b/modules/low-watermark/build.gradle
@@ -32,11 +32,13 @@ dependencies {
     implementation project(':ignite-vault')
     implementation project(':ignite-configuration-api')
     implementation project(':ignite-replicator')
+    implementation project(':ignite-schema')
     implementation libs.jetbrains.annotations
 
     testImplementation libs.hamcrest.core
     testImplementation libs.mockito.core
     testImplementation libs.mockito.junit
+    testImplementation project(":ignite-schema")
     testImplementation testFixtures(project(":ignite-core"))
     testImplementation testFixtures(project(":ignite-configuration"))
 
diff --git a/modules/low-watermark/src/main/java/org/apache/ignite/internal/lowwatermark/LowWatermarkImpl.java b/modules/low-watermark/src/main/java/org/apache/ignite/internal/lowwatermark/LowWatermarkImpl.java
index bbb959d8eb..e521fedf89 100644
--- a/modules/low-watermark/src/main/java/org/apache/ignite/internal/lowwatermark/LowWatermarkImpl.java
+++ b/modules/low-watermark/src/main/java/org/apache/ignite/internal/lowwatermark/LowWatermarkImpl.java
@@ -46,14 +46,14 @@ import org.apache.ignite.internal.lang.ByteArray;
 import org.apache.ignite.internal.lang.NodeStoppingException;
 import org.apache.ignite.internal.logger.IgniteLogger;
 import org.apache.ignite.internal.logger.Loggers;
-import org.apache.ignite.internal.lowwatermark.configuration.LowWatermarkConfiguration;
-import org.apache.ignite.internal.lowwatermark.configuration.LowWatermarkConfigurationSchema;
 import org.apache.ignite.internal.lowwatermark.message.GetLowWatermarkRequest;
 import org.apache.ignite.internal.lowwatermark.message.LowWatermarkMessageGroup;
 import org.apache.ignite.internal.lowwatermark.message.LowWatermarkMessagesFactory;
 import org.apache.ignite.internal.manager.IgniteComponent;
 import org.apache.ignite.internal.network.MessagingService;
 import org.apache.ignite.internal.network.NetworkMessage;
+import org.apache.ignite.internal.schema.configuration.LowWatermarkConfiguration;
+import org.apache.ignite.internal.schema.configuration.LowWatermarkConfigurationSchema;
 import org.apache.ignite.internal.thread.NamedThreadFactory;
 import org.apache.ignite.internal.util.ByteUtils;
 import org.apache.ignite.internal.util.IgniteSpinBusyLock;
diff --git a/modules/low-watermark/src/test/java/org/apache/ignite/internal/lowwatermark/LowWatermarkImplTest.java b/modules/low-watermark/src/test/java/org/apache/ignite/internal/lowwatermark/LowWatermarkImplTest.java
index 441ffa4bac..4906da89ac 100644
--- a/modules/low-watermark/src/test/java/org/apache/ignite/internal/lowwatermark/LowWatermarkImplTest.java
+++ b/modules/low-watermark/src/test/java/org/apache/ignite/internal/lowwatermark/LowWatermarkImplTest.java
@@ -56,12 +56,12 @@ import org.apache.ignite.internal.hlc.ClockService;
 import org.apache.ignite.internal.hlc.HybridClockImpl;
 import org.apache.ignite.internal.hlc.HybridTimestamp;
 import org.apache.ignite.internal.hlc.TestClockService;
-import org.apache.ignite.internal.lowwatermark.configuration.LowWatermarkConfiguration;
 import org.apache.ignite.internal.lowwatermark.message.GetLowWatermarkRequest;
 import org.apache.ignite.internal.lowwatermark.message.GetLowWatermarkResponse;
 import org.apache.ignite.internal.lowwatermark.message.LowWatermarkMessageGroup;
 import org.apache.ignite.internal.network.MessagingService;
 import org.apache.ignite.internal.network.NetworkMessage;
+import org.apache.ignite.internal.schema.configuration.LowWatermarkConfiguration;
 import org.apache.ignite.internal.testframework.BaseIgniteAbstractTest;
 import org.apache.ignite.internal.util.ByteUtils;
 import org.apache.ignite.internal.vault.VaultEntry;
diff --git a/modules/metastorage/build.gradle b/modules/metastorage/build.gradle
index cc55019e1b..c23d1ba6b1 100644
--- a/modules/metastorage/build.gradle
+++ b/modules/metastorage/build.gradle
@@ -54,6 +54,8 @@ dependencies {
     integrationTestImplementation project(':ignite-rest')
     integrationTestImplementation project(':ignite-raft')
     integrationTestImplementation project(":ignite-raft-api")
+    integrationTestImplementation project(':ignite-storage-api')
+    integrationTestImplementation project(':ignite-storage-rocksdb')
     integrationTestImplementation project(":ignite-vault")
     integrationTestImplementation project(":ignite-security")
     integrationTestImplementation testFixtures(project(':ignite-core'))
diff --git a/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItMetaStorageMultipleNodesAbstractTest.java b/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItMetaStorageMultipleNodesAbstractTest.java
index 09ebfc9a0a..60ee782e60 100644
--- a/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItMetaStorageMultipleNodesAbstractTest.java
+++ b/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItMetaStorageMultipleNodesAbstractTest.java
@@ -48,7 +48,6 @@ import org.apache.ignite.internal.cluster.management.ClusterManagementGroupManag
 import org.apache.ignite.internal.cluster.management.NodeAttributesCollector;
 import org.apache.ignite.internal.cluster.management.configuration.ClusterManagementConfiguration;
 import org.apache.ignite.internal.cluster.management.configuration.NodeAttributesConfiguration;
-import org.apache.ignite.internal.cluster.management.configuration.StorageProfilesConfiguration;
 import org.apache.ignite.internal.cluster.management.raft.ClusterStateStorage;
 import org.apache.ignite.internal.cluster.management.raft.TestClusterStateStorage;
 import org.apache.ignite.internal.cluster.management.topology.LogicalTopologyImpl;
@@ -78,6 +77,7 @@ import org.apache.ignite.internal.raft.Peer;
 import org.apache.ignite.internal.raft.client.TopologyAwareRaftGroupServiceFactory;
 import org.apache.ignite.internal.raft.configuration.RaftConfiguration;
 import org.apache.ignite.internal.raft.service.RaftGroupService;
+import org.apache.ignite.internal.storage.configurations.StorageConfiguration;
 import org.apache.ignite.internal.testframework.IgniteAbstractTest;
 import org.apache.ignite.internal.util.IgniteUtils;
 import org.apache.ignite.internal.vault.VaultManager;
@@ -109,7 +109,7 @@ public abstract class ItMetaStorageMultipleNodesAbstractTest extends IgniteAbstr
     private static NodeAttributesConfiguration nodeAttributes;
 
     @InjectConfiguration
-    private static StorageProfilesConfiguration storageProfilesConfiguration;
+    private static StorageConfiguration storageConfiguration;
 
     /**
      * Large interval to effectively disable idle safe time propagation.
@@ -170,7 +170,7 @@ public abstract class ItMetaStorageMultipleNodesAbstractTest extends IgniteAbstr
                     clusterStateStorage,
                     logicalTopology,
                     cmgConfiguration,
-                    new NodeAttributesCollector(nodeAttributes, storageProfilesConfiguration)
+                    new NodeAttributesCollector(nodeAttributes, storageConfiguration)
             );
 
             var logicalTopologyService = new LogicalTopologyServiceImpl(logicalTopology, cmgManager);
diff --git a/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItMetaStorageWatchTest.java b/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItMetaStorageWatchTest.java
index 130db543ec..9f7335730d 100644
--- a/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItMetaStorageWatchTest.java
+++ b/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItMetaStorageWatchTest.java
@@ -51,7 +51,6 @@ import org.apache.ignite.internal.cluster.management.ClusterManagementGroupManag
 import org.apache.ignite.internal.cluster.management.NodeAttributesCollector;
 import org.apache.ignite.internal.cluster.management.configuration.ClusterManagementConfiguration;
 import org.apache.ignite.internal.cluster.management.configuration.NodeAttributesConfiguration;
-import org.apache.ignite.internal.cluster.management.configuration.StorageProfilesConfiguration;
 import org.apache.ignite.internal.cluster.management.raft.TestClusterStateStorage;
 import org.apache.ignite.internal.cluster.management.topology.LogicalTopologyImpl;
 import org.apache.ignite.internal.cluster.management.topology.LogicalTopologyServiceImpl;
@@ -79,6 +78,7 @@ import org.apache.ignite.internal.network.utils.ClusterServiceTestUtils;
 import org.apache.ignite.internal.raft.Loza;
 import org.apache.ignite.internal.raft.client.TopologyAwareRaftGroupServiceFactory;
 import org.apache.ignite.internal.raft.configuration.RaftConfiguration;
+import org.apache.ignite.internal.storage.configurations.StorageConfiguration;
 import org.apache.ignite.internal.testframework.IgniteAbstractTest;
 import org.apache.ignite.internal.util.IgniteUtils;
 import org.apache.ignite.internal.vault.VaultManager;
@@ -101,7 +101,7 @@ public class ItMetaStorageWatchTest extends IgniteAbstractTest {
     private static NodeAttributesConfiguration nodeAttributes;
 
     @InjectConfiguration
-    private static StorageProfilesConfiguration storageProfilesConfiguration;
+    private static StorageConfiguration storageConfiguration;
 
     @InjectConfiguration
     private static MetaStorageConfiguration metaStorageConfiguration;
@@ -160,7 +160,7 @@ public class ItMetaStorageWatchTest extends IgniteAbstractTest {
                     clusterStateStorage,
                     logicalTopology,
                     cmgConfiguration,
-                    new NodeAttributesCollector(nodeAttributes, storageProfilesConfiguration)
+                    new NodeAttributesCollector(nodeAttributes, storageConfiguration)
             );
 
             components.add(cmgManager);
diff --git a/modules/page-memory/build.gradle b/modules/page-memory/build.gradle
index d7a33d4fc5..63905b9049 100644
--- a/modules/page-memory/build.gradle
+++ b/modules/page-memory/build.gradle
@@ -52,6 +52,7 @@ dependencies {
     testFixturesImplementation libs.mockito.core
     testFixturesImplementation libs.auto.service.annotations
 
+    integrationTestImplementation project(':ignite-storage-api')
     integrationTestImplementation(testFixtures(project))
     integrationTestImplementation(testFixtures(project(':ignite-core')))
     integrationTestImplementation(testFixtures(project(':ignite-configuration')))
diff --git a/modules/page-memory/src/integrationTest/java/org/apache/ignite/internal/pagememory/tree/ItBplusTreeReplaceRemoveRaceTest.java b/modules/page-memory/src/integrationTest/java/org/apache/ignite/internal/pagememory/tree/ItBplusTreeReplaceRemoveRaceTest.java
index e16c1367a0..fffa0d028d 100644
--- a/modules/page-memory/src/integrationTest/java/org/apache/ignite/internal/pagememory/tree/ItBplusTreeReplaceRemoveRaceTest.java
+++ b/modules/page-memory/src/integrationTest/java/org/apache/ignite/internal/pagememory/tree/ItBplusTreeReplaceRemoveRaceTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.pagememory.tree;
 
+import static org.apache.ignite.internal.configuration.ConfigurationTestUtils.fixConfiguration;
 import static org.apache.ignite.internal.pagememory.PageIdAllocator.FLAG_AUX;
 import static org.apache.ignite.internal.pagememory.util.PageIdUtils.partitionId;
 import static org.apache.ignite.internal.pagememory.util.PageUtils.putInt;
@@ -36,7 +37,9 @@ import org.apache.ignite.internal.lang.IgniteInternalCheckedException;
 import org.apache.ignite.internal.pagememory.FullPageId;
 import org.apache.ignite.internal.pagememory.PageMemory;
 import org.apache.ignite.internal.pagememory.TestPageIoRegistry;
-import org.apache.ignite.internal.pagememory.configuration.schema.VolatilePageMemoryDataRegionConfiguration;
+import org.apache.ignite.internal.pagememory.configuration.schema.VolatilePageMemoryProfileChange;
+import org.apache.ignite.internal.pagememory.configuration.schema.VolatilePageMemoryProfileConfiguration;
+import org.apache.ignite.internal.pagememory.configuration.schema.VolatilePageMemoryProfileConfigurationSchema;
 import org.apache.ignite.internal.pagememory.inmemory.VolatilePageMemory;
 import org.apache.ignite.internal.pagememory.io.IoVersions;
 import org.apache.ignite.internal.pagememory.tree.io.BplusInnerIo;
@@ -45,6 +48,7 @@ import org.apache.ignite.internal.pagememory.tree.io.BplusLeafIo;
 import org.apache.ignite.internal.pagememory.tree.io.BplusMetaIo;
 import org.apache.ignite.internal.pagememory.util.PageLockListenerNoOp;
 import org.apache.ignite.internal.pagememory.util.PageUtils;
+import org.apache.ignite.internal.storage.configurations.StorageProfileConfiguration;
 import org.apache.ignite.internal.testframework.BaseIgniteAbstractTest;
 import org.jetbrains.annotations.Nullable;
 import org.junit.jupiter.api.AfterEach;
@@ -65,8 +69,8 @@ public class ItBplusTreeReplaceRemoveRaceTest extends BaseIgniteAbstractTest {
 
     private static final int GROUP_ID = 100500;
 
-    @InjectConfiguration
-    private VolatilePageMemoryDataRegionConfiguration dataRegionCfg;
+    @InjectConfiguration(polymorphicExtensions = { VolatilePageMemoryProfileConfigurationSchema.class }, value = "mock.engine = aimem")
+    private StorageProfileConfiguration dataRegionCfg;
 
     @Nullable
     protected PageMemory pageMem;
@@ -86,14 +90,18 @@ public class ItBplusTreeReplaceRemoveRaceTest extends BaseIgniteAbstractTest {
     }
 
     protected PageMemory createPageMemory() throws Exception {
-        dataRegionCfg.change(c -> c.changeInitSize(1024 * MiB).changeMaxSize(1024 * MiB)).get(1, TimeUnit.SECONDS);
+        dataRegionCfg
+                .change(c -> ((VolatilePageMemoryProfileChange) c)
+                        .changeInitSize(1024 * MiB)
+                        .changeMaxSize(1024 * MiB))
+                .get(1, TimeUnit.SECONDS);
 
         TestPageIoRegistry ioRegistry = new TestPageIoRegistry();
 
         ioRegistry.loadFromServiceLoader();
 
         return new VolatilePageMemory(
-                dataRegionCfg,
+                (VolatilePageMemoryProfileConfiguration) fixConfiguration(dataRegionCfg),
                 ioRegistry,
                 512
         );
diff --git a/modules/page-memory/src/integrationTest/java/org/apache/ignite/internal/pagememory/tree/inmemory/ItBplusTreeReuseListVolatilePageMemoryTest.java b/modules/page-memory/src/integrationTest/java/org/apache/ignite/internal/pagememory/tree/inmemory/ItBplusTreeReuseListVolatilePageMemoryTest.java
index 28e21aff4c..aee5824388 100644
--- a/modules/page-memory/src/integrationTest/java/org/apache/ignite/internal/pagememory/tree/inmemory/ItBplusTreeReuseListVolatilePageMemoryTest.java
+++ b/modules/page-memory/src/integrationTest/java/org/apache/ignite/internal/pagememory/tree/inmemory/ItBplusTreeReuseListVolatilePageMemoryTest.java
@@ -17,14 +17,17 @@
 
 package org.apache.ignite.internal.pagememory.tree.inmemory;
 
-import java.util.concurrent.TimeUnit;
+import static org.apache.ignite.internal.configuration.ConfigurationTestUtils.fixConfiguration;
+
 import org.apache.ignite.internal.configuration.testframework.ConfigurationExtension;
 import org.apache.ignite.internal.configuration.testframework.InjectConfiguration;
 import org.apache.ignite.internal.pagememory.PageMemory;
 import org.apache.ignite.internal.pagememory.TestPageIoRegistry;
-import org.apache.ignite.internal.pagememory.configuration.schema.VolatilePageMemoryDataRegionConfiguration;
+import org.apache.ignite.internal.pagememory.configuration.schema.VolatilePageMemoryProfileConfiguration;
+import org.apache.ignite.internal.pagememory.configuration.schema.VolatilePageMemoryProfileConfigurationSchema;
 import org.apache.ignite.internal.pagememory.inmemory.VolatilePageMemory;
 import org.apache.ignite.internal.pagememory.tree.AbstractBplusTreeReusePageMemoryTest;
+import org.apache.ignite.internal.storage.configurations.StorageProfileConfiguration;
 import org.junit.jupiter.api.extension.ExtendWith;
 
 /**
@@ -32,20 +35,25 @@ import org.junit.jupiter.api.extension.ExtendWith;
  */
 @ExtendWith(ConfigurationExtension.class)
 public class ItBplusTreeReuseListVolatilePageMemoryTest extends AbstractBplusTreeReusePageMemoryTest {
-    @InjectConfiguration
-    private VolatilePageMemoryDataRegionConfiguration dataRegionCfg;
+    @InjectConfiguration(
+            polymorphicExtensions = VolatilePageMemoryProfileConfigurationSchema.class,
+            value = "mock = {"
+                    + "engine=aimem, "
+                    + "initSize=" + MAX_MEMORY_SIZE
+                    + ", maxSize=" + MAX_MEMORY_SIZE
+                    + "}"
+    )
+    private StorageProfileConfiguration storageProfileCfg;
 
     /** {@inheritDoc} */
     @Override
-    protected PageMemory createPageMemory() throws Exception {
-        dataRegionCfg.change(c -> c.changeInitSize(MAX_MEMORY_SIZE).changeMaxSize(MAX_MEMORY_SIZE)).get(1, TimeUnit.SECONDS);
-
+    protected PageMemory createPageMemory() {
         TestPageIoRegistry ioRegistry = new TestPageIoRegistry();
 
         ioRegistry.loadFromServiceLoader();
 
         return new VolatilePageMemory(
-                dataRegionCfg,
+                (VolatilePageMemoryProfileConfiguration) fixConfiguration(storageProfileCfg),
                 ioRegistry,
                 PAGE_SIZE
         );
diff --git a/modules/page-memory/src/integrationTest/java/org/apache/ignite/internal/pagememory/tree/inmemory/ItBplusTreeVolatilePageMemoryTest.java b/modules/page-memory/src/integrationTest/java/org/apache/ignite/internal/pagememory/tree/inmemory/ItBplusTreeVolatilePageMemoryTest.java
index d3c5417b13..2baf21b13f 100644
--- a/modules/page-memory/src/integrationTest/java/org/apache/ignite/internal/pagememory/tree/inmemory/ItBplusTreeVolatilePageMemoryTest.java
+++ b/modules/page-memory/src/integrationTest/java/org/apache/ignite/internal/pagememory/tree/inmemory/ItBplusTreeVolatilePageMemoryTest.java
@@ -17,16 +17,19 @@
 
 package org.apache.ignite.internal.pagememory.tree.inmemory;
 
-import java.util.concurrent.TimeUnit;
+import static org.apache.ignite.internal.configuration.ConfigurationTestUtils.fixConfiguration;
+
 import org.apache.ignite.internal.configuration.testframework.ConfigurationExtension;
 import org.apache.ignite.internal.configuration.testframework.InjectConfiguration;
 import org.apache.ignite.internal.pagememory.PageMemory;
 import org.apache.ignite.internal.pagememory.TestPageIoRegistry;
-import org.apache.ignite.internal.pagememory.configuration.schema.VolatilePageMemoryDataRegionConfiguration;
+import org.apache.ignite.internal.pagememory.configuration.schema.VolatilePageMemoryProfileConfiguration;
+import org.apache.ignite.internal.pagememory.configuration.schema.VolatilePageMemoryProfileConfigurationSchema;
 import org.apache.ignite.internal.pagememory.inmemory.VolatilePageMemory;
 import org.apache.ignite.internal.pagememory.reuse.ReuseList;
 import org.apache.ignite.internal.pagememory.tree.AbstractBplusTreePageMemoryTest;
 import org.apache.ignite.internal.pagememory.tree.BplusTree;
+import org.apache.ignite.internal.storage.configurations.StorageProfileConfiguration;
 import org.jetbrains.annotations.Nullable;
 import org.junit.jupiter.api.extension.ExtendWith;
 
@@ -35,20 +38,25 @@ import org.junit.jupiter.api.extension.ExtendWith;
  */
 @ExtendWith(ConfigurationExtension.class)
 public class ItBplusTreeVolatilePageMemoryTest extends AbstractBplusTreePageMemoryTest {
-    @InjectConfiguration
-    private VolatilePageMemoryDataRegionConfiguration dataRegionCfg;
+    @InjectConfiguration(
+            polymorphicExtensions = VolatilePageMemoryProfileConfigurationSchema.class,
+            value = "mock = {"
+                    + "engine=aimem, "
+                    + "initSize=" + MAX_MEMORY_SIZE
+                    + ", maxSize=" + MAX_MEMORY_SIZE
+                    + "}"
+    )
+    private StorageProfileConfiguration storageProfileConfiguration;
 
     /** {@inheritDoc} */
     @Override
-    protected PageMemory createPageMemory() throws Exception {
-        dataRegionCfg.change(c -> c.changeInitSize(MAX_MEMORY_SIZE).changeMaxSize(MAX_MEMORY_SIZE)).get(1, TimeUnit.SECONDS);
-
+    protected PageMemory createPageMemory() {
         TestPageIoRegistry ioRegistry = new TestPageIoRegistry();
 
         ioRegistry.loadFromServiceLoader();
 
         return new VolatilePageMemory(
-                dataRegionCfg,
+                (VolatilePageMemoryProfileConfiguration) fixConfiguration(storageProfileConfiguration),
                 ioRegistry,
                 PAGE_SIZE
         );
diff --git a/modules/page-memory/src/integrationTest/java/org/apache/ignite/internal/pagememory/tree/persistence/ItBplusTreePersistentPageMemoryTest.java b/modules/page-memory/src/integrationTest/java/org/apache/ignite/internal/pagememory/tree/persistence/ItBplusTreePersistentPageMemoryTest.java
index 22eef6eb26..e62df7cd7b 100644
--- a/modules/page-memory/src/integrationTest/java/org/apache/ignite/internal/pagememory/tree/persistence/ItBplusTreePersistentPageMemoryTest.java
+++ b/modules/page-memory/src/integrationTest/java/org/apache/ignite/internal/pagememory/tree/persistence/ItBplusTreePersistentPageMemoryTest.java
@@ -17,21 +17,23 @@
 
 package org.apache.ignite.internal.pagememory.tree.persistence;
 
+import static org.apache.ignite.internal.configuration.ConfigurationTestUtils.fixConfiguration;
 import static org.apache.ignite.internal.pagememory.persistence.checkpoint.CheckpointTestUtils.mockCheckpointTimeoutLock;
 import static org.apache.ignite.internal.util.Constants.MiB;
 
-import java.util.concurrent.TimeUnit;
 import java.util.stream.LongStream;
 import org.apache.ignite.internal.configuration.testframework.ConfigurationExtension;
 import org.apache.ignite.internal.configuration.testframework.InjectConfiguration;
 import org.apache.ignite.internal.pagememory.PageMemory;
 import org.apache.ignite.internal.pagememory.TestPageIoRegistry;
-import org.apache.ignite.internal.pagememory.configuration.schema.PersistentPageMemoryDataRegionConfiguration;
+import org.apache.ignite.internal.pagememory.configuration.schema.PersistentPageMemoryProfileConfiguration;
+import org.apache.ignite.internal.pagememory.configuration.schema.PersistentPageMemoryProfileConfigurationSchema;
 import org.apache.ignite.internal.pagememory.persistence.PersistentPageMemory;
 import org.apache.ignite.internal.pagememory.persistence.TestPageReadWriteManager;
 import org.apache.ignite.internal.pagememory.reuse.ReuseList;
 import org.apache.ignite.internal.pagememory.tree.AbstractBplusTreePageMemoryTest;
 import org.apache.ignite.internal.pagememory.tree.BplusTree;
+import org.apache.ignite.internal.storage.configurations.StorageProfileConfiguration;
 import org.jetbrains.annotations.Nullable;
 import org.junit.jupiter.api.extension.ExtendWith;
 
@@ -40,20 +42,24 @@ import org.junit.jupiter.api.extension.ExtendWith;
  */
 @ExtendWith(ConfigurationExtension.class)
 public class ItBplusTreePersistentPageMemoryTest extends AbstractBplusTreePageMemoryTest {
-    @InjectConfiguration
-    private PersistentPageMemoryDataRegionConfiguration dataRegionCfg;
+    @InjectConfiguration(
+            polymorphicExtensions = { PersistentPageMemoryProfileConfigurationSchema.class },
+            value = "mock = {"
+            + "engine=aipersist, "
+            + "size=" + MAX_MEMORY_SIZE
+            + "}"
+    )
+    private StorageProfileConfiguration storageProfileCfg;
 
     /** {@inheritDoc} */
     @Override
-    protected PageMemory createPageMemory() throws Exception {
-        dataRegionCfg.change(c -> c.changeSize(MAX_MEMORY_SIZE)).get(1, TimeUnit.SECONDS);
-
+    protected PageMemory createPageMemory() {
         TestPageIoRegistry ioRegistry = new TestPageIoRegistry();
 
         ioRegistry.loadFromServiceLoader();
 
         return new PersistentPageMemory(
-                dataRegionCfg,
+                (PersistentPageMemoryProfileConfiguration) fixConfiguration(storageProfileCfg),
                 ioRegistry,
                 LongStream.range(0, CPUS).map(i -> MAX_MEMORY_SIZE / CPUS).toArray(),
                 10 * MiB,
diff --git a/modules/page-memory/src/integrationTest/java/org/apache/ignite/internal/pagememory/tree/persistence/ItBplusTreeReuseListPersistentPageMemoryTest.java b/modules/page-memory/src/integrationTest/java/org/apache/ignite/internal/pagememory/tree/persistence/ItBplusTreeReuseListPersistentPageMemoryTest.java
index a3161ec3fb..bc0aaf7456 100644
--- a/modules/page-memory/src/integrationTest/java/org/apache/ignite/internal/pagememory/tree/persistence/ItBplusTreeReuseListPersistentPageMemoryTest.java
+++ b/modules/page-memory/src/integrationTest/java/org/apache/ignite/internal/pagememory/tree/persistence/ItBplusTreeReuseListPersistentPageMemoryTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.pagememory.tree.persistence;
 
+import static org.apache.ignite.internal.configuration.ConfigurationTestUtils.fixConfiguration;
 import static org.apache.ignite.internal.pagememory.persistence.checkpoint.CheckpointTestUtils.mockCheckpointTimeoutLock;
 import static org.apache.ignite.internal.util.Constants.MiB;
 
@@ -26,10 +27,13 @@ import org.apache.ignite.internal.configuration.testframework.ConfigurationExten
 import org.apache.ignite.internal.configuration.testframework.InjectConfiguration;
 import org.apache.ignite.internal.pagememory.PageMemory;
 import org.apache.ignite.internal.pagememory.TestPageIoRegistry;
-import org.apache.ignite.internal.pagememory.configuration.schema.PersistentPageMemoryDataRegionConfiguration;
+import org.apache.ignite.internal.pagememory.configuration.schema.PersistentPageMemoryProfileChange;
+import org.apache.ignite.internal.pagememory.configuration.schema.PersistentPageMemoryProfileConfiguration;
+import org.apache.ignite.internal.pagememory.configuration.schema.PersistentPageMemoryProfileConfigurationSchema;
 import org.apache.ignite.internal.pagememory.persistence.PersistentPageMemory;
 import org.apache.ignite.internal.pagememory.persistence.TestPageReadWriteManager;
 import org.apache.ignite.internal.pagememory.tree.AbstractBplusTreeReusePageMemoryTest;
+import org.apache.ignite.internal.storage.configurations.StorageProfileConfiguration;
 import org.junit.jupiter.api.extension.ExtendWith;
 
 /**
@@ -37,20 +41,26 @@ import org.junit.jupiter.api.extension.ExtendWith;
  */
 @ExtendWith(ConfigurationExtension.class)
 public class ItBplusTreeReuseListPersistentPageMemoryTest extends AbstractBplusTreeReusePageMemoryTest {
-    @InjectConfiguration
-    private PersistentPageMemoryDataRegionConfiguration dataRegionCfg;
+    @InjectConfiguration(
+            polymorphicExtensions = PersistentPageMemoryProfileConfigurationSchema.class,
+            value = "mock.engine = aipersist"
+    )
+    private StorageProfileConfiguration dataRegionCfg;
 
     /** {@inheritDoc} */
     @Override
     protected PageMemory createPageMemory() throws Exception {
-        dataRegionCfg.change(c -> c.changeSize(MAX_MEMORY_SIZE)).get(1, TimeUnit.SECONDS);
+        dataRegionCfg
+                .change(c -> ((PersistentPageMemoryProfileChange) c)
+                        .changeSize(MAX_MEMORY_SIZE))
+                .get(1, TimeUnit.SECONDS);
 
         TestPageIoRegistry ioRegistry = new TestPageIoRegistry();
 
         ioRegistry.loadFromServiceLoader();
 
         return new PersistentPageMemory(
-                dataRegionCfg,
+                (PersistentPageMemoryProfileConfiguration) fixConfiguration(dataRegionCfg),
                 ioRegistry,
                 LongStream.range(0, CPUS).map(i -> MAX_MEMORY_SIZE / CPUS).toArray(),
                 10 * MiB,
diff --git a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/configuration/PageMemoryLocalConfigurationModule.java b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/configuration/PageMemoryLocalConfigurationModule.java
index e09d1440de..24ff56bd5e 100644
--- a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/configuration/PageMemoryLocalConfigurationModule.java
+++ b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/configuration/PageMemoryLocalConfigurationModule.java
@@ -22,7 +22,9 @@ import java.util.Collection;
 import java.util.List;
 import org.apache.ignite.configuration.ConfigurationModule;
 import org.apache.ignite.configuration.annotation.ConfigurationType;
+import org.apache.ignite.internal.pagememory.configuration.schema.PersistentPageMemoryProfileConfigurationSchema;
 import org.apache.ignite.internal.pagememory.configuration.schema.UnsafeMemoryAllocatorConfigurationSchema;
+import org.apache.ignite.internal.pagememory.configuration.schema.VolatilePageMemoryProfileConfigurationSchema;
 
 /**
  * {@link ConfigurationModule} for cluster-wide configuration provided by ignite-page-memory.
@@ -38,6 +40,9 @@ public class PageMemoryLocalConfigurationModule implements ConfigurationModule {
     /** {@inheritDoc} */
     @Override
     public Collection<Class<?>> polymorphicSchemaExtensions() {
-        return List.of(UnsafeMemoryAllocatorConfigurationSchema.class);
+        return List.of(
+                PersistentPageMemoryProfileConfigurationSchema.class,
+                VolatilePageMemoryProfileConfigurationSchema.class,
+                UnsafeMemoryAllocatorConfigurationSchema.class);
     }
 }
diff --git a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/configuration/schema/PersistentPageMemoryDataRegionConfigurationSchema.java b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/configuration/schema/PersistentPageMemoryProfileConfigurationSchema.java
similarity index 77%
rename from modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/configuration/schema/PersistentPageMemoryDataRegionConfigurationSchema.java
rename to modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/configuration/schema/PersistentPageMemoryProfileConfigurationSchema.java
index 98be6bc4ca..7186a9b8aa 100644
--- a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/configuration/schema/PersistentPageMemoryDataRegionConfigurationSchema.java
+++ b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/configuration/schema/PersistentPageMemoryProfileConfigurationSchema.java
@@ -20,17 +20,19 @@ package org.apache.ignite.internal.pagememory.configuration.schema;
 import static org.apache.ignite.internal.util.Constants.MiB;
 import static org.apache.ignite.internal.util.IgniteUtils.getTotalMemoryAvailable;
 
-import org.apache.ignite.configuration.annotation.Config;
+import org.apache.ignite.configuration.annotation.ConfigValue;
+import org.apache.ignite.configuration.annotation.PolymorphicConfigInstance;
 import org.apache.ignite.configuration.annotation.Value;
 import org.apache.ignite.configuration.validation.OneOf;
+import org.apache.ignite.internal.storage.configurations.StorageProfileConfigurationSchema;
 
 /**
- * Persistent data region configuration schema.
+ * Persistent storage profile configuration schema.
  */
-@Config
-public class PersistentPageMemoryDataRegionConfigurationSchema extends BasePageMemoryDataRegionConfigurationSchema {
+@PolymorphicConfigInstance("aipersist")
+public class PersistentPageMemoryProfileConfigurationSchema extends StorageProfileConfigurationSchema {
     /**
-     * Default size, maximum between 256 MiB and 20% of the total physical memory.
+     * Default size of page memory data region, maximum between 256 MiB and 20% of the total physical memory.
      * 256 MiB, if system was unable to retrieve physical memory size.
      */
     @SuppressWarnings("NumericCastThatLosesPrecision")
@@ -53,4 +55,7 @@ public class PersistentPageMemoryDataRegionConfigurationSchema extends BasePageM
     @OneOf({RANDOM_LRU_REPLACEMENT_MODE, SEGMENTED_LRU_REPLACEMENT_MODE, CLOCK_REPLACEMENT_MODE})
     @Value(hasDefault = true)
     public String replacementMode = CLOCK_REPLACEMENT_MODE;
+
+    @ConfigValue
+    public MemoryAllocatorConfigurationSchema memoryAllocator;
 }
diff --git a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/configuration/schema/VolatilePageMemoryDataRegionConfigurationSchema.java b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/configuration/schema/VolatilePageMemoryProfileConfigurationSchema.java
similarity index 81%
rename from modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/configuration/schema/VolatilePageMemoryDataRegionConfigurationSchema.java
rename to modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/configuration/schema/VolatilePageMemoryProfileConfigurationSchema.java
index c3d7eda882..52ba3eeef4 100644
--- a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/configuration/schema/VolatilePageMemoryDataRegionConfigurationSchema.java
+++ b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/configuration/schema/VolatilePageMemoryProfileConfigurationSchema.java
@@ -20,17 +20,19 @@ package org.apache.ignite.internal.pagememory.configuration.schema;
 import static org.apache.ignite.internal.util.Constants.MiB;
 import static org.apache.ignite.internal.util.IgniteUtils.getTotalMemoryAvailable;
 
-import org.apache.ignite.configuration.annotation.Config;
+import org.apache.ignite.configuration.annotation.ConfigValue;
+import org.apache.ignite.configuration.annotation.PolymorphicConfigInstance;
 import org.apache.ignite.configuration.annotation.Value;
 import org.apache.ignite.configuration.validation.OneOf;
+import org.apache.ignite.internal.storage.configurations.StorageProfileConfigurationSchema;
 
 /**
- * In-memory data region configuration schema.
+ * In-memory storage profile configuration schema.
  */
-@Config
-public class VolatilePageMemoryDataRegionConfigurationSchema extends BasePageMemoryDataRegionConfigurationSchema {
+@PolymorphicConfigInstance("aimem")
+public class VolatilePageMemoryProfileConfigurationSchema extends StorageProfileConfigurationSchema {
     /**
-     * Default initial size, maximum between 256 MiB and 20% of the total physical memory.
+     * Default initial volatile page memory data region size, maximum between 256 MiB and 20% of the total physical memory.
      * 256 MiB, if system was unable to retrieve physical memory size.
      */
     @SuppressWarnings("NumericCastThatLosesPrecision")
@@ -71,4 +73,8 @@ public class VolatilePageMemoryDataRegionConfigurationSchema extends BasePageMem
     /** Maximum amount of empty pages to keep in memory. */
     @Value(hasDefault = true)
     public int emptyPagesPoolSize = 100;
+
+    /** Memory allocator. */
+    @ConfigValue
+    public MemoryAllocatorConfigurationSchema memoryAllocator;
 }
diff --git a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/inmemory/VolatilePageMemory.java b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/inmemory/VolatilePageMemory.java
index 69f9e88d32..81e90d88c5 100644
--- a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/inmemory/VolatilePageMemory.java
+++ b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/inmemory/VolatilePageMemory.java
@@ -33,8 +33,8 @@ import org.apache.ignite.internal.logger.IgniteLogger;
 import org.apache.ignite.internal.logger.Loggers;
 import org.apache.ignite.internal.pagememory.PageMemory;
 import org.apache.ignite.internal.pagememory.configuration.schema.UnsafeMemoryAllocatorView;
-import org.apache.ignite.internal.pagememory.configuration.schema.VolatilePageMemoryDataRegionConfiguration;
-import org.apache.ignite.internal.pagememory.configuration.schema.VolatilePageMemoryDataRegionView;
+import org.apache.ignite.internal.pagememory.configuration.schema.VolatilePageMemoryProfileConfiguration;
+import org.apache.ignite.internal.pagememory.configuration.schema.VolatilePageMemoryProfileView;
 import org.apache.ignite.internal.pagememory.io.PageIo;
 import org.apache.ignite.internal.pagememory.io.PageIoRegistry;
 import org.apache.ignite.internal.pagememory.mem.DirectMemoryProvider;
@@ -132,7 +132,7 @@ public class VolatilePageMemory implements PageMemory {
     private final DirectMemoryProvider directMemoryProvider;
 
     /** Data region configuration view. */
-    private final VolatilePageMemoryDataRegionView dataRegionConfigView;
+    private final VolatilePageMemoryProfileView storageProfileView;
 
     /** Head of the singly linked list of free pages. */
     private final AtomicLong freePageListHead = new AtomicLong(INVALID_REL_PTR);
@@ -172,22 +172,22 @@ public class VolatilePageMemory implements PageMemory {
     /**
      * Constructor.
      *
-     * @param dataRegionConfig Data region configuration.
+     * @param storageProfileConfiguration Storage profile configuration.
      * @param ioRegistry IO registry.
      * @param pageSize Page size in bytes.
      */
     public VolatilePageMemory(
-            VolatilePageMemoryDataRegionConfiguration dataRegionConfig,
+            VolatilePageMemoryProfileConfiguration storageProfileConfiguration,
             PageIoRegistry ioRegistry,
             // TODO: IGNITE-17017 Move to common config
             int pageSize
     ) {
         this.ioRegistry = ioRegistry;
         this.trackAcquiredPages = false;
-        this.dataRegionConfigView = dataRegionConfig.value();
+        this.storageProfileView = (VolatilePageMemoryProfileView) storageProfileConfiguration.value();
 
-        if (!(dataRegionConfigView.memoryAllocator() instanceof UnsafeMemoryAllocatorView)) {
-            throw new IgniteInternalException("Unexpected memory allocator: " + dataRegionConfigView.memoryAllocator());
+        if (!(storageProfileView.memoryAllocator() instanceof UnsafeMemoryAllocatorView)) {
+            throw new IgniteInternalException("Unexpected memory allocator: " + storageProfileView.memoryAllocator());
         }
 
         directMemoryProvider = new UnsafeMemoryProvider(null);
@@ -196,7 +196,7 @@ public class VolatilePageMemory implements PageMemory {
 
         assert sysPageSize % 8 == 0 : sysPageSize;
 
-        totalPages = (int) (this.dataRegionConfigView.maxSize() / sysPageSize);
+        totalPages = (int) (this.storageProfileView.maxSize() / sysPageSize);
 
         rwLock = new OffheapReadWriteLock(lockConcLvl);
     }
@@ -210,8 +210,8 @@ public class VolatilePageMemory implements PageMemory {
 
             started = true;
 
-            long startSize = dataRegionConfigView.initSize();
-            long maxSize = dataRegionConfigView.maxSize();
+            long startSize = storageProfileView.initSize();
+            long maxSize = storageProfileView.maxSize();
 
             long[] chunks = new long[SEG_CNT];
 
@@ -308,11 +308,11 @@ public class VolatilePageMemory implements PageMemory {
 
         if (relPtr == INVALID_REL_PTR) {
             IgniteOutOfMemoryException oom = new IgniteOutOfMemoryException("Out of memory in data region ["
-                    + "name=" + dataRegionConfigView.name()
-                    + ", initSize=" + IgniteUtils.readableSize(dataRegionConfigView.initSize(), false)
-                    + ", maxSize=" + IgniteUtils.readableSize(dataRegionConfigView.maxSize(), false)
+                    + "name=" + storageProfileView.name()
+                    + ", initSize=" + IgniteUtils.readableSize(storageProfileView.initSize(), false)
+                    + ", maxSize=" + IgniteUtils.readableSize(storageProfileView.maxSize(), false)
                     + ", persistence=false] Try the following:" + lineSeparator()
-                    + "  ^-- Increase maximum off-heap memory size (VolatilePageMemoryDataRegionConfigurationSchema.maxSize)"
+                    + "  ^-- Increase maximum off-heap memory size (VolatilePageMemoryProfileConfigurationSchema.maxSize)"
                     + lineSeparator()
                     + "  ^-- Use persistence" + lineSeparator()
                     + "  ^-- Enable eviction or expiration policies"
@@ -683,7 +683,7 @@ public class VolatilePageMemory implements PageMemory {
             if (oldRef != null) {
                 if (LOG.isInfoEnabled()) {
                     LOG.info("Allocated next memory segment for region [name={}, size={}]",
-                            dataRegionConfigView.name(), IgniteUtils.readableSize(region.size(), true));
+                            storageProfileView.name(), IgniteUtils.readableSize(region.size(), true));
                 }
             }
 
diff --git a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemory.java b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemory.java
index 7f425266c9..0e8af508e9 100644
--- a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemory.java
+++ b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemory.java
@@ -19,9 +19,9 @@ package org.apache.ignite.internal.pagememory.persistence;
 
 import static java.lang.System.lineSeparator;
 import static org.apache.ignite.internal.pagememory.FullPageId.NULL_PAGE;
-import static org.apache.ignite.internal.pagememory.configuration.schema.PersistentPageMemoryDataRegionConfigurationSchema.CLOCK_REPLACEMENT_MODE;
-import static org.apache.ignite.internal.pagememory.configuration.schema.PersistentPageMemoryDataRegionConfigurationSchema.RANDOM_LRU_REPLACEMENT_MODE;
-import static org.apache.ignite.internal.pagememory.configuration.schema.PersistentPageMemoryDataRegionConfigurationSchema.SEGMENTED_LRU_REPLACEMENT_MODE;
+import static org.apache.ignite.internal.pagememory.configuration.schema.PersistentPageMemoryProfileConfigurationSchema.CLOCK_REPLACEMENT_MODE;
+import static org.apache.ignite.internal.pagememory.configuration.schema.PersistentPageMemoryProfileConfigurationSchema.RANDOM_LRU_REPLACEMENT_MODE;
+import static org.apache.ignite.internal.pagememory.configuration.schema.PersistentPageMemoryProfileConfigurationSchema.SEGMENTED_LRU_REPLACEMENT_MODE;
 import static org.apache.ignite.internal.pagememory.io.PageIo.getCrc;
 import static org.apache.ignite.internal.pagememory.io.PageIo.getPageId;
 import static org.apache.ignite.internal.pagememory.io.PageIo.getType;
@@ -82,8 +82,8 @@ import org.apache.ignite.internal.logger.IgniteLogger;
 import org.apache.ignite.internal.logger.Loggers;
 import org.apache.ignite.internal.pagememory.FullPageId;
 import org.apache.ignite.internal.pagememory.PageMemory;
-import org.apache.ignite.internal.pagememory.configuration.schema.PersistentPageMemoryDataRegionConfiguration;
-import org.apache.ignite.internal.pagememory.configuration.schema.PersistentPageMemoryDataRegionView;
+import org.apache.ignite.internal.pagememory.configuration.schema.PersistentPageMemoryProfileConfiguration;
+import org.apache.ignite.internal.pagememory.configuration.schema.PersistentPageMemoryProfileView;
 import org.apache.ignite.internal.pagememory.configuration.schema.UnsafeMemoryAllocatorView;
 import org.apache.ignite.internal.pagememory.io.PageIoRegistry;
 import org.apache.ignite.internal.pagememory.mem.DirectMemoryProvider;
@@ -156,7 +156,7 @@ public class PersistentPageMemory implements PageMemory {
     public static final int TRY_AGAIN_TAG = -1;
 
     /** Data region configuration view. */
-    private final PersistentPageMemoryDataRegionView dataRegionConfigView;
+    private final PersistentPageMemoryProfileView storageProfileView;
 
     /** Page IO registry. */
     private final PageIoRegistry ioRegistry;
@@ -220,7 +220,7 @@ public class PersistentPageMemory implements PageMemory {
     /**
      * Constructor.
      *
-     * @param dataRegionConfig Data region configuration.
+     * @param storageProfileConfiguration Storage profile configuration.
      * @param ioRegistry IO registry.
      * @param segmentSizes Segments sizes in bytes.
      * @param checkpointBufferSize Checkpoint buffer size in bytes.
@@ -231,7 +231,7 @@ public class PersistentPageMemory implements PageMemory {
      * @param pageSize Page size in bytes.
      */
     public PersistentPageMemory(
-            PersistentPageMemoryDataRegionConfiguration dataRegionConfig,
+            PersistentPageMemoryProfileConfiguration storageProfileConfiguration,
             PageIoRegistry ioRegistry,
             long[] segmentSizes,
             long checkpointBufferSize,
@@ -242,15 +242,15 @@ public class PersistentPageMemory implements PageMemory {
             // TODO: IGNITE-17017 Move to common config
             int pageSize
     ) {
-        this.dataRegionConfigView = dataRegionConfig.value();
+        this.storageProfileView = (PersistentPageMemoryProfileView) storageProfileConfiguration.value();
         this.ioRegistry = ioRegistry;
         this.sizes = concat(segmentSizes, checkpointBufferSize);
         this.pageStoreManager = pageStoreManager;
         this.changeTracker = changeTracker;
         this.checkpointTimeoutLock = checkpointTimeoutLock;
 
-        if (!(dataRegionConfigView.memoryAllocator() instanceof UnsafeMemoryAllocatorView)) {
-            throw new IgniteInternalException("Unexpected memory allocator: " + dataRegionConfigView.memoryAllocator());
+        if (!(storageProfileView.memoryAllocator() instanceof UnsafeMemoryAllocatorView)) {
+            throw new IgniteInternalException("Unexpected memory allocator: " + storageProfileView.memoryAllocator());
         }
 
         directMemoryProvider = new UnsafeMemoryProvider(null);
@@ -259,7 +259,7 @@ public class PersistentPageMemory implements PageMemory {
 
         rwLock = new OffheapReadWriteLock(128);
 
-        String replacementMode = dataRegionConfigView.replacementMode();
+        String replacementMode = storageProfileView.replacementMode();
 
         switch (replacementMode) {
             case RANDOM_LRU_REPLACEMENT_MODE:
@@ -567,10 +567,10 @@ public class PersistentPageMemory implements PageMemory {
             seg.loadedPages.put(grpId, effectivePageId(pageId), relPtr, seg.partGeneration(grpId, partId));
         } catch (IgniteOutOfMemoryException oom) {
             IgniteOutOfMemoryException e = new IgniteOutOfMemoryException("Out of memory in data region ["
-                    + "name=" + dataRegionConfigView.name()
-                    + ", size=" + readableSize(dataRegionConfigView.size(), false)
+                    + "name=" + storageProfileView.name()
+                    + ", size=" + readableSize(storageProfileView.size(), false)
                     + ", persistence=true] Try the following:" + lineSeparator()
-                    + "  ^-- Increase maximum off-heap memory size (PersistentPageMemoryDataRegionConfigurationSchema.size)"
+                    + "  ^-- Increase maximum off-heap memory size (PersistentPageMemoryProfileConfigurationSchema.size)"
                     + lineSeparator()
                     + "  ^-- Enable eviction or expiration policies"
             );
@@ -1101,7 +1101,7 @@ public class PersistentPageMemory implements PageMemory {
 
                 throw new IgniteInternalException(
                         "Failed to allocate temporary buffer for checkpoint (increase checkpointPageBufferSize configuration property): "
-                                + dataRegionConfigView.name());
+                                + storageProfileView.name());
             }
 
             // Pin the page until checkpoint is not finished.
@@ -1570,7 +1570,7 @@ public class PersistentPageMemory implements PageMemory {
                 if (pageReplacementWarnedFieldUpdater.compareAndSet(PersistentPageMemory.this, 0, 1)) {
                     LOG.warn("Page replacements started, pages will be rotated with disk, this will affect "
                             + "storage performance (consider increasing PageMemoryDataRegionConfiguration#setMaxSize for "
-                            + "data region) [region={}]", dataRegionConfigView.name());
+                            + "data region) [region={}]", storageProfileView.name());
                 }
             }
 
@@ -1595,10 +1595,10 @@ public class PersistentPageMemory implements PageMemory {
                     + ", dirtyPages=" + dirtyPagesCntr
                     + ", pinned=" + acquiredPages()
                     + ']' + lineSeparator() + "Out of memory in data region ["
-                    + "name=" + dataRegionConfigView.name()
-                    + ", size=" + readableSize(dataRegionConfigView.size(), false)
+                    + "name=" + storageProfileView.name()
+                    + ", size=" + readableSize(storageProfileView.size(), false)
                     + ", persistence=true] Try the following:" + lineSeparator()
-                    + "  ^-- Increase off-heap memory size (PersistentPageMemoryDataRegionConfigurationSchema.size)" + lineSeparator()
+                    + "  ^-- Increase off-heap memory size (PersistentPageMemoryProfileConfigurationSchema.size)" + lineSeparator()
             );
         }
 
diff --git a/modules/page-memory/src/test/java/org/apache/ignite/internal/pagememory/freelist/AbstractFreeListTest.java b/modules/page-memory/src/test/java/org/apache/ignite/internal/pagememory/freelist/AbstractFreeListTest.java
index ad0d97daea..21c71cf0d7 100644
--- a/modules/page-memory/src/test/java/org/apache/ignite/internal/pagememory/freelist/AbstractFreeListTest.java
+++ b/modules/page-memory/src/test/java/org/apache/ignite/internal/pagememory/freelist/AbstractFreeListTest.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.internal.pagememory.freelist;
 
 import static java.util.concurrent.TimeUnit.MINUTES;
+import static org.apache.ignite.internal.configuration.ConfigurationTestUtils.fixConfiguration;
 import static org.apache.ignite.internal.pagememory.PageIdAllocator.FLAG_DATA;
 import static org.apache.ignite.internal.pagememory.util.PageIdUtils.partitionId;
 import static org.apache.ignite.internal.testframework.IgniteTestUtils.runMultiThreadedAsync;
@@ -42,12 +43,15 @@ import org.apache.ignite.internal.configuration.testframework.InjectConfiguratio
 import org.apache.ignite.internal.lang.IgniteInternalCheckedException;
 import org.apache.ignite.internal.pagememory.PageMemory;
 import org.apache.ignite.internal.pagememory.TestPageIoRegistry;
-import org.apache.ignite.internal.pagememory.configuration.schema.VolatilePageMemoryDataRegionConfiguration;
+import org.apache.ignite.internal.pagememory.configuration.schema.VolatilePageMemoryProfileChange;
+import org.apache.ignite.internal.pagememory.configuration.schema.VolatilePageMemoryProfileConfiguration;
+import org.apache.ignite.internal.pagememory.configuration.schema.VolatilePageMemoryProfileConfigurationSchema;
 import org.apache.ignite.internal.pagememory.evict.PageEvictionTrackerNoOp;
 import org.apache.ignite.internal.pagememory.inmemory.VolatilePageMemory;
 import org.apache.ignite.internal.pagememory.metric.IoStatisticsHolder;
 import org.apache.ignite.internal.pagememory.metric.IoStatisticsHolderNoOp;
 import org.apache.ignite.internal.pagememory.util.PageLockListenerNoOp;
+import org.apache.ignite.internal.storage.configurations.StorageProfileConfiguration;
 import org.apache.ignite.internal.testframework.BaseIgniteAbstractTest;
 import org.jetbrains.annotations.Nullable;
 import org.junit.jupiter.api.AfterEach;
@@ -65,8 +69,8 @@ public class AbstractFreeListTest extends BaseIgniteAbstractTest {
 
     private static final int BATCH_SIZE = 100;
 
-    @InjectConfiguration
-    private VolatilePageMemoryDataRegionConfiguration dataRegionCfg;
+    @InjectConfiguration(polymorphicExtensions = VolatilePageMemoryProfileConfigurationSchema.class, value = "mock.engine = aimem")
+    private StorageProfileConfiguration storageProfileCfg;
 
     @Nullable
     private PageMemory pageMemory;
@@ -162,7 +166,11 @@ public class AbstractFreeListTest extends BaseIgniteAbstractTest {
     }
 
     private PageMemory createPageMemory(int pageSize) throws Exception {
-        dataRegionCfg.change(c -> c.changeInitSize(MAX_SIZE).changeMaxSize(MAX_SIZE)).get(1, TimeUnit.SECONDS);
+        storageProfileCfg
+                .change(c -> ((VolatilePageMemoryProfileChange) c)
+                        .changeInitSize(MAX_SIZE)
+                        .changeMaxSize(MAX_SIZE))
+                .get(1, TimeUnit.SECONDS);
 
         TestPageIoRegistry ioRegistry = new TestPageIoRegistry();
 
@@ -171,7 +179,7 @@ public class AbstractFreeListTest extends BaseIgniteAbstractTest {
         ioRegistry.load(TestDataPageIo.VERSIONS);
 
         return new VolatilePageMemory(
-                dataRegionCfg,
+                (VolatilePageMemoryProfileConfiguration) fixConfiguration(storageProfileCfg),
                 ioRegistry,
                 pageSize
         );
diff --git a/modules/page-memory/src/test/java/org/apache/ignite/internal/pagememory/inmemory/VolatilePageMemoryNoLoadSelfTest.java b/modules/page-memory/src/test/java/org/apache/ignite/internal/pagememory/inmemory/VolatilePageMemoryNoLoadSelfTest.java
index 27a93eccfe..341ff6f34c 100644
--- a/modules/page-memory/src/test/java/org/apache/ignite/internal/pagememory/inmemory/VolatilePageMemoryNoLoadSelfTest.java
+++ b/modules/page-memory/src/test/java/org/apache/ignite/internal/pagememory/inmemory/VolatilePageMemoryNoLoadSelfTest.java
@@ -17,14 +17,15 @@
 
 package org.apache.ignite.internal.pagememory.inmemory;
 
-import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.apache.ignite.internal.configuration.ConfigurationTestUtils.fixConfiguration;
 
 import org.apache.ignite.internal.configuration.testframework.ConfigurationExtension;
 import org.apache.ignite.internal.configuration.testframework.InjectConfiguration;
 import org.apache.ignite.internal.pagememory.AbstractPageMemoryNoLoadSelfTest;
-import org.apache.ignite.internal.pagememory.configuration.schema.VolatilePageMemoryDataRegionConfiguration;
+import org.apache.ignite.internal.pagememory.configuration.schema.VolatilePageMemoryProfileConfiguration;
+import org.apache.ignite.internal.pagememory.configuration.schema.VolatilePageMemoryProfileConfigurationSchema;
 import org.apache.ignite.internal.pagememory.io.PageIoRegistry;
-import org.junit.jupiter.api.BeforeEach;
+import org.apache.ignite.internal.storage.configurations.StorageProfileConfiguration;
 import org.junit.jupiter.api.extension.ExtendWith;
 
 /**
@@ -32,13 +33,15 @@ import org.junit.jupiter.api.extension.ExtendWith;
  */
 @ExtendWith(ConfigurationExtension.class)
 public class VolatilePageMemoryNoLoadSelfTest extends AbstractPageMemoryNoLoadSelfTest {
-    @InjectConfiguration
-    private VolatilePageMemoryDataRegionConfiguration dataRegionCfg;
-
-    @BeforeEach
-    void setUp() throws Exception {
-        dataRegionCfg.change(c -> c.changeInitSize(MAX_MEMORY_SIZE).changeMaxSize(MAX_MEMORY_SIZE)).get(1, SECONDS);
-    }
+    @InjectConfiguration(
+            polymorphicExtensions = VolatilePageMemoryProfileConfigurationSchema.class,
+            value = "mock = {"
+            + "engine=aimem, "
+            + "initSize=" + MAX_MEMORY_SIZE
+            + ", maxSize=" + MAX_MEMORY_SIZE
+            + "}"
+    )
+    private StorageProfileConfiguration storageProfileCfg;
 
     /** {@inheritDoc} */
     @Override
@@ -48,7 +51,7 @@ public class VolatilePageMemoryNoLoadSelfTest extends AbstractPageMemoryNoLoadSe
         ioRegistry.loadFromServiceLoader();
 
         return new VolatilePageMemory(
-                dataRegionCfg,
+                (VolatilePageMemoryProfileConfiguration) fixConfiguration(storageProfileCfg),
                 ioRegistry,
                 PAGE_SIZE
         );
diff --git a/modules/page-memory/src/test/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemoryNoLoadTest.java b/modules/page-memory/src/test/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemoryNoLoadTest.java
index af3fbc0ec4..ae75564df0 100644
--- a/modules/page-memory/src/test/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemoryNoLoadTest.java
+++ b/modules/page-memory/src/test/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemoryNoLoadTest.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.internal.pagememory.persistence;
 
 import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.apache.ignite.internal.configuration.ConfigurationTestUtils.fixConfiguration;
 import static org.apache.ignite.internal.pagememory.persistence.CheckpointUrgency.MUST_TRIGGER;
 import static org.apache.ignite.internal.pagememory.persistence.CheckpointUrgency.NOT_REQUIRED;
 import static org.apache.ignite.internal.pagememory.persistence.CheckpointUrgency.SHOULD_TRIGGER;
@@ -61,13 +62,16 @@ import org.apache.ignite.internal.pagememory.DataRegion;
 import org.apache.ignite.internal.pagememory.FullPageId;
 import org.apache.ignite.internal.pagememory.PageMemory;
 import org.apache.ignite.internal.pagememory.configuration.schema.PageMemoryCheckpointConfiguration;
-import org.apache.ignite.internal.pagememory.configuration.schema.PersistentPageMemoryDataRegionConfiguration;
+import org.apache.ignite.internal.pagememory.configuration.schema.PersistentPageMemoryProfileChange;
+import org.apache.ignite.internal.pagememory.configuration.schema.PersistentPageMemoryProfileConfiguration;
+import org.apache.ignite.internal.pagememory.configuration.schema.PersistentPageMemoryProfileConfigurationSchema;
 import org.apache.ignite.internal.pagememory.io.PageIoRegistry;
 import org.apache.ignite.internal.pagememory.persistence.PartitionMeta.PartitionMetaSnapshot;
 import org.apache.ignite.internal.pagememory.persistence.checkpoint.CheckpointManager;
 import org.apache.ignite.internal.pagememory.persistence.checkpoint.CheckpointProgress;
 import org.apache.ignite.internal.pagememory.persistence.store.FilePageStore;
 import org.apache.ignite.internal.pagememory.persistence.store.FilePageStoreManager;
+import org.apache.ignite.internal.storage.configurations.StorageProfileConfiguration;
 import org.apache.ignite.internal.testframework.WorkDirectory;
 import org.apache.ignite.internal.testframework.WorkDirectoryExtension;
 import org.jetbrains.annotations.Nullable;
@@ -84,8 +88,11 @@ import org.junit.jupiter.api.extension.ExtendWith;
 public class PersistentPageMemoryNoLoadTest extends AbstractPageMemoryNoLoadSelfTest {
     private static PageIoRegistry ioRegistry;
 
-    @InjectConfiguration
-    private PersistentPageMemoryDataRegionConfiguration dataRegionCfg;
+    @InjectConfiguration(
+            polymorphicExtensions = PersistentPageMemoryProfileConfigurationSchema.class,
+            value = "mock.engine = aipersist"
+    )
+    private StorageProfileConfiguration dataRegionCfg;
 
     @BeforeAll
     static void beforeAll() {
@@ -96,7 +103,7 @@ public class PersistentPageMemoryNoLoadTest extends AbstractPageMemoryNoLoadSelf
 
     @BeforeEach
     void setUp() throws Exception {
-        dataRegionCfg.change(c -> c.changeSize(MAX_MEMORY_SIZE)).get(1, SECONDS);
+        dataRegionCfg.change(c -> ((PersistentPageMemoryProfileChange) c).changeSize(MAX_MEMORY_SIZE)).get(1, SECONDS);
     }
 
     @AfterAll
@@ -205,7 +212,7 @@ public class PersistentPageMemoryNoLoadTest extends AbstractPageMemoryNoLoadSelf
 
         long systemPageSize = PAGE_SIZE + PAGE_OVERHEAD;
 
-        dataRegionCfg.change(c -> c.changeSize(128 * systemPageSize)).get(1, SECONDS);
+        dataRegionCfg.change(c -> ((PersistentPageMemoryProfileChange) c).changeSize(128 * systemPageSize)).get(1, SECONDS);
 
         PersistentPageMemory pageMemory = createPageMemory(
                 new long[]{100 * systemPageSize},
@@ -444,7 +451,7 @@ public class PersistentPageMemoryNoLoadTest extends AbstractPageMemoryNoLoadSelf
             WriteDirtyPage flushDirtyPageForReplacement
     ) {
         return new PersistentPageMemory(
-                dataRegionCfg,
+                (PersistentPageMemoryProfileConfiguration) fixConfiguration(dataRegionCfg),
                 ioRegistry,
                 segmentSizes,
                 checkpointBufferSize,
diff --git a/modules/placement-driver/src/integrationTest/java/org/apache/ignite/internal/placementdriver/ItPrimaryReplicaChoiceTest.java b/modules/placement-driver/src/integrationTest/java/org/apache/ignite/internal/placementdriver/ItPrimaryReplicaChoiceTest.java
index 36af41713e..ed549094c7 100644
--- a/modules/placement-driver/src/integrationTest/java/org/apache/ignite/internal/placementdriver/ItPrimaryReplicaChoiceTest.java
+++ b/modules/placement-driver/src/integrationTest/java/org/apache/ignite/internal/placementdriver/ItPrimaryReplicaChoiceTest.java
@@ -51,7 +51,7 @@ import org.apache.ignite.internal.replicator.TablePartitionId;
 import org.apache.ignite.internal.schema.BinaryRow;
 import org.apache.ignite.internal.schema.BinaryTuple;
 import org.apache.ignite.internal.storage.impl.TestMvPartitionStorage;
-import org.apache.ignite.internal.storage.impl.TestStorageEngine;
+import org.apache.ignite.internal.storage.impl.schema.TestProfileConfigurationSchema;
 import org.apache.ignite.internal.storage.index.impl.TestHashIndexStorage;
 import org.apache.ignite.internal.storage.index.impl.TestSortedIndexStorage;
 import org.apache.ignite.internal.table.NodeUtils;
@@ -93,8 +93,9 @@ public class ItPrimaryReplicaChoiceTest extends ClusterPerTestIntegrationTest {
     public void setup(TestInfo testInfo) throws Exception {
         super.setup(testInfo);
 
-        String zoneSql = IgniteStringFormatter.format("CREATE ZONE IF NOT EXISTS {} ENGINE {} WITH REPLICAS={}, PARTITIONS={}",
-                ZONE_NAME, TestStorageEngine.ENGINE_NAME, 3, 1
+        String zoneSql = IgniteStringFormatter.format(
+                "CREATE ZONE IF NOT EXISTS {} WITH REPLICAS={}, PARTITIONS={}, STORAGE_PROFILES='{}'",
+                ZONE_NAME, 3, 1, TestProfileConfigurationSchema.TEST_PROFILE_NAME
         );
 
         String sql = IgniteStringFormatter.format(
diff --git a/modules/placement-driver/src/integrationTest/resources/META-INF/services/org.apache.ignite.configuration.ConfigurationModule b/modules/placement-driver/src/integrationTest/resources/META-INF/services/org.apache.ignite.configuration.ConfigurationModule
deleted file mode 100644
index 43a08d979d..0000000000
--- a/modules/placement-driver/src/integrationTest/resources/META-INF/services/org.apache.ignite.configuration.ConfigurationModule
+++ /dev/null
@@ -1 +0,0 @@
-org.apache.ignite.internal.storage.impl.TestPersistStorageConfigurationModule
diff --git a/modules/replicator/src/main/java/org/apache/ignite/internal/replicator/ReplicaManager.java b/modules/replicator/src/main/java/org/apache/ignite/internal/replicator/ReplicaManager.java
index 182e00537b..df2a484dd8 100644
--- a/modules/replicator/src/main/java/org/apache/ignite/internal/replicator/ReplicaManager.java
+++ b/modules/replicator/src/main/java/org/apache/ignite/internal/replicator/ReplicaManager.java
@@ -21,6 +21,7 @@ import static java.util.concurrent.CompletableFuture.completedFuture;
 import static java.util.stream.Collectors.toSet;
 import static org.apache.ignite.internal.replicator.LocalReplicaEvent.AFTER_REPLICA_STARTED;
 import static org.apache.ignite.internal.replicator.LocalReplicaEvent.BEFORE_REPLICA_STOPPED;
+import static org.apache.ignite.internal.replicator.ReplicatorConstants.DEFAULT_IDLE_SAFE_TIME_PROPAGATION_PERIOD_MILLISECONDS;
 import static org.apache.ignite.internal.thread.ThreadOperation.STORAGE_READ;
 import static org.apache.ignite.internal.thread.ThreadOperation.STORAGE_WRITE;
 import static org.apache.ignite.internal.util.CompletableFutures.isCompletedSuccessfully;
@@ -93,9 +94,6 @@ import org.jetbrains.annotations.TestOnly;
  * <p>Only a single instance of the class exists in Ignite node.
  */
 public class ReplicaManager extends AbstractEventProducer<LocalReplicaEvent, LocalReplicaEventParameters> implements IgniteComponent {
-    /** Default Idle safe time propagation period for tests. */
-    public static final int DEFAULT_IDLE_SAFE_TIME_PROPAGATION_PERIOD_MILLISECONDS = 1000;
-
     /** The logger. */
     private static final IgniteLogger LOG = Loggers.forClass(ReplicaManager.class);
 
diff --git a/modules/runner/build.gradle b/modules/runner/build.gradle
index 50d66c83e3..6db1d35296 100644
--- a/modules/runner/build.gradle
+++ b/modules/runner/build.gradle
@@ -130,6 +130,7 @@ dependencies {
     integrationTestImplementation project(':ignite-client')
     integrationTestImplementation project(':ignite-client-handler')
     integrationTestImplementation project(':ignite-storage-api')
+    integrationTestImplementation project(':ignite-storage-api')
     integrationTestImplementation project(':ignite-storage-page-memory')
     integrationTestImplementation project(':ignite-storage-rocksdb')
     integrationTestImplementation project(':ignite-index')
@@ -206,6 +207,7 @@ dependencies {
     testFixturesImplementation testFixtures(project(':ignite-network'))
     testFixturesImplementation testFixtures(project(':ignite-catalog'))
     testFixturesImplementation testFixtures(project(':ignite-table'))
+    testFixturesImplementation testFixtures(project(':ignite-storage-api'))
     testFixturesImplementation libs.jetbrains.annotations
     testFixturesImplementation libs.hamcrest.core
     testFixturesImplementation libs.auto.service.annotations
diff --git a/modules/runner/src/defaultsGenerator/java/org/apache/ignite/internal/configuration/generator/DefaultsGenerator.java b/modules/runner/src/defaultsGenerator/java/org/apache/ignite/internal/configuration/generator/DefaultsGenerator.java
index a5173a29bc..5dfd62dbd8 100644
--- a/modules/runner/src/defaultsGenerator/java/org/apache/ignite/internal/configuration/generator/DefaultsGenerator.java
+++ b/modules/runner/src/defaultsGenerator/java/org/apache/ignite/internal/configuration/generator/DefaultsGenerator.java
@@ -87,7 +87,8 @@ public class DefaultsGenerator {
                 modules.local().polymorphicSchemaExtensions()
         );
 
-        ConfigurationStorage storage = new LocalFileConfigurationStorage("defaultGen", configPath, localConfigurationGenerator);
+        ConfigurationStorage storage = new LocalFileConfigurationStorage(
+                "defaultGen", configPath, localConfigurationGenerator, modules.local());
 
         ConfigurationValidator configurationValidator =
                 ConfigurationValidatorImpl.withDefaultValidators(localConfigurationGenerator, modules.local().validators());
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/benchmark/AbstractMultiNodeBenchmark.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/benchmark/AbstractMultiNodeBenchmark.java
index c7a4f91def..4bdb0282d6 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/benchmark/AbstractMultiNodeBenchmark.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/benchmark/AbstractMultiNodeBenchmark.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.internal.benchmark;
 
 import static java.util.stream.Collectors.toList;
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.sql.engine.util.CursorUtils.getAllFromCursor;
 import static org.apache.ignite.internal.testframework.IgniteTestUtils.await;
 import static org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully;
@@ -81,7 +82,8 @@ public class AbstractMultiNodeBenchmark {
         try {
             var queryEngine = clusterNode.queryEngine();
 
-            var createZoneStatement = "CREATE ZONE IF NOT EXISTS " + ZONE_NAME + " WITH partitions=" + partitionCount();
+            var createZoneStatement = "CREATE ZONE IF NOT EXISTS " + ZONE_NAME + " WITH partitions=" + partitionCount()
+                    + ", storage_profiles ='" + DEFAULT_STORAGE_PROFILE + "'";
 
             getAllFromCursor(
                     await(queryEngine.queryAsync(
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItDistributedConfigurationPropertiesTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItDistributedConfigurationPropertiesTest.java
index a58a241bdd..eb914b7ee8 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItDistributedConfigurationPropertiesTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItDistributedConfigurationPropertiesTest.java
@@ -43,7 +43,6 @@ import org.apache.ignite.internal.cluster.management.ClusterManagementGroupManag
 import org.apache.ignite.internal.cluster.management.NodeAttributesCollector;
 import org.apache.ignite.internal.cluster.management.configuration.ClusterManagementConfiguration;
 import org.apache.ignite.internal.cluster.management.configuration.NodeAttributesConfiguration;
-import org.apache.ignite.internal.cluster.management.configuration.StorageProfilesConfiguration;
 import org.apache.ignite.internal.cluster.management.raft.TestClusterStateStorage;
 import org.apache.ignite.internal.cluster.management.topology.LogicalTopologyImpl;
 import org.apache.ignite.internal.cluster.management.topology.LogicalTopologyServiceImpl;
@@ -65,6 +64,7 @@ import org.apache.ignite.internal.network.utils.ClusterServiceTestUtils;
 import org.apache.ignite.internal.raft.Loza;
 import org.apache.ignite.internal.raft.client.TopologyAwareRaftGroupServiceFactory;
 import org.apache.ignite.internal.raft.configuration.RaftConfiguration;
+import org.apache.ignite.internal.storage.configurations.StorageConfiguration;
 import org.apache.ignite.internal.testframework.BaseIgniteAbstractTest;
 import org.apache.ignite.internal.testframework.WorkDirectory;
 import org.apache.ignite.internal.testframework.WorkDirectoryExtension;
@@ -102,7 +102,7 @@ public class ItDistributedConfigurationPropertiesTest extends BaseIgniteAbstract
     private static NodeAttributesConfiguration nodeAttributes;
 
     @InjectConfiguration
-    private static StorageProfilesConfiguration storageProfilesConfiguration;
+    private static StorageConfiguration storageConfiguration;
 
     @InjectConfiguration
     private static MetaStorageConfiguration metaStorageConfiguration;
@@ -172,7 +172,7 @@ public class ItDistributedConfigurationPropertiesTest extends BaseIgniteAbstract
                     clusterStateStorage,
                     logicalTopology,
                     clusterManagementConfiguration,
-                    new NodeAttributesCollector(nodeAttributes, storageProfilesConfiguration)
+                    new NodeAttributesCollector(nodeAttributes, storageConfiguration)
             );
 
             var logicalTopologyService = new LogicalTopologyServiceImpl(logicalTopology, cmgManager);
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItNodeBootstrapConfigurationTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItNodeBootstrapConfigurationTest.java
index ff1d2f6ade..43945ad100 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItNodeBootstrapConfigurationTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItNodeBootstrapConfigurationTest.java
@@ -77,7 +77,7 @@ public class ItNodeBootstrapConfigurationTest {
 
         assertThrowsWithCause(
                 () -> TestIgnitionManager.start(testNodeName(testInfo, 0), config, workDir),
-                IllegalArgumentException.class,
+                ConfigurationValidationException.class,
                 "'String' is expected as a type for the 'rest.ssl.keyStore.path' configuration value");
     }
 
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItNodeConfigurationFileTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItNodeConfigurationFileTest.java
index 21c2d5f4c7..c70400fe6a 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItNodeConfigurationFileTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItNodeConfigurationFileTest.java
@@ -71,7 +71,7 @@ public class ItNodeConfigurationFileTest {
 
         assertThrowsWithCause(
                 () -> TestIgnitionManager.start(testNodeName(testInfo, 0), config, workDir),
-                IllegalArgumentException.class,
+                ConfigurationValidationException.class,
                 "'String' is expected as a type for the 'rest.ssl.keyStore.path' configuration value");
     }
 
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/storage/ItDistributedConfigurationStorageTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/storage/ItDistributedConfigurationStorageTest.java
index d0de55fb56..91dae76264 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/storage/ItDistributedConfigurationStorageTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/storage/ItDistributedConfigurationStorageTest.java
@@ -36,7 +36,6 @@ import org.apache.ignite.internal.cluster.management.ClusterManagementGroupManag
 import org.apache.ignite.internal.cluster.management.NodeAttributesCollector;
 import org.apache.ignite.internal.cluster.management.configuration.ClusterManagementConfiguration;
 import org.apache.ignite.internal.cluster.management.configuration.NodeAttributesConfiguration;
-import org.apache.ignite.internal.cluster.management.configuration.StorageProfilesConfiguration;
 import org.apache.ignite.internal.cluster.management.raft.TestClusterStateStorage;
 import org.apache.ignite.internal.cluster.management.topology.LogicalTopologyImpl;
 import org.apache.ignite.internal.cluster.management.topology.LogicalTopologyServiceImpl;
@@ -56,6 +55,7 @@ import org.apache.ignite.internal.network.utils.ClusterServiceTestUtils;
 import org.apache.ignite.internal.raft.Loza;
 import org.apache.ignite.internal.raft.client.TopologyAwareRaftGroupServiceFactory;
 import org.apache.ignite.internal.raft.configuration.RaftConfiguration;
+import org.apache.ignite.internal.storage.configurations.StorageConfiguration;
 import org.apache.ignite.internal.testframework.BaseIgniteAbstractTest;
 import org.apache.ignite.internal.testframework.WorkDirectory;
 import org.apache.ignite.internal.testframework.WorkDirectoryExtension;
@@ -83,7 +83,7 @@ public class ItDistributedConfigurationStorageTest extends BaseIgniteAbstractTes
     private static NodeAttributesConfiguration nodeAttributes;
 
     @InjectConfiguration
-    private static StorageProfilesConfiguration storageProfilesConfiguration;
+    private static StorageConfiguration storageConfiguration;
 
     @InjectConfiguration
     private static MetaStorageConfiguration metaStorageConfiguration;
@@ -144,7 +144,7 @@ public class ItDistributedConfigurationStorageTest extends BaseIgniteAbstractTes
                     clusterStateStorage,
                     logicalTopology,
                     clusterManagementConfiguration,
-                    new NodeAttributesCollector(nodeAttributes, storageProfilesConfiguration)
+                    new NodeAttributesCollector(nodeAttributes, storageConfiguration)
             );
 
             var logicalTopologyService = new LogicalTopologyServiceImpl(logicalTopology, cmgManager);
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/inmemory/ItRaftStorageVolatilityTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/inmemory/ItRaftStorageVolatilityTest.java
index 347b55674d..7b0b032db3 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/inmemory/ItRaftStorageVolatilityTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/inmemory/ItRaftStorageVolatilityTest.java
@@ -20,6 +20,8 @@ package org.apache.ignite.internal.inmemory;
 import static ca.seinesoftware.hamcrest.path.PathMatcher.exists;
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static java.util.stream.Collectors.toList;
+import static org.apache.ignite.internal.TestDefaultProfilesNames.DEFAULT_AIMEM_PROFILE_NAME;
+import static org.apache.ignite.internal.TestDefaultProfilesNames.DEFAULT_ROCKSDB_PROFILE_NAME;
 import static org.apache.ignite.internal.TestWrappers.unwrapTableManager;
 import static org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully;
 import static org.hamcrest.MatcherAssert.assertThat;
@@ -75,11 +77,11 @@ class ItRaftStorageVolatilityTest extends ClusterPerTestIntegrationTest {
     }
 
     private void createInMemoryTable() {
-        executeSql("CREATE ZONE ZONE_" + TABLE_NAME + " ENGINE aimem");
+        executeSql("CREATE ZONE ZONE_" + TABLE_NAME + " WITH STORAGE_PROFILES = '" + DEFAULT_AIMEM_PROFILE_NAME + "'");
 
         executeSql("CREATE TABLE " + TABLE_NAME
-                + " (k int, v int, CONSTRAINT PK PRIMARY KEY (k)) WITH PRIMARY_ZONE='ZONE_"
-                + TABLE_NAME.toUpperCase() + "'");
+                + " (k int, v int, CONSTRAINT PK PRIMARY KEY (k)) WITH STORAGE_PROFILE='"
+                + DEFAULT_AIMEM_PROFILE_NAME + "', PRIMARY_ZONE='ZONE_" + TABLE_NAME.toUpperCase() + "'");
     }
 
     /**
@@ -163,11 +165,13 @@ class ItRaftStorageVolatilityTest extends ClusterPerTestIntegrationTest {
     }
 
     private void createPersistentTable() {
-        executeSql("CREATE ZONE ZONE_" + TABLE_NAME + " ENGINE rocksdb");
+        executeSql("CREATE ZONE ZONE_" + TABLE_NAME
+                + " WITH STORAGE_PROFILES = '" + DEFAULT_ROCKSDB_PROFILE_NAME + "'");
 
         executeSql("CREATE TABLE " + TABLE_NAME
-                + " (k int, v int, CONSTRAINT PK PRIMARY KEY (k)) WITH PRIMARY_ZONE='ZONE_"
-                + TABLE_NAME.toUpperCase() + "'");
+                + " (k int, v int, CONSTRAINT PK PRIMARY KEY (k)) "
+                + "WITH STORAGE_PROFILE='" + DEFAULT_ROCKSDB_PROFILE_NAME + "',"
+                + "PRIMARY_ZONE='ZONE_" + TABLE_NAME.toUpperCase() + "'");
     }
 
     @Test
@@ -240,8 +244,14 @@ class ItRaftStorageVolatilityTest extends ClusterPerTestIntegrationTest {
         assertThat(configUpdateFuture, willCompleteSuccessfully());
 
         cluster.doInSession(0, session -> {
-            session.execute(null, "create zone zone1 engine aimem with partitions=1, replicas=1");
-            session.execute(null, "create table " + tableName + " (id int primary key, name varchar) with primary_zone='ZONE1'");
+            session.execute(
+                    null,
+                    "create zone zone1 with partitions=1, replicas=1, "
+                            + "storage_profiles = '" + DEFAULT_AIMEM_PROFILE_NAME + "'"
+            );
+            session.execute(null, "create table " + tableName
+                    + " (id int primary key, name varchar) with storage_profile='"
+                    + DEFAULT_AIMEM_PROFILE_NAME + "', primary_zone='ZONE1'");
         });
     }
 }
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteInMemoryNodeRestartTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteInMemoryNodeRestartTest.java
index ac5fad63ee..ef1597ac15 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteInMemoryNodeRestartTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteInMemoryNodeRestartTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.runner.app;
 
+import static org.apache.ignite.internal.TestDefaultProfilesNames.DEFAULT_AIMEM_PROFILE_NAME;
 import static org.apache.ignite.internal.TestWrappers.unwrapTableViewInternal;
 import static org.apache.ignite.internal.testframework.IgniteTestUtils.testNodeName;
 import static org.apache.ignite.internal.testframework.IgniteTestUtils.waitForCondition;
@@ -336,8 +337,8 @@ public class ItIgniteInMemoryNodeRestartTest extends BaseIgniteRestartTest {
     private static void createTableWithData(Ignite ignite, String name, int replicas, int partitions) throws InterruptedException {
         IgniteSql sql = ignite.sql();
 
-        sql.execute(null, String.format("CREATE ZONE IF NOT EXISTS ZONE_%s ENGINE aimem WITH REPLICAS=%d, PARTITIONS=%d",
-                name, replicas, partitions));
+        sql.execute(null, String.format("CREATE ZONE IF NOT EXISTS ZONE_%s WITH REPLICAS=%d, PARTITIONS=%d, STORAGE_PROFILES='%s'",
+                name, replicas, partitions, DEFAULT_AIMEM_PROFILE_NAME));
         sql.execute(null, "CREATE TABLE " + name
                 + " (id INT PRIMARY KEY, name VARCHAR)"
                 + " WITH PRIMARY_ZONE='ZONE_" + name.toUpperCase() + "';");
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
index d1002c03b9..a55f3a7d25 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
@@ -24,6 +24,7 @@ import static java.util.stream.Collectors.toSet;
 import static org.apache.ignite.internal.TestWrappers.unwrapTableImpl;
 import static org.apache.ignite.internal.TestWrappers.unwrapTableManager;
 import static org.apache.ignite.internal.TestWrappers.unwrapTableViewInternal;
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.distributionzones.DistributionZonesTestUtil.alterZone;
 import static org.apache.ignite.internal.distributionzones.rebalance.RebalanceUtil.REBALANCE_SCHEDULER_POOL_SIZE;
 import static org.apache.ignite.internal.distributionzones.rebalance.RebalanceUtil.STABLE_ASSIGNMENTS_PREFIX;
@@ -99,7 +100,6 @@ import org.apache.ignite.internal.cluster.management.ClusterManagementGroupManag
 import org.apache.ignite.internal.cluster.management.NodeAttributesCollector;
 import org.apache.ignite.internal.cluster.management.configuration.ClusterManagementConfiguration;
 import org.apache.ignite.internal.cluster.management.configuration.NodeAttributesConfiguration;
-import org.apache.ignite.internal.cluster.management.configuration.StorageProfilesConfiguration;
 import org.apache.ignite.internal.cluster.management.raft.RocksDbClusterStateStorage;
 import org.apache.ignite.internal.cluster.management.topology.LogicalTopologyImpl;
 import org.apache.ignite.internal.cluster.management.topology.LogicalTopologyServiceImpl;
@@ -170,6 +170,7 @@ import org.apache.ignite.internal.sql.engine.SqlQueryProcessor;
 import org.apache.ignite.internal.storage.DataStorageManager;
 import org.apache.ignite.internal.storage.DataStorageModule;
 import org.apache.ignite.internal.storage.DataStorageModules;
+import org.apache.ignite.internal.storage.configurations.StorageConfiguration;
 import org.apache.ignite.internal.systemview.SystemViewManagerImpl;
 import org.apache.ignite.internal.table.TableImpl;
 import org.apache.ignite.internal.table.TableViewInternal;
@@ -245,7 +246,7 @@ public class ItIgniteNodeRestartTest extends BaseIgniteRestartTest {
     private static NodeAttributesConfiguration nodeAttributes;
 
     @InjectConfiguration
-    private static StorageProfilesConfiguration storageProfilesConfiguration;
+    private static StorageConfiguration storageConfiguration;
 
     @InjectConfiguration
     private static MetaStorageConfiguration metaStorageConfiguration;
@@ -316,7 +317,7 @@ public class ItIgniteNodeRestartTest extends BaseIgniteRestartTest {
 
         var nodeCfgMgr = new ConfigurationManager(
                 modules.local().rootKeys(),
-                new LocalFileConfigurationStorage(configFile, localConfigurationGenerator),
+                new LocalFileConfigurationStorage(configFile, localConfigurationGenerator, modules.local()),
                 localConfigurationGenerator,
                 ConfigurationValidatorImpl.withDefaultValidators(localConfigurationGenerator, modules.local().validators())
         );
@@ -371,7 +372,8 @@ public class ItIgniteNodeRestartTest extends BaseIgniteRestartTest {
                 clusterStateStorage,
                 logicalTopology,
                 clusterManagementConfiguration,
-                new NodeAttributesCollector(nodeAttributes, storageProfilesConfiguration)
+                new NodeAttributesCollector(nodeAttributes,
+                        nodeCfgMgr.configurationRegistry().getConfiguration(StorageConfiguration.KEY))
         );
 
         LongSupplier partitionIdleSafeTimePropagationPeriodMsSupplier
@@ -524,7 +526,9 @@ public class ItIgniteNodeRestartTest extends BaseIgniteRestartTest {
 
         Consumer<LongFunction<CompletableFuture<?>>> registry = (c) -> metaStorageMgr.registerRevisionUpdateListener(c::apply);
 
-        DataStorageModules dataStorageModules = new DataStorageModules(ServiceLoader.load(DataStorageModule.class));
+        DataStorageModules dataStorageModules = new DataStorageModules(
+                ServiceLoader.load(DataStorageModule.class)
+        );
 
         Path storagePath = getPartitionsStorePath(dir);
 
@@ -536,7 +540,8 @@ public class ItIgniteNodeRestartTest extends BaseIgniteRestartTest {
                         null,
                         failureProcessor,
                         raftMgr.getLogSyncer()
-                )
+                ),
+                nodeCfgMgr.configurationRegistry().getConfiguration(StorageConfiguration.KEY)
         );
 
         TransactionConfiguration txConfiguration = clusterConfigRegistry.getConfiguration(TransactionConfiguration.KEY);
@@ -634,7 +639,6 @@ public class ItIgniteNodeRestartTest extends BaseIgniteRestartTest {
                 tableManager,
                 schemaManager,
                 dataStorageManager,
-                () -> dataStorageModules.collectSchemasFields(modules.local().polymorphicSchemaExtensions()),
                 replicaService,
                 clockService,
                 schemaSyncService,
@@ -1519,7 +1523,8 @@ public class ItIgniteNodeRestartTest extends BaseIgniteRestartTest {
 
         IgniteSql sql = node.sql();
 
-        sql.execute(null, String.format("CREATE ZONE IF NOT EXISTS %s WITH REPLICAS=%d, PARTITIONS=%d", zoneName, nodesCount, 1));
+        sql.execute(null, String.format("CREATE ZONE IF NOT EXISTS %s WITH REPLICAS=%d, PARTITIONS=%d, STORAGE_PROFILES='%s'",
+                zoneName, nodesCount, 1, DEFAULT_STORAGE_PROFILE));
 
         sql.execute(null, "CREATE TABLE " + TABLE_NAME
                 + "(id INT PRIMARY KEY, name VARCHAR) WITH PRIMARY_ZONE='" + zoneName + "';");
@@ -1629,7 +1634,8 @@ public class ItIgniteNodeRestartTest extends BaseIgniteRestartTest {
         // Create table, all nodes are lagging.
         IgniteSql sql = node0.sql();
 
-        sql.execute(null, String.format("CREATE ZONE IF NOT EXISTS %s WITH REPLICAS=%d, PARTITIONS=%d", zoneName, 2, 1));
+        sql.execute(null, String.format("CREATE ZONE IF NOT EXISTS %s WITH REPLICAS=%d, PARTITIONS=%d, STORAGE_PROFILES='%s'",
+                zoneName, 2, 1, DEFAULT_STORAGE_PROFILE));
 
         nodeInhibitor0.startInhibit();
         nodeInhibitor1.startInhibit();
@@ -1695,7 +1701,9 @@ public class ItIgniteNodeRestartTest extends BaseIgniteRestartTest {
         String tableName = "TEST";
         String zoneName = "ZONE_TEST";
 
-        node0.sql().execute(null, String.format("CREATE ZONE IF NOT EXISTS %s WITH REPLICAS=%d, PARTITIONS=%d", zoneName, 2, 1));
+        node0.sql().execute(null,
+                String.format("CREATE ZONE IF NOT EXISTS %s WITH REPLICAS=%d, PARTITIONS=%d, STORAGE_PROFILES='%s'",
+                        zoneName, 2, 1, DEFAULT_STORAGE_PROFILE));
 
         int catalogVersionBeforeTable = node0.catalogManager().latestCatalogVersion();
 
@@ -1888,7 +1896,8 @@ public class ItIgniteNodeRestartTest extends BaseIgniteRestartTest {
         IgniteSql sql = nodes.get(0).sql();
 
         sql.execute(null,
-                String.format("CREATE ZONE IF NOT EXISTS ZONE_%s WITH REPLICAS=%d, PARTITIONS=%d", name, replicas, partitions));
+                String.format("CREATE ZONE IF NOT EXISTS ZONE_%s WITH REPLICAS=%d, PARTITIONS=%d, STORAGE_PROFILES='%s'",
+                        name, replicas, partitions, DEFAULT_STORAGE_PROFILE));
         sql.execute(null, "CREATE TABLE IF NOT EXISTS " + name
                 + "(id INT PRIMARY KEY, name VARCHAR) WITH PRIMARY_ZONE='ZONE_" + name.toUpperCase() + "';");
 
@@ -1933,7 +1942,8 @@ public class ItIgniteNodeRestartTest extends BaseIgniteRestartTest {
         IgniteSql sql = ignite.sql();
 
         sql.execute(null,
-                String.format("CREATE ZONE IF NOT EXISTS ZONE_%s WITH REPLICAS=%d, PARTITIONS=%d", name, replicas, partitions));
+                String.format("CREATE ZONE IF NOT EXISTS ZONE_%s WITH REPLICAS=%d, PARTITIONS=%d, STORAGE_PROFILES='%s'",
+                        name, replicas, partitions, DEFAULT_STORAGE_PROFILE));
         sql.execute(null, "CREATE TABLE " + name
                 + "(id INT PRIMARY KEY, name VARCHAR) WITH PRIMARY_ZONE='ZONE_" + name.toUpperCase() + "';");
 
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/client/ItAbstractThinClientTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/client/ItAbstractThinClientTest.java
index 17505355dd..172fdba34d 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/client/ItAbstractThinClientTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/client/ItAbstractThinClientTest.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.internal.runner.app.client;
 
 import static java.util.stream.Collectors.toList;
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.testframework.IgniteTestUtils.testNodeName;
 import static org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully;
 import static org.hamcrest.MatcherAssert.assertThat;
@@ -119,7 +120,8 @@ public abstract class ItAbstractThinClientTest extends BaseIgniteAbstractTest {
 
         IgniteSql sql = startedNodes.get(0).sql();
 
-        sql.execute(null, "CREATE ZONE TEST_ZONE WITH REPLICAS=1, PARTITIONS=10");
+        sql.execute(null,  "CREATE ZONE TEST_ZONE WITH REPLICAS=1, PARTITIONS=10, STORAGE_PROFILES='"
+                + DEFAULT_STORAGE_PROFILE + "'");
         sql.execute(null, "CREATE TABLE " + TABLE_NAME + "("
                 + COLUMN_KEY + " INT PRIMARY KEY, " + COLUMN_VAL + " VARCHAR) WITH PRIMARY_ZONE='TEST_ZONE'");
 
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/schemasync/ItSchemaSyncAndReplicationTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/schemasync/ItSchemaSyncAndReplicationTest.java
index 4a048231db..622dbe6be9 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/schemasync/ItSchemaSyncAndReplicationTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/schemasync/ItSchemaSyncAndReplicationTest.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.schemasync;
 
 import static org.apache.ignite.internal.SessionUtils.executeUpdate;
 import static org.apache.ignite.internal.TestWrappers.unwrapTableManager;
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.testframework.IgniteTestUtils.waitForCondition;
 import static org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willSucceedIn;
 import static org.hamcrest.MatcherAssert.assertThat;
@@ -103,7 +104,7 @@ class ItSchemaSyncAndReplicationTest extends ClusterPerTestIntegrationTest {
     }
 
     private void createTestTableWith3Replicas() {
-        String zoneSql = "create zone test_zone with partitions=1, replicas=3";
+        String zoneSql = "create zone test_zone with partitions=1, replicas=3, storage_profiles='" + DEFAULT_STORAGE_PROFILE + "'";
         String sql = "create table " + TABLE_NAME + " (key int primary key, val varchar(20))"
                 + " with primary_zone='TEST_ZONE'";
 
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/schemasync/ItSchemaSyncMultiNodeTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/schemasync/ItSchemaSyncMultiNodeTest.java
index 952786586b..79438e9e51 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/schemasync/ItSchemaSyncMultiNodeTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/schemasync/ItSchemaSyncMultiNodeTest.java
@@ -185,7 +185,7 @@ class ItSchemaSyncMultiNodeTest extends ClusterPerTestIntegrationTest {
 
         try {
             cluster.doInSession(NODE_0_INDEX, session -> {
-                executeUpdate("CREATE ZONE test_zone", session);
+                executeUpdate("CREATE ZONE test_zone WITH STORAGE_PROFILES='default'", session);
             });
 
             CompletableFuture<Void> tableCreationFuture = runAsync(() -> cluster.doInSession(NODE_1_INDEX, session -> {
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/table/ItDurableFinishTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/table/ItDurableFinishTest.java
index 119a1ab3d1..7bf8b4c886 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/table/ItDurableFinishTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/table/ItDurableFinishTest.java
@@ -21,6 +21,7 @@ import static java.util.concurrent.TimeUnit.SECONDS;
 import static java.util.stream.Collectors.toSet;
 import static org.apache.ignite.internal.SessionUtils.executeUpdate;
 import static org.apache.ignite.internal.TestWrappers.unwrapTableViewInternal;
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.testframework.IgniteTestUtils.bypassingThreadAssertions;
 import static org.apache.ignite.internal.testframework.IgniteTestUtils.waitForCondition;
 import static org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully;
@@ -75,7 +76,7 @@ public class ItDurableFinishTest extends ClusterPerTestIntegrationTest {
     private final Collection<CompletableFuture<?>> futures = new ArrayList<>();
 
     private void createTestTableWith3Replicas() {
-        String zoneSql = "create zone test_zone with partitions=1, replicas=3";
+        String zoneSql = "create zone test_zone with partitions=1, replicas=3, storage_profiles='" + DEFAULT_STORAGE_PROFILE + "'";
         String sql = "create table " + TABLE_NAME + " (key int primary key, val varchar(20))"
                 + " with primary_zone='TEST_ZONE'";
 
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/table/ItInternalTableTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/table/ItInternalTableTest.java
index 79cf9019c4..953beb2b78 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/table/ItInternalTableTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/table/ItInternalTableTest.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.internal.table;
 
 import static org.apache.ignite.internal.TestWrappers.unwrapTableViewInternal;
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_REPLICA_COUNT;
 import static org.apache.ignite.internal.schema.BinaryRowMatcher.equalToRow;
 import static org.apache.ignite.internal.testframework.IgniteTestUtils.testNodeName;
@@ -698,7 +699,8 @@ public class ItInternalTableTest extends BaseIgniteAbstractTest {
         String zoneName = zoneNameForTable(tableName);
         IgniteSql sql = node.sql();
 
-        sql.execute(null, String.format("create zone \"%s\" with partitions=3, replicas=%d", zoneName, DEFAULT_REPLICA_COUNT));
+        sql.execute(null, String.format("create zone \"%s\" with partitions=3, replicas=%d, storage_profiles='%s'",
+                zoneName, DEFAULT_REPLICA_COUNT, DEFAULT_STORAGE_PROFILE));
 
         sql.execute(null,
                 String.format(
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/table/ItReadOnlyTransactionTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/table/ItReadOnlyTransactionTest.java
index 123514dec3..2a35c266bf 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/table/ItReadOnlyTransactionTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/table/ItReadOnlyTransactionTest.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.internal.table;
 
 import static org.apache.ignite.internal.TestWrappers.unwrapTableViewInternal;
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.testframework.IgniteTestUtils.bypassingThreadAssertions;
 import static org.apache.ignite.internal.testframework.IgniteTestUtils.bypassingThreadAssertionsAsync;
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -64,8 +65,8 @@ public class ItReadOnlyTransactionTest extends ClusterPerClassIntegrationTest {
 
     @BeforeEach
     public void beforeEach() {
-        sql(IgniteStringFormatter.format("CREATE ZONE IF NOT EXISTS {} WITH REPLICAS={}, PARTITIONS={};",
-                ZONE_NAME, initialNodes(), 10));
+        sql(IgniteStringFormatter.format("CREATE ZONE IF NOT EXISTS {} WITH REPLICAS={}, PARTITIONS={}, STORAGE_PROFILES='{}';",
+                ZONE_NAME, initialNodes(), 10, DEFAULT_STORAGE_PROFILE));
         sql(IgniteStringFormatter.format("CREATE TABLE {}(id INT PRIMARY KEY, val VARCHAR) WITH PRIMARY_ZONE='{}'",
                 TABLE_NAME, ZONE_NAME));
 
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/table/ItTableScanTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/table/ItTableScanTest.java
index cf9f69a474..06508bf3e3 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/table/ItTableScanTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/table/ItTableScanTest.java
@@ -67,7 +67,6 @@ import org.apache.ignite.internal.schema.row.Row;
 import org.apache.ignite.internal.schema.row.RowAssembler;
 import org.apache.ignite.internal.sql.BaseSqlIntegrationTest;
 import org.apache.ignite.internal.storage.impl.TestMvPartitionStorage;
-import org.apache.ignite.internal.storage.impl.TestStorageEngine;
 import org.apache.ignite.internal.storage.index.impl.TestSortedIndexStorage;
 import org.apache.ignite.internal.testframework.IgniteTestUtils;
 import org.apache.ignite.internal.testframework.WithSystemProperty;
@@ -934,7 +933,7 @@ public class ItTableScanTest extends BaseSqlIntegrationTest {
      * @return Ignite table.
      */
     private static TableViewInternal getOrCreateTable() {
-        sql("CREATE ZONE IF NOT EXISTS ZONE1 ENGINE " + TestStorageEngine.ENGINE_NAME + " WITH REPLICAS=1, PARTITIONS=1;");
+        sql("CREATE ZONE IF NOT EXISTS ZONE1 WITH REPLICAS=1, PARTITIONS=1, STORAGE_PROFILES='test'");
 
         sql("CREATE TABLE IF NOT EXISTS " + TABLE_NAME
                 + " (key INTEGER PRIMARY KEY, valInt INTEGER NOT NULL, valStr VARCHAR NOT NULL) WITH PRIMARY_ZONE='ZONE1';");
diff --git a/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java b/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
index 49104e1a38..fd56fa5cca 100644
--- a/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
+++ b/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
@@ -70,7 +70,6 @@ import org.apache.ignite.internal.cluster.management.ClusterManagementGroupManag
 import org.apache.ignite.internal.cluster.management.NodeAttributesCollector;
 import org.apache.ignite.internal.cluster.management.configuration.ClusterManagementConfiguration;
 import org.apache.ignite.internal.cluster.management.configuration.NodeAttributesConfiguration;
-import org.apache.ignite.internal.cluster.management.configuration.StorageProfilesConfiguration;
 import org.apache.ignite.internal.cluster.management.raft.ClusterStateStorage;
 import org.apache.ignite.internal.cluster.management.raft.RocksDbClusterStateStorage;
 import org.apache.ignite.internal.cluster.management.topology.LogicalTopologyImpl;
@@ -186,6 +185,7 @@ import org.apache.ignite.internal.sql.engine.SqlQueryProcessor;
 import org.apache.ignite.internal.storage.DataStorageManager;
 import org.apache.ignite.internal.storage.DataStorageModule;
 import org.apache.ignite.internal.storage.DataStorageModules;
+import org.apache.ignite.internal.storage.configurations.StorageConfiguration;
 import org.apache.ignite.internal.storage.engine.StorageEngine;
 import org.apache.ignite.internal.storage.engine.ThreadAssertingStorageEngine;
 import org.apache.ignite.internal.systemview.SystemViewManagerImpl;
@@ -429,7 +429,8 @@ public class IgniteImpl implements Ignite {
         LocalFileConfigurationStorage localFileConfigurationStorage = new LocalFileConfigurationStorage(
                 name,
                 configPath,
-                localConfigurationGenerator
+                localConfigurationGenerator,
+                modules.local()
         );
 
         ConfigurationValidator localConfigurationValidator =
@@ -532,7 +533,7 @@ public class IgniteImpl implements Ignite {
         NodeAttributesCollector nodeAttributesCollector =
                 new NodeAttributesCollector(
                         nodeConfigRegistry.getConfiguration(NodeAttributesConfiguration.KEY),
-                        nodeConfigRegistry.getConfiguration(StorageProfilesConfiguration.KEY)
+                        nodeConfigRegistry.getConfiguration(StorageConfiguration.KEY)
                 );
 
         cmgMgr = new ClusterManagementGroupManager(
@@ -643,7 +644,10 @@ public class IgniteImpl implements Ignite {
                 logSyncer
         );
 
-        dataStorageMgr = new DataStorageManager(applyThreadAssertionsIfNeeded(storageEngines));
+        dataStorageMgr = new DataStorageManager(
+                applyThreadAssertionsIfNeeded(storageEngines),
+                nodeConfigRegistry.getConfiguration(StorageConfiguration.KEY)
+        );
 
         volatileLogStorageFactoryCreator = new VolatileLogStorageFactoryCreator(name, workDir.resolve("volatile-log-spillout"));
 
@@ -809,7 +813,6 @@ public class IgniteImpl implements Ignite {
                 distributedTblMgr,
                 schemaManager,
                 dataStorageMgr,
-                () -> dataStorageModules.collectSchemasFields(modules.local().polymorphicSchemaExtensions()),
                 replicaSvc,
                 clockService,
                 schemaSyncService,
diff --git a/modules/runner/src/main/java/org/apache/ignite/internal/configuration/storage/LocalFileConfigurationStorage.java b/modules/runner/src/main/java/org/apache/ignite/internal/configuration/storage/LocalFileConfigurationStorage.java
index dbf0c61eaf..739113e2eb 100644
--- a/modules/runner/src/main/java/org/apache/ignite/internal/configuration/storage/LocalFileConfigurationStorage.java
+++ b/modules/runner/src/main/java/org/apache/ignite/internal/configuration/storage/LocalFileConfigurationStorage.java
@@ -25,7 +25,7 @@ import static org.apache.ignite.internal.util.CompletableFutures.falseCompletedF
 import static org.apache.ignite.internal.util.CompletableFutures.trueCompletedFuture;
 
 import com.typesafe.config.Config;
-import com.typesafe.config.ConfigException;
+import com.typesafe.config.ConfigException.Parse;
 import com.typesafe.config.ConfigFactory;
 import com.typesafe.config.ConfigObject;
 import com.typesafe.config.ConfigParseOptions;
@@ -50,7 +50,11 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
+import org.apache.ignite.configuration.ConfigurationDynamicDefaultsPatcher;
+import org.apache.ignite.configuration.ConfigurationModule;
 import org.apache.ignite.configuration.annotation.ConfigurationType;
+import org.apache.ignite.configuration.validation.ConfigurationValidationException;
+import org.apache.ignite.internal.configuration.ConfigurationDynamicDefaultsPatcherImpl;
 import org.apache.ignite.internal.configuration.ConfigurationTreeGenerator;
 import org.apache.ignite.internal.configuration.NodeConfigCreateException;
 import org.apache.ignite.internal.configuration.NodeConfigParseException;
@@ -63,6 +67,7 @@ import org.apache.ignite.internal.logger.IgniteLogger;
 import org.apache.ignite.internal.logger.Loggers;
 import org.apache.ignite.internal.thread.NamedThreadFactory;
 import org.apache.ignite.internal.util.IgniteUtils;
+import org.jetbrains.annotations.Nullable;
 import org.jetbrains.annotations.TestOnly;
 
 /**
@@ -86,6 +91,9 @@ public class LocalFileConfigurationStorage implements ConfigurationStorage {
     /** Configuration tree generator. */
     private final ConfigurationTreeGenerator generator;
 
+    /** Configuration module, which provide configuration patches. **/
+    private final ConfigurationModule module;
+
     /** Configuration changes listener. */
     private final AtomicReference<ConfigurationStorageListener> lsnrRef = new AtomicReference<>();
 
@@ -103,10 +111,11 @@ public class LocalFileConfigurationStorage implements ConfigurationStorage {
      *
      * @param configPath Path to node bootstrap configuration file.
      * @param generator Configuration tree generator.
+     * @param module Configuration module, which provides configuration patches.
      */
     @TestOnly
-    public LocalFileConfigurationStorage(Path configPath, ConfigurationTreeGenerator generator) {
-        this("test", configPath, generator);
+    public LocalFileConfigurationStorage(Path configPath, ConfigurationTreeGenerator generator, @Nullable ConfigurationModule module) {
+        this("test", configPath, generator, module);
     }
 
     /**
@@ -114,11 +123,14 @@ public class LocalFileConfigurationStorage implements ConfigurationStorage {
      *
      * @param configPath Path to node bootstrap configuration file.
      * @param generator Configuration tree generator.
+     * @param module Configuration module, which provides configuration patches.
      */
-    public LocalFileConfigurationStorage(String nodeName, Path configPath, ConfigurationTreeGenerator generator) {
+    public LocalFileConfigurationStorage(
+            String nodeName, Path configPath, ConfigurationTreeGenerator generator, @Nullable ConfigurationModule module) {
         this.configPath = configPath;
         this.generator = generator;
         this.tempConfigPath = configPath.resolveSibling(configPath.getFileName() + ".tmp");
+        this.module = module;
 
         notificationsThreadPool = Executors.newFixedThreadPool(
                 2, NamedThreadFactory.create(nodeName, "cfg-file", LOG)
@@ -127,6 +139,26 @@ public class LocalFileConfigurationStorage implements ConfigurationStorage {
         checkAndRestoreConfigFile();
     }
 
+    /**
+     * Patch the local configs with defaults from provided {@link ConfigurationModule}.
+     *
+     * @param hocon Config string in Hocon format.
+     * @param module Configuration module, which provides configuration patches.
+     * @return Patched config string in Hocon format.
+     */
+    private String patch(String hocon, ConfigurationModule module) {
+        if (module == null) {
+            return hocon;
+        }
+
+        ConfigurationDynamicDefaultsPatcher localCfgDynamicDefaultsPatcher = new ConfigurationDynamicDefaultsPatcherImpl(
+                module,
+                generator
+        );
+
+        return localCfgDynamicDefaultsPatcher.patchWithDynamicDefaults(hocon);
+    }
+
     @Override
     public CompletableFuture<Data> readDataOnRecovery() {
         lock.writeLock().lock();
@@ -154,9 +186,12 @@ public class LocalFileConfigurationStorage implements ConfigurationStorage {
         checkAndRestoreConfigFile();
 
         try {
+            String confString = Files.readString(configPath.toAbsolutePath());
+
             ConfigParseOptions parseOptions = ConfigParseOptions.defaults().setSyntax(ConfigSyntax.CONF).setAllowMissing(false);
-            return ConfigFactory.parseFile(configPath.toFile(), parseOptions);
-        } catch (ConfigException.Parse e) {
+
+            return ConfigFactory.parseString(patch(confString, module), parseOptions);
+        } catch (Parse | ConfigurationValidationException | IOException e) {
             throw new NodeConfigParseException("Failed to parse config content from file " + configPath, e);
         }
     }
diff --git a/modules/runner/src/test/java/org/apache/ignite/internal/configuration/storage/LocalFileConfigurationStorageTest.java b/modules/runner/src/test/java/org/apache/ignite/internal/configuration/storage/LocalFileConfigurationStorageTest.java
index aca7fa140a..3c4616aa1e 100644
--- a/modules/runner/src/test/java/org/apache/ignite/internal/configuration/storage/LocalFileConfigurationStorageTest.java
+++ b/modules/runner/src/test/java/org/apache/ignite/internal/configuration/storage/LocalFileConfigurationStorageTest.java
@@ -90,7 +90,7 @@ public class LocalFileConfigurationStorageTest {
 
     @BeforeEach
     void before() {
-        storage = new LocalFileConfigurationStorage(getConfigFile(), treeGenerator);
+        storage = new LocalFileConfigurationStorage(getConfigFile(), treeGenerator, null);
 
         changer = new TestConfigurationChanger(
                 List.of(TopConfiguration.KEY),
@@ -535,7 +535,7 @@ public class LocalFileConfigurationStorageTest {
         ConfigParseOptions parseOptions = ConfigParseOptions.defaults().setSyntax(ConfigSyntax.JSON).setAllowMissing(false);
         assertDoesNotThrow(() -> ConfigFactory.parseFile(configFile.toFile(), parseOptions));
 
-        LocalFileConfigurationStorage storage = new LocalFileConfigurationStorage(configFile, treeGenerator);
+        LocalFileConfigurationStorage storage = new LocalFileConfigurationStorage(configFile, treeGenerator, null);
 
         // And storage reads the file successfully
         assertDoesNotThrow(storage::readDataOnRecovery);
diff --git a/modules/runner/src/testFixtures/java/org/apache/ignite/internal/BaseIgniteRestartTest.java b/modules/runner/src/testFixtures/java/org/apache/ignite/internal/BaseIgniteRestartTest.java
index a731be183d..2d392af51d 100644
--- a/modules/runner/src/testFixtures/java/org/apache/ignite/internal/BaseIgniteRestartTest.java
+++ b/modules/runner/src/testFixtures/java/org/apache/ignite/internal/BaseIgniteRestartTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal;
 
+import static org.apache.ignite.internal.TestDefaultProfilesNames.DEFAULT_AIMEM_PROFILE_NAME;
 import static org.apache.ignite.internal.testframework.IgniteTestUtils.testNodeName;
 import static org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully;
 import static org.hamcrest.MatcherAssert.assertThat;
@@ -99,6 +100,9 @@ public abstract class BaseIgniteRestartTest extends IgniteAbstractTest {
             + "  },\n"
             + "  raft: " + RAFT_CFG + ",\n"
             + "  clientConnector.port: {},\n"
+            + "  storage: {\n"
+            + "    profiles: {" + DEFAULT_AIMEM_PROFILE_NAME + ": { engine: \"aimem\"}}\n"
+            + "  },\n"
             + "  rest: {\n"
             + "    port: {}, \n"
             + "    ssl.port: {} \n"
diff --git a/modules/runner/src/testFixtures/java/org/apache/ignite/internal/ClusterPerClassIntegrationTest.java b/modules/runner/src/testFixtures/java/org/apache/ignite/internal/ClusterPerClassIntegrationTest.java
index af68b45ab4..d165a79aa7 100644
--- a/modules/runner/src/testFixtures/java/org/apache/ignite/internal/ClusterPerClassIntegrationTest.java
+++ b/modules/runner/src/testFixtures/java/org/apache/ignite/internal/ClusterPerClassIntegrationTest.java
@@ -17,7 +17,11 @@
 
 package org.apache.ignite.internal;
 
-import static org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_STORAGE_ENGINE;
+import static org.apache.ignite.internal.TestDefaultProfilesNames.DEFAULT_AIMEM_PROFILE_NAME;
+import static org.apache.ignite.internal.TestDefaultProfilesNames.DEFAULT_AIPERSIST_PROFILE_NAME;
+import static org.apache.ignite.internal.TestDefaultProfilesNames.DEFAULT_ROCKSDB_PROFILE_NAME;
+import static org.apache.ignite.internal.TestDefaultProfilesNames.DEFAULT_TEST_PROFILE_NAME;
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.catalog.descriptors.CatalogIndexStatus.AVAILABLE;
 import static org.apache.ignite.internal.lang.IgniteStringFormatter.format;
 import static org.apache.ignite.internal.testframework.IgniteTestUtils.waitForCondition;
@@ -36,7 +40,6 @@ import org.apache.ignite.InitParametersBuilder;
 import org.apache.ignite.internal.app.IgniteImpl;
 import org.apache.ignite.internal.catalog.CatalogManager;
 import org.apache.ignite.internal.catalog.CatalogService;
-import org.apache.ignite.internal.catalog.commands.CatalogUtils;
 import org.apache.ignite.internal.catalog.descriptors.CatalogIndexDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.CatalogZoneDescriptor;
 import org.apache.ignite.internal.hlc.HybridClock;
@@ -72,6 +75,12 @@ public abstract class ClusterPerClassIntegrationTest extends IgniteIntegrationTe
             + "      netClusterNodes: [ {} ]\n"
             + "    }\n"
             + "  },\n"
+            + "  storage.profiles: {"
+            + "        " + DEFAULT_TEST_PROFILE_NAME + ".engine: test, "
+            + "        " + DEFAULT_AIPERSIST_PROFILE_NAME + ".engine: aipersist, "
+            + "        " + DEFAULT_AIMEM_PROFILE_NAME + ".engine: aimem, "
+            + "        " + DEFAULT_ROCKSDB_PROFILE_NAME + ".engine: rocksDb"
+            + "  },\n"
             + "  clientConnector: { port:{} },\n"
             + "  rest.port: {},\n"
             + "  compute.threadPoolSize: 1\n"
@@ -186,12 +195,12 @@ public abstract class ClusterPerClassIntegrationTest extends IgniteIntegrationTe
      * @param zoneName Zone name.
      * @param replicas Replica factor.
      * @param partitions Partitions count.
-     * @param storageEngine Storage engine, {@code null} to use {@link CatalogUtils#DEFAULT_STORAGE_ENGINE}.
+     * @param storageProfile Storage profile.
      */
-    protected static void createZoneOnlyIfNotExists(String zoneName, int replicas, int partitions, @Nullable String storageEngine) {
+    protected static void createZoneOnlyIfNotExists(String zoneName, int replicas, int partitions, String storageProfile) {
         sql(format(
-                "CREATE ZONE IF NOT EXISTS {} ENGINE {} WITH REPLICAS={}, PARTITIONS={};",
-                zoneName, Objects.requireNonNullElse(storageEngine, DEFAULT_STORAGE_ENGINE), replicas, partitions
+                "CREATE ZONE IF NOT EXISTS {} WITH REPLICAS={}, PARTITIONS={}, STORAGE_PROFILES='{}';",
+                zoneName, replicas, partitions, storageProfile
         ));
     }
 
@@ -204,7 +213,7 @@ public abstract class ClusterPerClassIntegrationTest extends IgniteIntegrationTe
      * @param partitions Partitions count.
      */
     protected static Table createZoneAndTable(String zoneName, String tableName, int replicas, int partitions) {
-        createZoneOnlyIfNotExists(zoneName, replicas, partitions, null);
+        createZoneOnlyIfNotExists(zoneName, replicas, partitions, DEFAULT_STORAGE_PROFILE);
 
         return createTableOnly(tableName, zoneName);
     }
@@ -216,16 +225,16 @@ public abstract class ClusterPerClassIntegrationTest extends IgniteIntegrationTe
      * @param tableName Table name.
      * @param replicas Replica factor.
      * @param partitions Partitions count.
-     * @param storageEngine Storage engine, {@code null} to use {@link CatalogUtils#DEFAULT_STORAGE_ENGINE}.
+     * @param storageProfile Storage profile.
      */
     protected static Table createZoneAndTable(
             String zoneName,
             String tableName,
             int replicas,
             int partitions,
-            @Nullable String storageEngine
+            String storageProfile
     ) {
-        createZoneOnlyIfNotExists(zoneName, replicas, partitions, storageEngine);
+        createZoneOnlyIfNotExists(zoneName, replicas, partitions, storageProfile);
 
         return createTableOnly(tableName, zoneName);
     }
diff --git a/modules/runner/src/testFixtures/java/org/apache/ignite/internal/ClusterPerTestIntegrationTest.java b/modules/runner/src/testFixtures/java/org/apache/ignite/internal/ClusterPerTestIntegrationTest.java
index 6362c04674..83565cf402 100644
--- a/modules/runner/src/testFixtures/java/org/apache/ignite/internal/ClusterPerTestIntegrationTest.java
+++ b/modules/runner/src/testFixtures/java/org/apache/ignite/internal/ClusterPerTestIntegrationTest.java
@@ -17,6 +17,11 @@
 
 package org.apache.ignite.internal;
 
+import static org.apache.ignite.internal.TestDefaultProfilesNames.DEFAULT_AIMEM_PROFILE_NAME;
+import static org.apache.ignite.internal.TestDefaultProfilesNames.DEFAULT_AIPERSIST_PROFILE_NAME;
+import static org.apache.ignite.internal.TestDefaultProfilesNames.DEFAULT_ROCKSDB_PROFILE_NAME;
+import static org.apache.ignite.internal.TestDefaultProfilesNames.DEFAULT_TEST_PROFILE_NAME;
+
 import java.nio.file.Path;
 import java.util.List;
 import java.util.stream.Stream;
@@ -46,6 +51,12 @@ public abstract class ClusterPerTestIntegrationTest extends IgniteIntegrationTes
             + "      netClusterNodes: [ {} ]\n"
             + "    }\n"
             + "  },\n"
+            + "  storage.profiles: {"
+            + "        " + DEFAULT_TEST_PROFILE_NAME + ".engine: test, "
+            + "        " + DEFAULT_AIPERSIST_PROFILE_NAME + ".engine: aipersist, "
+            + "        " + DEFAULT_AIMEM_PROFILE_NAME + ".engine: aimem, "
+            + "        " + DEFAULT_ROCKSDB_PROFILE_NAME + ".engine: rocksDb"
+            + "  },\n"
             + "  clientConnector: { port:{} },\n"
             + "  rest.port: {},\n"
             + "  compute.threadPoolSize: 1\n"
diff --git a/modules/api/src/main/java/org/apache/ignite/catalog/ZoneEngine.java b/modules/runner/src/testFixtures/java/org/apache/ignite/internal/TestDefaultProfilesNames.java
similarity index 68%
copy from modules/api/src/main/java/org/apache/ignite/catalog/ZoneEngine.java
copy to modules/runner/src/testFixtures/java/org/apache/ignite/internal/TestDefaultProfilesNames.java
index 4e33a6d770..de12ac4c9f 100644
--- a/modules/api/src/main/java/org/apache/ignite/catalog/ZoneEngine.java
+++ b/modules/runner/src/testFixtures/java/org/apache/ignite/internal/TestDefaultProfilesNames.java
@@ -15,11 +15,17 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.catalog;
+package org.apache.ignite.internal;
 
 /**
- * Engine to use for distribution zone.
+ * Test default profile names for different storages.
  */
-public enum ZoneEngine {
-    AIMEM, ROCKSDB, DEFAULT
+public interface TestDefaultProfilesNames {
+    String DEFAULT_AIMEM_PROFILE_NAME = "default_aimem";
+
+    String DEFAULT_AIPERSIST_PROFILE_NAME = "default_aipersist";
+
+    String DEFAULT_ROCKSDB_PROFILE_NAME = "default_rocksdb";
+
+    String DEFAULT_TEST_PROFILE_NAME = "test";
 }
diff --git a/modules/schema/build.gradle b/modules/schema/build.gradle
index b45ec4e2a8..b45ea6aba1 100644
--- a/modules/schema/build.gradle
+++ b/modules/schema/build.gradle
@@ -33,10 +33,9 @@ dependencies {
     implementation project(':ignite-bytecode')
     implementation project(':ignite-catalog')
     implementation project(':ignite-core')
-    implementation project(':ignite-replicator')
     implementation project(':ignite-configuration-api')
     implementation project(':ignite-metastorage-api')
-    implementation project(':ignite-low-watermark')
+//    implementation project(':ignite-low-watermark')
     implementation libs.jetbrains.annotations
     implementation libs.auto.service.annotations
 
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/GcConfigurationSchema.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/GcConfigurationSchema.java
index 80354ea4a3..9eeb11cd60 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/GcConfigurationSchema.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/GcConfigurationSchema.java
@@ -21,7 +21,6 @@ import org.apache.ignite.configuration.annotation.ConfigValue;
 import org.apache.ignite.configuration.annotation.ConfigurationRoot;
 import org.apache.ignite.configuration.annotation.ConfigurationType;
 import org.apache.ignite.configuration.annotation.Value;
-import org.apache.ignite.internal.lowwatermark.configuration.LowWatermarkConfigurationSchema;
 
 /**
  * Garbage collector configuration schema.
diff --git a/modules/low-watermark/src/main/java/org/apache/ignite/internal/lowwatermark/configuration/LowWatermarkConfigurationSchema.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/LowWatermarkConfigurationSchema.java
similarity index 91%
rename from modules/low-watermark/src/main/java/org/apache/ignite/internal/lowwatermark/configuration/LowWatermarkConfigurationSchema.java
rename to modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/LowWatermarkConfigurationSchema.java
index 505ba3a43e..9a1c3fb8d4 100644
--- a/modules/low-watermark/src/main/java/org/apache/ignite/internal/lowwatermark/configuration/LowWatermarkConfigurationSchema.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/LowWatermarkConfigurationSchema.java
@@ -15,9 +15,9 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.lowwatermark.configuration;
+package org.apache.ignite.internal.schema.configuration;
 
-import static org.apache.ignite.internal.replicator.ReplicaManager.DEFAULT_IDLE_SAFE_TIME_PROPAGATION_PERIOD_MILLISECONDS;
+import static org.apache.ignite.internal.replicator.ReplicatorConstants.DEFAULT_IDLE_SAFE_TIME_PROPAGATION_PERIOD_MILLISECONDS;
 
 import java.util.concurrent.TimeUnit;
 import org.apache.ignite.configuration.annotation.Config;
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/SchemaManagerTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/SchemaManagerTest.java
index 338a5d9ad5..2593710394 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/SchemaManagerTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/SchemaManagerTest.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.internal.schema;
 
 import static org.apache.ignite.internal.catalog.CatalogManagerImpl.INITIAL_CAUSALITY_TOKEN;
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.catalog.descriptors.CatalogTableDescriptor.INITIAL_TABLE_VERSION;
 import static org.apache.ignite.internal.testframework.matchers.CompletableFutureCompletedMatcher.completedFuture;
 import static org.apache.ignite.internal.testframework.matchers.CompletableFutureExceptionMatcher.willTimeoutFast;
@@ -122,7 +123,7 @@ class SchemaManagerTest extends BaseIgniteAbstractTest {
                 new CatalogTableColumnDescriptor("v1", ColumnType.INT32, false, 0, 0, 0, null)
         );
         CatalogTableDescriptor tableDescriptor = new CatalogTableDescriptor(
-                TABLE_ID, -1, -1, TABLE_NAME, 0, columns, List.of("k1", "k2"), null
+                TABLE_ID, -1, -1, TABLE_NAME, 0, columns, List.of("k1", "k2"), null, DEFAULT_STORAGE_PROFILE
         );
 
         CompletableFuture<Boolean> future = tableCreatedListener()
@@ -161,12 +162,14 @@ class SchemaManagerTest extends BaseIgniteAbstractTest {
                 0,
                 columns,
                 List.of("k1", "k2"),
-                null
+                null,
+                DEFAULT_STORAGE_PROFILE
         ).newDescriptor(
                 TABLE_NAME,
                 INITIAL_TABLE_VERSION + 1,
                 columns,
-                INITIAL_CAUSALITY_TOKEN
+                INITIAL_CAUSALITY_TOKEN,
+                DEFAULT_STORAGE_PROFILE
         );
     }
 
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/catalog/CatalogToSchemaDescriptorConverterTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/catalog/CatalogToSchemaDescriptorConverterTest.java
index 1f6441cb58..488faceef5 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/catalog/CatalogToSchemaDescriptorConverterTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/catalog/CatalogToSchemaDescriptorConverterTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.schema.catalog;
 
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.schema.SchemaTestUtils.specToType;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.equalTo;
@@ -140,7 +141,8 @@ public class CatalogToSchemaDescriptorConverterTest extends AbstractSchemaConver
                         new CatalogTableColumnDescriptor("K1", ColumnType.INT32, false, 0, 0, 0, null)
                 ),
                 List.of("K1", "K2"),
-                List.of("K2")
+                List.of("K2"),
+                DEFAULT_STORAGE_PROFILE
         );
 
         SchemaDescriptor schema = CatalogToSchemaDescriptorConverter.convert(tableDescriptor, tableDescriptor.tableVersion());
diff --git a/modules/sql-engine/build.gradle b/modules/sql-engine/build.gradle
index a1e26214e5..b24dbd327d 100644
--- a/modules/sql-engine/build.gradle
+++ b/modules/sql-engine/build.gradle
@@ -116,6 +116,7 @@ dependencies {
     integrationTestImplementation project(':ignite-schema')
     integrationTestImplementation project(':ignite-catalog')
     integrationTestImplementation project(':ignite-transactions')
+    integrationTestImplementation project(':ignite-storage-api')
     integrationTestImplementation project(':ignite-cluster-management')
     integrationTestImplementation project(':ignite-system-view-api')
     integrationTestImplementation project(':ignite-system-view')
diff --git a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItAggregatesTest.java b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItAggregatesTest.java
index ae6b4262d6..86cbb06e67 100644
--- a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItAggregatesTest.java
+++ b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItAggregatesTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.sql.engine;
 
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -61,7 +62,7 @@ public class ItAggregatesTest extends BaseSqlIntegrationTest {
     static void initTestData() {
         createAndPopulateTable();
 
-        sql("CREATE ZONE test_zone with replicas=2, partitions=10");
+        sql("CREATE ZONE test_zone with replicas=2, partitions=10, storage_profiles='" + DEFAULT_STORAGE_PROFILE + "'");
         sql("CREATE TABLE test (id INT PRIMARY KEY, grp0 INT, grp1 INT, val0 INT, val1 INT) WITH PRIMARY_ZONE='TEST_ZONE'");
         sql("CREATE TABLE test_one_col_idx (pk INT PRIMARY KEY, col0 INT)");
 
diff --git a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItCreateTableDdlTest.java b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItCreateTableDdlTest.java
index baa014f61e..67bc59fd0f 100644
--- a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItCreateTableDdlTest.java
+++ b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItCreateTableDdlTest.java
@@ -18,6 +18,8 @@
 package org.apache.ignite.internal.sql.engine;
 
 import static org.apache.ignite.internal.TestWrappers.unwrapTableViewInternal;
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_ZONE_NAME;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.SYSTEM_SCHEMAS;
 import static org.apache.ignite.internal.lang.IgniteStringFormatter.format;
 import static org.apache.ignite.internal.sql.engine.util.SqlTestUtils.assertThrowsSqlException;
@@ -34,6 +36,8 @@ import java.util.Set;
 import java.util.stream.Stream;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.ignite.internal.app.IgniteImpl;
+import org.apache.ignite.internal.catalog.descriptors.CatalogTableDescriptor;
+import org.apache.ignite.internal.catalog.descriptors.CatalogZoneDescriptor;
 import org.apache.ignite.internal.lang.IgniteStringBuilder;
 import org.apache.ignite.internal.schema.Column;
 import org.apache.ignite.internal.schema.SchemaTestUtils;
@@ -375,19 +379,19 @@ public class ItCreateTableDdlTest extends BaseSqlIntegrationTest {
 
     @Test
     public void testSuccessfulCreateTableWithZoneIdentifier() {
-        sql("CREATE ZONE test_zone");
+        sql("CREATE ZONE test_zone WITH STORAGE_PROFILES='" + DEFAULT_STORAGE_PROFILE + "'");
         sql("CREATE TABLE test_table (id INT PRIMARY KEY, val INT) WITH PRIMARY_ZONE=test_zone");
     }
 
     @Test
     public void testSuccessfulCreateTableWithZoneLiteral() {
-        sql("CREATE ZONE test_zone");
+        sql("CREATE ZONE test_zone WITH STORAGE_PROFILES='" + DEFAULT_STORAGE_PROFILE + "'");
         sql("CREATE TABLE test_table (id INT PRIMARY KEY, val INT) WITH PRIMARY_ZONE='TEST_ZONE'");
     }
 
     @Test
     public void testSuccessfulCreateTableWithZoneQuotedLiteral() {
-        sql("CREATE ZONE \"test_zone\"");
+        sql("CREATE ZONE \"test_zone\" WITH STORAGE_PROFILES='" + DEFAULT_STORAGE_PROFILE + "'");
         sql("CREATE TABLE test_table (id INT PRIMARY KEY, val INT) WITH PRIMARY_ZONE='test_zone'");
         sql("DROP TABLE test_table");
         sql("DROP ZONE \"test_zone\"");
@@ -396,11 +400,83 @@ public class ItCreateTableDdlTest extends BaseSqlIntegrationTest {
     @Test
     public void testExceptionalCreateTableWithZoneUnquotedLiteral() {
 
-        sql("CREATE ZONE test_zone");
+        sql("CREATE ZONE test_zone WITH STORAGE_PROFILES='" + DEFAULT_STORAGE_PROFILE + "'");
         assertThrowsSqlException(
                 SqlException.class,
                 STMT_VALIDATION_ERR,
                 "Failed to validate query. Distribution zone with name 'test_zone' not found",
                 () -> sql("CREATE TABLE test_table (id INT PRIMARY KEY, val INT) WITH PRIMARY_ZONE='test_zone'"));
     }
+
+    @Test
+    public void tableStorageProfileWithoutSettingItExplicitly() {
+        sql("CREATE TABLE TEST(ID INT PRIMARY KEY, VAL0 INT)");
+
+        IgniteImpl node = CLUSTER.aliveNode();
+
+        CatalogTableDescriptor table = node.catalogManager().table("TEST", node.clock().nowLong());
+
+        CatalogZoneDescriptor zone = node.catalogManager().zone(DEFAULT_ZONE_NAME, node.clock().nowLong());
+
+        assertEquals(zone.storageProfiles().defaultProfile().storageProfile(), table.storageProfile());
+    }
+
+
+    @Test
+    public void tableStorageProfileExceptionIfZoneDoesntContainProfile() {
+        assertThrowsSqlException(
+                STMT_VALIDATION_ERR,
+                "Zone with name '" + DEFAULT_ZONE_NAME + "' does not contain table's storage profile",
+                () -> sql("CREATE TABLE TEST(ID INT PRIMARY KEY, VAL0 INT) WITH STORAGE_PROFILE='profile1'")
+        );
+    }
+
+    @Test
+    public void tableStorageProfile() {
+        sql("CREATE TABLE TEST(ID INT PRIMARY KEY, VAL0 INT) WITH STORAGE_PROFILE='" + DEFAULT_STORAGE_PROFILE + "'");
+
+        IgniteImpl node = CLUSTER.aliveNode();
+
+        CatalogTableDescriptor table = node.catalogManager().table("TEST", node.clock().nowLong());
+
+        assertEquals(DEFAULT_STORAGE_PROFILE, table.storageProfile());
+
+        CatalogZoneDescriptor zone = node.catalogManager().zone(DEFAULT_ZONE_NAME, node.clock().nowLong());
+
+        assertEquals(zone.storageProfiles().defaultProfile().storageProfile(), table.storageProfile());
+    }
+
+    @Test
+    public void tableStorageProfileWithCustomZoneDefaultProfile() {
+        sql("CREATE ZONE ZONE1 WITH PARTITIONS = 1, STORAGE_PROFILES = '" + DEFAULT_STORAGE_PROFILE + "'");
+
+        sql("CREATE TABLE TEST(ID INT PRIMARY KEY, VAL0 INT) WITH PRIMARY_ZONE='ZONE1'");
+
+        IgniteImpl node = CLUSTER.aliveNode();
+
+        CatalogTableDescriptor table = node.catalogManager().table("TEST", node.clock().nowLong());
+
+        assertEquals(DEFAULT_STORAGE_PROFILE, table.storageProfile());
+
+        sql("DROP TABLE TEST");
+
+        sql("DROP ZONE ZONE1");
+    }
+
+    @Test
+    public void tableStorageProfileWithCustomZoneExplicitProfile() {
+        sql("CREATE ZONE ZONE1 WITH PARTITIONS = 1, STORAGE_PROFILES = '" + DEFAULT_STORAGE_PROFILE + "'");
+
+        sql("CREATE TABLE TEST(ID INT PRIMARY KEY, VAL0 INT) WITH PRIMARY_ZONE='ZONE1', STORAGE_PROFILE='" + DEFAULT_STORAGE_PROFILE + "'");
+
+        IgniteImpl node = CLUSTER.aliveNode();
+
+        CatalogTableDescriptor table = node.catalogManager().table("TEST", node.clock().nowLong());
+
+        assertEquals(DEFAULT_STORAGE_PROFILE, table.storageProfile());
+
+        sql("DROP TABLE TEST");
+
+        sql("DROP ZONE ZONE1");
+    }
 }
diff --git a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItIndexSpoolTest.java b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItIndexSpoolTest.java
index a5f56d128e..2ca44e8aab 100644
--- a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItIndexSpoolTest.java
+++ b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItIndexSpoolTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.sql.engine;
 
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.sql.engine.util.Commons.IN_BUFFER_SIZE;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
@@ -97,7 +98,12 @@ public class ItIndexSpoolTest extends BaseSqlIntegrationTest {
         }
 
         for (String name : List.of("TEST0", "TEST1")) {
-            sql(String.format("CREATE ZONE %s with replicas=2, partitions=%d", "ZONE_" + name.toUpperCase(), parts));
+            sql(String.format(
+                    "CREATE ZONE %s with replicas=2, partitions=%d, storage_profiles='%s'",
+                    "ZONE_" + name.toUpperCase(),
+                    parts,
+                    DEFAULT_STORAGE_PROFILE
+            ));
             sql(String.format("CREATE TABLE %s(id INT PRIMARY KEY, jid INT, val VARCHAR) WITH PRIMARY_ZONE='%s'",
                     name, "ZONE_" + name.toUpperCase()));
 
diff --git a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItPkOnlyTableCrossApiTest.java b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItPkOnlyTableCrossApiTest.java
index bda25ad758..452c7b6394 100644
--- a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItPkOnlyTableCrossApiTest.java
+++ b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItPkOnlyTableCrossApiTest.java
@@ -76,9 +76,16 @@ public class ItPkOnlyTableCrossApiTest extends BaseSqlIntegrationTest {
         for (String engine : ENGINES) {
             String testZoneName = ("test_zone_" + engine).toUpperCase();
 
-            sql(String.format("create zone %s engine %s with partitions=1, replicas=3;", testZoneName, engine));
-            sql(String.format("create table %s (ID int, NAME varchar, primary key(ID, NAME)) with primary_zone='%s'",
-                    tableName(engine), testZoneName));
+            String regionName = "default_" + engine;
+            sql(String.format("create zone %s with partitions=1, replicas=3, storage_profiles = '%s';",
+                    testZoneName, regionName, regionName));
+
+            sql(String.format(
+                    "create table %s (ID int, NAME varchar, primary key(ID, NAME)) with primary_zone='%s', storage_profile='%s'",
+                    tableName(engine),
+                    testZoneName,
+                    regionName
+            ));
         }
     }
 
diff --git a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItZoneDdlTest.java b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItZoneDdlTest.java
index 5fdba7b80c..ee1cc4465e 100644
--- a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItZoneDdlTest.java
+++ b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItZoneDdlTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.sql.engine;
 
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.lang.IgniteStringFormatter.format;
 
 import org.apache.ignite.internal.ClusterPerClassIntegrationTest;
@@ -122,7 +123,9 @@ public class ItZoneDdlTest extends ClusterPerClassIntegrationTest {
     }
 
     private static void tryToCreateZone(String zoneName, boolean failIfExists) {
-        sql(String.format("CREATE ZONE %s", failIfExists ? zoneName : "IF NOT EXISTS " + zoneName));
+        sql(String.format(
+                "CREATE ZONE %s WITH STORAGE_PROFILES='%s'", failIfExists ? zoneName : "IF NOT EXISTS " + zoneName, DEFAULT_STORAGE_PROFILE
+        ));
     }
 
     private static void tryToDropZone(String zoneName, boolean failIfNotExists) {
diff --git a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItZonesSystemViewTest.java b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItZonesSystemViewTest.java
index bffe3e2bd2..da5715b148 100644
--- a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItZonesSystemViewTest.java
+++ b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItZonesSystemViewTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.sql.engine;
 
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_ZONE_NAME;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_FILTER;
 import static org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_PARTITION_COUNT;
@@ -155,9 +156,10 @@ public class ItZonesSystemViewTest extends BaseSqlIntegrationTest {
                 + "\"REPLICAS\" = %d, "
                 + "\"DATA_NODES_AUTO_ADJUST_SCALE_UP\" = %d, "
                 + "\"DATA_NODES_AUTO_ADJUST_SCALE_DOWN\" = %d,"
-                + "\"DATA_NODES_FILTER\" = '%s'";
+                + "\"DATA_NODES_FILTER\" = '%s',"
+                + "\"STORAGE_PROFILES\" = '%s'";
 
-        return String.format(sqlFormat, zoneName, partitions, replicas, scaleUp, scaleDown, filter);
+        return String.format(sqlFormat, zoneName, partitions, replicas, scaleUp, scaleDown, filter, DEFAULT_STORAGE_PROFILE);
     }
 
     private static String selectFromZonesSystemView(String zoneName) {
diff --git a/modules/sql-engine/src/main/codegen/includes/parserImpls.ftl b/modules/sql-engine/src/main/codegen/includes/parserImpls.ftl
index 2b3040b7c9..e6c5bd9976 100644
--- a/modules/sql-engine/src/main/codegen/includes/parserImpls.ftl
+++ b/modules/sql-engine/src/main/codegen/includes/parserImpls.ftl
@@ -510,20 +510,16 @@ SqlCreate SqlCreateZone(Span s, boolean replace) :
         final boolean ifNotExists;
         final SqlIdentifier id;
         SqlNodeList optionList = null;
-        SqlIdentifier engine = null;
 }
 {
     <ZONE> { s.add(this); }
         ifNotExists = IfNotExistsOpt()
         id = CompoundIdentifier()
-    [
-            <ENGINE> { s.add(this); } engine = SimpleIdentifier()
-    ]
     [
         <WITH> { s.add(this); } optionList = CreateZoneOptionList()
     ]
     {
-        return new IgniteSqlCreateZone(s.end(this), ifNotExists, id, optionList, engine);
+        return new IgniteSqlCreateZone(s.end(this), ifNotExists, id, optionList);
     }
 }
 
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/SqlQueryProcessor.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/SqlQueryProcessor.java
index 119ad36098..c40d668dde 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/SqlQueryProcessor.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/SqlQueryProcessor.java
@@ -40,7 +40,6 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
-import java.util.Map;
 import java.util.Queue;
 import java.util.Set;
 import java.util.UUID;
@@ -53,7 +52,6 @@ import java.util.function.Consumer;
 import java.util.function.Function;
 import java.util.function.LongFunction;
 import java.util.function.LongSupplier;
-import java.util.function.Supplier;
 import java.util.stream.Collectors;
 import org.apache.calcite.schema.SchemaPlus;
 import org.apache.calcite.tools.Frameworks;
@@ -189,8 +187,6 @@ public class SqlQueryProcessor implements QueryProcessor {
 
     private final DataStorageManager dataStorageManager;
 
-    private final Supplier<Map<String, Map<String, Class<?>>>> dataStorageFieldsSupplier;
-
     /** Busy lock for stop synchronisation. */
     private final IgniteSpinBusyLock busyLock = new IgniteSpinBusyLock();
 
@@ -242,7 +238,6 @@ public class SqlQueryProcessor implements QueryProcessor {
             TableManager tableManager,
             SchemaManager schemaManager,
             DataStorageManager dataStorageManager,
-            Supplier<Map<String, Map<String, Class<?>>>> dataStorageFieldsSupplier,
             ReplicaService replicaService,
             ClockService clockService,
             SchemaSyncService schemaSyncService,
@@ -261,7 +256,6 @@ public class SqlQueryProcessor implements QueryProcessor {
         this.tableManager = tableManager;
         this.schemaManager = schemaManager;
         this.dataStorageManager = dataStorageManager;
-        this.dataStorageFieldsSupplier = dataStorageFieldsSupplier;
         this.replicaService = replicaService;
         this.clockService = clockService;
         this.schemaSyncService = schemaSyncService;
@@ -297,7 +291,6 @@ public class SqlQueryProcessor implements QueryProcessor {
                 nodeName,
                 CACHE_FACTORY,
                 dataStorageManager,
-                dataStorageFieldsSupplier.get(),
                 metricManager,
                 clusterCfg,
                 nodeCfg
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ddl/DdlToCatalogCommandConverter.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ddl/DdlToCatalogCommandConverter.java
index a1fe0f8fe4..0efd0a8409 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ddl/DdlToCatalogCommandConverter.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ddl/DdlToCatalogCommandConverter.java
@@ -17,11 +17,9 @@
 
 package org.apache.ignite.internal.sql.engine.exec.ddl;
 
-import static org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_DATA_REGION;
-import static org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_STORAGE_ENGINE;
+import static org.apache.ignite.internal.distributionzones.DistributionZonesUtil.parseStorageProfiles;
 
 import java.util.List;
-import java.util.Objects;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 import org.apache.calcite.rel.type.RelDataType;
@@ -36,7 +34,6 @@ import org.apache.ignite.internal.catalog.commands.AlterZoneSetDefaultCatalogCom
 import org.apache.ignite.internal.catalog.commands.ColumnParams;
 import org.apache.ignite.internal.catalog.commands.CreateHashIndexCommand;
 import org.apache.ignite.internal.catalog.commands.CreateSortedIndexCommand;
-import org.apache.ignite.internal.catalog.commands.DataStorageParams;
 import org.apache.ignite.internal.catalog.commands.DefaultValue;
 import org.apache.ignite.internal.catalog.commands.RenameZoneCommand;
 import org.apache.ignite.internal.catalog.commands.TableHashPrimaryKey;
@@ -101,6 +98,7 @@ class DdlToCatalogCommandConverter {
                 .colocationColumns(cmd.colocationColumns())
 
                 .zone(cmd.zone())
+                .storageProfile(cmd.storageProfile())
 
                 .build();
     }
@@ -113,10 +111,6 @@ class DdlToCatalogCommandConverter {
     }
 
     static CatalogCommand convert(CreateZoneCommand cmd) {
-        // TODO: IGNITE-19719 We need to define the default engine differently and the parameters should depend on the engine
-        String engine = Objects.requireNonNullElse(cmd.dataStorage(), DEFAULT_STORAGE_ENGINE);
-        String dataRegion = (String) cmd.dataStorageOptions().getOrDefault("dataRegion", DEFAULT_DATA_REGION);
-
         return org.apache.ignite.internal.catalog.commands.CreateZoneCommand.builder()
                 .zoneName(cmd.zoneName())
                 .partitions(cmd.partitions())
@@ -125,7 +119,7 @@ class DdlToCatalogCommandConverter {
                 .dataNodesAutoAdjust(cmd.dataNodesAutoAdjust())
                 .dataNodesAutoAdjustScaleUp(cmd.dataNodesAutoAdjustScaleUp())
                 .dataNodesAutoAdjustScaleDown(cmd.dataNodesAutoAdjustScaleDown())
-                .dataStorageParams(DataStorageParams.builder().engine(engine).dataRegion(dataRegion).build())
+                .storageProfilesParams(parseStorageProfiles(cmd.storageProfiles()))
                 .build();
     }
 
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PrepareServiceImpl.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PrepareServiceImpl.java
index ef0ec57cee..d8b0b7c3f0 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PrepareServiceImpl.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PrepareServiceImpl.java
@@ -42,7 +42,6 @@ import org.apache.calcite.sql.SqlDdl;
 import org.apache.calcite.sql.SqlExplain;
 import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql.SqlNodeList;
-import org.apache.ignite.internal.catalog.commands.CatalogUtils;
 import org.apache.ignite.internal.lang.SqlExceptionMapperUtil;
 import org.apache.ignite.internal.logger.IgniteLogger;
 import org.apache.ignite.internal.logger.Loggers;
@@ -117,7 +116,6 @@ public class PrepareServiceImpl implements PrepareService {
      * @param nodeName Name of the current Ignite node. Will be used in thread factory as part of the thread name.
      * @param cacheFactory A factory to create cache of query plans.
      * @param dataStorageManager Data storage manager.
-     * @param dataStorageFields Data storage fields. Mapping: Data storage name -> field name -> field type.
      * @param metricManager Metric manager.
      * @param clusterCfg  Cluster SQL configuration.
      * @param nodeCfg Node SQL configuration.
@@ -126,7 +124,6 @@ public class PrepareServiceImpl implements PrepareService {
             String nodeName,
             CacheFactory cacheFactory,
             DataStorageManager dataStorageManager,
-            Map<String, Map<String, Class<?>>> dataStorageFields,
             MetricManager metricManager,
             SqlDistributedConfiguration clusterCfg,
             SqlLocalConfiguration nodeCfg
@@ -135,7 +132,7 @@ public class PrepareServiceImpl implements PrepareService {
                 nodeName,
                 clusterCfg.planner().estimatedNumberOfQueries().value(),
                 cacheFactory,
-                new DdlSqlToCommandConverter(dataStorageFields, () -> CatalogUtils.DEFAULT_STORAGE_ENGINE),
+                new DdlSqlToCommandConverter(),
                 clusterCfg.planner().maxPlanningTime().value(),
                 nodeCfg.planner().threadCount().value(),
                 metricManager
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/CreateTableCommand.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/CreateTableCommand.java
index 51d7c73a7c..f985626def 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/CreateTableCommand.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/CreateTableCommand.java
@@ -46,6 +46,8 @@ public class CreateTableCommand extends AbstractTableDdlCommand {
 
     private String zone;
 
+    private String storageProfile;
+
     /**
      * Get primary key index type.
      */
@@ -139,4 +141,19 @@ public class CreateTableCommand extends AbstractTableDdlCommand {
     public void zone(String zoneName) {
         this.zone = zoneName;
     }
+
+    /**
+     * Get storage profile.
+     */
+    @Nullable
+    public String storageProfile() {
+        return storageProfile;
+    }
+
+    /**
+     * Set storage profile.
+     */
+    public void storageProfile(String storageProfile) {
+        this.storageProfile = storageProfile;
+    }
 }
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/CreateZoneCommand.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/CreateZoneCommand.java
index ecc3b43bd4..82d9e73008 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/CreateZoneCommand.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/CreateZoneCommand.java
@@ -17,8 +17,6 @@
 
 package org.apache.ignite.internal.sql.engine.prepare.ddl;
 
-import java.util.HashMap;
-import java.util.Map;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -38,7 +36,7 @@ public class CreateZoneCommand extends AbstractZoneDdlCommand {
     private String affinity;
 
     /** Data nodes filter expression. */
-    private String nodeFiler;
+    private String nodeFilter;
 
     /** Data nodes auto adjust timeout. */
     private Integer dataNodesAutoAdjust;
@@ -49,36 +47,15 @@ public class CreateZoneCommand extends AbstractZoneDdlCommand {
     /** Data nodes auto adjust scale down timeout. */
     private Integer dataNodesAutoAdjustScaleDown;
 
-    /** Data storage. */
-    private String dataStorage;
+    /** Storage profiles. */
+    private String storageProfiles;
 
-    /** Data storage options. */
-    private Map<String, Object> dataStorageOptions;
-
-    @Nullable public String dataStorage() {
-        return dataStorage;
-    }
-
-    public void dataStorage(String dataStorage) {
-        this.dataStorage = dataStorage;
+    public String storageProfiles() {
+        return storageProfiles;
     }
 
-    public Map<String, Object> dataStorageOptions() {
-        return (dataStorageOptions == null) ? Map.of() : dataStorageOptions;
-    }
-
-    /**
-     * Add data storage option.
-     *
-     * @param name Name of the option.
-     * @param value Value of the option.
-     */
-    public void addDataStorageOption(String name, Object value) {
-        if (dataStorageOptions == null) {
-            dataStorageOptions = new HashMap<>();
-        }
-
-        dataStorageOptions.put(name, value);
+    public void storageProfiles(String storageProfiles) {
+        this.storageProfiles = storageProfiles;
     }
 
     public boolean ifNotExists() {
@@ -114,11 +91,11 @@ public class CreateZoneCommand extends AbstractZoneDdlCommand {
     }
 
     @Nullable public String nodeFilter() {
-        return nodeFiler;
+        return nodeFilter;
     }
 
-    public void nodeFilter(String nodeFiler) {
-        this.nodeFiler = nodeFiler;
+    public void nodeFilter(String nodeFilter) {
+        this.nodeFilter = nodeFilter;
     }
 
     @Nullable public Integer dataNodesAutoAdjust() {
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverter.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverter.java
index 460a12eac9..fd4716e993 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverter.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverter.java
@@ -17,19 +17,19 @@
 
 package org.apache.ignite.internal.sql.engine.prepare.ddl;
 
-import static java.util.function.Function.identity;
-import static java.util.stream.Collectors.toUnmodifiableMap;
 import static org.apache.calcite.rel.type.RelDataType.PRECISION_NOT_SPECIFIED;
 import static org.apache.calcite.rel.type.RelDataType.SCALE_NOT_SPECIFIED;
 import static org.apache.ignite.internal.lang.IgniteStringFormatter.format;
+import static org.apache.ignite.internal.sql.engine.prepare.ddl.TableOptionEnum.PRIMARY_ZONE;
+import static org.apache.ignite.internal.sql.engine.prepare.ddl.TableOptionEnum.STORAGE_PROFILE;
 import static org.apache.ignite.internal.sql.engine.prepare.ddl.ZoneOptionEnum.AFFINITY_FUNCTION;
 import static org.apache.ignite.internal.sql.engine.prepare.ddl.ZoneOptionEnum.DATA_NODES_AUTO_ADJUST;
 import static org.apache.ignite.internal.sql.engine.prepare.ddl.ZoneOptionEnum.DATA_NODES_AUTO_ADJUST_SCALE_DOWN;
 import static org.apache.ignite.internal.sql.engine.prepare.ddl.ZoneOptionEnum.DATA_NODES_AUTO_ADJUST_SCALE_UP;
 import static org.apache.ignite.internal.sql.engine.prepare.ddl.ZoneOptionEnum.DATA_NODES_FILTER;
-import static org.apache.ignite.internal.sql.engine.prepare.ddl.ZoneOptionEnum.DATA_STORAGE_ENGINE;
 import static org.apache.ignite.internal.sql.engine.prepare.ddl.ZoneOptionEnum.PARTITIONS;
 import static org.apache.ignite.internal.sql.engine.prepare.ddl.ZoneOptionEnum.REPLICAS;
+import static org.apache.ignite.internal.sql.engine.prepare.ddl.ZoneOptionEnum.STORAGE_PROFILES;
 import static org.apache.ignite.internal.sql.engine.util.IgniteMath.convertToByteExact;
 import static org.apache.ignite.internal.sql.engine.util.IgniteMath.convertToIntExact;
 import static org.apache.ignite.internal.sql.engine.util.IgniteMath.convertToShortExact;
@@ -44,20 +44,17 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
 import java.time.Period;
-import java.util.AbstractMap.SimpleEntry;
 import java.util.ArrayList;
 import java.util.EnumMap;
 import java.util.EnumSet;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Objects;
 import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Function;
-import java.util.function.Supplier;
 import java.util.stream.Collectors;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.runtime.CalciteContextException;
@@ -119,20 +116,8 @@ import org.jetbrains.annotations.Nullable;
  */
 // TODO: IGNITE-15859 Add documentation
 public class DdlSqlToCommandConverter {
-    private final Supplier<String> defaultDataStorageSupplier;
-
-    /**
-     * Mapping: Data storage ID -> data storage name.
-     *
-     * <p>Example for "rocksdb": {@code Map.of("ROCKSDB", "rocksdb")}.
-     */
-    private final Map<String, String> dataStorageNames;
-
     /** Mapping: Table option ID -> DDL option info. */
-    private final Map<String, DdlOptionInfo<CreateTableCommand, ?>> tableOptionInfos;
-
-    /** Like {@link #tableOptionInfos}, but for each data storage name. */
-    private final Map<String, Map<String, DdlOptionInfo<CreateZoneCommand, ?>>> dataStorageOptionInfos;
+    private final Map<TableOptionEnum, DdlOptionInfo<CreateTableCommand, ?>> tableOptionInfos;
 
     /** Mapping: Zone option ID -> DDL option info. */
     private final Map<ZoneOptionEnum, DdlOptionInfo<CreateZoneCommand, ?>> zoneOptionInfos;
@@ -145,37 +130,17 @@ public class DdlSqlToCommandConverter {
 
     /**
      * Constructor.
-     *
-     * @param dataStorageFields Data storage fields. Mapping: Data storage name -> field name -> field type.
-     * @param defaultDataStorageSupplier Default data storage supplier.
      */
-    public DdlSqlToCommandConverter(
-            Map<String, Map<String, Class<?>>> dataStorageFields,
-            Supplier<String> defaultDataStorageSupplier
-    ) {
-        this.defaultDataStorageSupplier = defaultDataStorageSupplier;
-
+    public DdlSqlToCommandConverter() {
         knownZoneOptionNames = EnumSet.allOf(ZoneOptionEnum.class)
                 .stream()
                 .map(Enum::name)
                 .collect(Collectors.toSet());
 
-        this.dataStorageNames = collectDataStorageNames(dataStorageFields.keySet());
-
-        this.tableOptionInfos = Map.of(
-                "PRIMARY_ZONE", new DdlOptionInfo<>(String.class, null, CreateTableCommand::zone)
-        );
-
-        this.dataStorageOptionInfos = dataStorageFields.entrySet()
-                .stream()
-                .collect(toUnmodifiableMap(
-                        Entry::getKey,
-                        e0 -> e0.getValue().entrySet().stream()
-                                .map(this::dataStorageFieldOptionInfo)
-                                .collect(toUnmodifiableMap(k -> k.getKey().toUpperCase(), Entry::getValue))
-                ));
-
-        dataStorageOptionInfos.values().forEach(v -> checkDuplicates(v.keySet(), tableOptionInfos.keySet()));
+        this.tableOptionInfos = new EnumMap<>(Map.of(
+                PRIMARY_ZONE, new DdlOptionInfo<>(String.class, null, CreateTableCommand::zone),
+                STORAGE_PROFILE, new DdlOptionInfo<>(String.class, this::checkEmptyString, CreateTableCommand::storageProfile)
+        ));
 
         // CREATE ZONE options.
         zoneOptionInfos = new EnumMap<>(Map.of(
@@ -183,14 +148,13 @@ public class DdlSqlToCommandConverter {
                 PARTITIONS, new DdlOptionInfo<>(Integer.class, this::checkPositiveNumber, CreateZoneCommand::partitions),
                 AFFINITY_FUNCTION, new DdlOptionInfo<>(String.class, null, CreateZoneCommand::affinity),
                 DATA_NODES_FILTER, new DdlOptionInfo<>(String.class, null, CreateZoneCommand::nodeFilter),
-
                 DATA_NODES_AUTO_ADJUST,
                 new DdlOptionInfo<>(Integer.class, this::checkPositiveNumber, CreateZoneCommand::dataNodesAutoAdjust),
                 DATA_NODES_AUTO_ADJUST_SCALE_UP,
                 new DdlOptionInfo<>(Integer.class, this::checkPositiveNumber, CreateZoneCommand::dataNodesAutoAdjustScaleUp),
                 DATA_NODES_AUTO_ADJUST_SCALE_DOWN,
                 new DdlOptionInfo<>(Integer.class, this::checkPositiveNumber, CreateZoneCommand::dataNodesAutoAdjustScaleDown),
-                DATA_STORAGE_ENGINE, new DdlOptionInfo<>(String.class, null, CreateZoneCommand::dataStorage)
+                STORAGE_PROFILES, new DdlOptionInfo<>(String.class, this::checkEmptyString, CreateZoneCommand::storageProfiles)
         ));
 
         // ALTER ZONE options.
@@ -198,7 +162,6 @@ public class DdlSqlToCommandConverter {
                 REPLICAS, new DdlOptionInfo<>(Integer.class, this::checkPositiveNumber, AlterZoneSetCommand::replicas),
                 PARTITIONS, new DdlOptionInfo<>(Integer.class, this::checkPositiveNumber, AlterZoneSetCommand::partitions),
                 DATA_NODES_FILTER, new DdlOptionInfo<>(String.class, null, AlterZoneSetCommand::nodeFilter),
-
                 DATA_NODES_AUTO_ADJUST,
                 new DdlOptionInfo<>(Integer.class, this::checkPositiveNumber, AlterZoneSetCommand::dataNodesAutoAdjust),
                 DATA_NODES_AUTO_ADJUST_SCALE_UP,
@@ -290,11 +253,11 @@ public class DdlSqlToCommandConverter {
 
                 String optionKey = option.key().getSimple().toUpperCase();
 
-                DdlOptionInfo<CreateTableCommand, ?> tblOptionInfo = tableOptionInfos.get(optionKey);
+                try {
+                    DdlOptionInfo<CreateTableCommand, ?> tblOptionInfo = tableOptionInfos.get(TableOptionEnum.valueOf(optionKey));
 
-                if (tblOptionInfo != null) {
                     updateCommandOption("Table", optionKey, option.value(), tblOptionInfo, ctx.query(), createTblCmd);
-                } else {
+                } catch (IllegalArgumentException ignored) {
                     throw new SqlException(
                             STMT_VALIDATION_ERR, String.format("Unexpected table option [option=%s, query=%s]", optionKey, ctx.query()));
                 }
@@ -579,19 +542,15 @@ public class DdlSqlToCommandConverter {
      */
     private CreateZoneCommand convertCreateZone(IgniteSqlCreateZone createZoneNode, PlanningContext ctx) {
         CreateZoneCommand createZoneCmd = new CreateZoneCommand();
-        String dataStorageName = deriveDataStorage(createZoneNode.engineName(), ctx);
 
         createZoneCmd.schemaName(deriveSchemaName(createZoneNode.name(), ctx));
         createZoneCmd.zoneName(deriveObjectName(createZoneNode.name(), ctx, "zoneName"));
         createZoneCmd.ifNotExists(createZoneNode.ifNotExists());
-        createZoneCmd.dataStorage(dataStorageName);
 
         if (createZoneNode.createOptionList() == null) {
-            return createZoneCmd;
+            throw new SqlException(STMT_VALIDATION_ERR, STORAGE_PROFILES + " option cannot be null");
         }
 
-        Map<String, DdlOptionInfo<CreateZoneCommand, ?>> dsOptInfos = dataStorageOptionInfos.get(dataStorageName);
-
         Set<String> remainingKnownOptions = new HashSet<>(knownZoneOptionNames);
 
         for (SqlNode optionNode : createZoneNode.createOptionList().getList()) {
@@ -601,14 +560,12 @@ public class DdlSqlToCommandConverter {
 
             String optionName = option.key().getSimple().toUpperCase();
 
-            DdlOptionInfo<CreateZoneCommand, ?> zoneOptionInfo;
+            DdlOptionInfo<CreateZoneCommand, ?> zoneOptionInfo = null;
 
             if (remainingKnownOptions.remove(optionName)) {
                 zoneOptionInfo = zoneOptionInfos.get(ZoneOptionEnum.valueOf(optionName));
             } else if (knownZoneOptionNames.contains(optionName)) {
                 throw duplicateZoneOption(ctx, optionName);
-            } else {
-                zoneOptionInfo = dsOptInfos != null ? dsOptInfos.get(optionName) : null;
             }
 
             if (zoneOptionInfo == null) {
@@ -618,6 +575,10 @@ public class DdlSqlToCommandConverter {
             updateCommandOption("Zone", optionName, (SqlLiteral) option.value(), zoneOptionInfo, ctx.query(), createZoneCmd);
         }
 
+        if (createZoneCmd.storageProfiles() == null) {
+            throw new SqlException(STMT_VALIDATION_ERR, STORAGE_PROFILES + " option cannot be null");
+        }
+
         return createZoneCmd;
     }
 
@@ -752,18 +713,6 @@ public class DdlSqlToCommandConverter {
         }
     }
 
-    /**
-     * Collects a mapping of the ID of the data storage to a name.
-     *
-     * <p>Example: {@code collectDataStorageNames(Set.of("rocksdb"))} -> {@code Map.of("ROCKSDB", "rocksdb")}.
-     *
-     * @param dataStorages Names of the data storages.
-     * @throws IllegalStateException If there is a duplicate ID.
-     */
-    static Map<String, String> collectDataStorageNames(Set<String> dataStorages) {
-        return dataStorages.stream().collect(toUnmodifiableMap(String::toUpperCase, identity()));
-    }
-
     /**
      * Checks that there are no ID duplicates.
      *
@@ -779,27 +728,6 @@ public class DdlSqlToCommandConverter {
         }
     }
 
-    private String deriveDataStorage(@Nullable SqlIdentifier engineName, PlanningContext ctx) {
-        if (engineName == null) {
-            String defaultDataStorage = defaultDataStorageSupplier.get();
-
-            return defaultDataStorage;
-        }
-
-        assert engineName.isSimple() : engineName;
-
-        String dataStorage = engineName.getSimple().toUpperCase();
-
-        if (!dataStorageNames.containsKey(dataStorage)) {
-            throw new SqlException(STMT_VALIDATION_ERR, String.format(
-                    "Unexpected data storage engine [engine=%s, expected=%s, query=%s]",
-                    dataStorage, dataStorageNames, ctx.query()
-            ));
-        }
-
-        return dataStorageNames.get(dataStorage);
-    }
-
     private <S, T> void updateCommandOption(
             String sqlObjName,
             Object optId,
@@ -879,11 +807,10 @@ public class DdlSqlToCommandConverter {
         }
     }
 
-    private Entry<String, DdlOptionInfo<CreateZoneCommand, ?>> dataStorageFieldOptionInfo(Entry<String, Class<?>> e) {
-        return new SimpleEntry<>(
-                e.getKey(),
-                new DdlOptionInfo<>(e.getValue(), null, (cmd, o) -> cmd.addDataStorageOption(e.getKey(), o))
-        );
+    private void checkEmptyString(String string) {
+        if (string.isEmpty()) {
+            throw new SqlException(STMT_VALIDATION_ERR, "String cannot be empty");
+        }
     }
 
     private Type convertIndexType(IgniteSqlIndexType type) {
diff --git a/modules/api/src/main/java/org/apache/ignite/catalog/ZoneEngine.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/TableOptionEnum.java
similarity index 76%
copy from modules/api/src/main/java/org/apache/ignite/catalog/ZoneEngine.java
copy to modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/TableOptionEnum.java
index 4e33a6d770..4f477141f1 100644
--- a/modules/api/src/main/java/org/apache/ignite/catalog/ZoneEngine.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/TableOptionEnum.java
@@ -15,11 +15,15 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.catalog;
+package org.apache.ignite.internal.sql.engine.prepare.ddl;
 
 /**
- * Engine to use for distribution zone.
+ * Enumerates the options for CREATE TABLE and ALTER TABLE statements.
  */
-public enum ZoneEngine {
-    AIMEM, ROCKSDB, DEFAULT
+public enum TableOptionEnum {
+    /** Primary zone. */
+    PRIMARY_ZONE,
+
+    /** Storage profile. */
+    STORAGE_PROFILE
 }
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/ZoneOptionEnum.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/ZoneOptionEnum.java
index 60294ff51d..a6c94f4365 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/ZoneOptionEnum.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/ZoneOptionEnum.java
@@ -42,6 +42,6 @@ public enum ZoneOptionEnum {
     /** Data nodes scale down auto adjust timeout. */
     DATA_NODES_AUTO_ADJUST_SCALE_DOWN,
 
-    /** Data storage engine. */
-    DATA_STORAGE_ENGINE
+    /** Storage profiles. */
+    STORAGE_PROFILES
 }
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlCreateZone.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlCreateZone.java
index 2aedf2f40c..ea8e3be7e9 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlCreateZone.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlCreateZone.java
@@ -50,14 +50,12 @@ public class IgniteSqlCreateZone extends SqlCreate {
                 SqlParserPos pos, @Nullable SqlNode... operands) {
 
             return new IgniteSqlCreateZone(pos, existFlag(), (SqlIdentifier) operands[0],
-                    (SqlNodeList) operands[1], (SqlIdentifier) operands[2]);
+                    (SqlNodeList) operands[1]);
         }
     }
 
     private final SqlIdentifier name;
 
-    private final @Nullable SqlIdentifier engineName;
-
     private final @Nullable SqlNodeList createOptionList;
 
     /** Creates a SqlCreateZone. */
@@ -65,16 +63,12 @@ public class IgniteSqlCreateZone extends SqlCreate {
             SqlParserPos pos,
             boolean ifNotExists,
             SqlIdentifier name,
-            @Nullable SqlNodeList createOptionList,
-            @Nullable SqlIdentifier engineName
+            @Nullable SqlNodeList createOptionList
     ) {
         super(new Operator(ifNotExists), pos, false, ifNotExists);
 
-        assert engineName == null || engineName.isSimple() : engineName;
-
         this.name = Objects.requireNonNull(name, "name");
         this.createOptionList = createOptionList;
-        this.engineName = engineName;
     }
 
     /** {@inheritDoc} */
@@ -87,7 +81,7 @@ public class IgniteSqlCreateZone extends SqlCreate {
     @SuppressWarnings("nullness")
     @Override
     public List<SqlNode> getOperandList() {
-        return ImmutableNullableList.of(name, createOptionList, engineName);
+        return ImmutableNullableList.of(name, createOptionList);
     }
 
     /** {@inheritDoc} */
@@ -101,12 +95,6 @@ public class IgniteSqlCreateZone extends SqlCreate {
 
         name.unparse(writer, leftPrec, rightPrec);
 
-        if (engineName != null) {
-            writer.keyword("ENGINE");
-
-            engineName.unparse(writer, 0, 0);
-        }
-
         if (createOptionList != null) {
             writer.keyword("WITH");
 
@@ -134,11 +122,4 @@ public class IgniteSqlCreateZone extends SqlCreate {
     public boolean ifNotExists() {
         return ifNotExists;
     }
-
-    /**
-     * Returns an engine name of the zone to create.
-     */
-    public @Nullable SqlIdentifier engineName() {
-        return engineName;
-    }
 }
diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/ddl/DdlCommandHandlerExceptionHandlingTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/ddl/DdlCommandHandlerExceptionHandlingTest.java
index 0042f4c583..49e01972fc 100644
--- a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/ddl/DdlCommandHandlerExceptionHandlingTest.java
+++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/ddl/DdlCommandHandlerExceptionHandlingTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.sql.engine.exec.ddl;
 
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.catalog.CatalogTestUtils.createTestCatalogManager;
 import static org.apache.ignite.internal.distributionzones.DistributionZonesTestUtil.createZone;
 import static org.apache.ignite.internal.testframework.matchers.CompletableFutureExceptionMatcher.willThrow;
@@ -98,6 +99,7 @@ public class DdlCommandHandlerExceptionHandlingTest extends IgniteAbstractTest {
 
         CreateZoneCommand cmd = new CreateZoneCommand();
         cmd.zoneName(ZONE_NAME);
+        cmd.storageProfiles(DEFAULT_STORAGE_PROFILE);
         cmd.ifNotExists(ifNotExists);
 
         return commandHandler.handle(cmd);
diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/ddl/DistributionZoneDdlCommandHandlerTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/ddl/DistributionZoneDdlCommandHandlerTest.java
index c06addb691..a308596bbc 100644
--- a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/ddl/DistributionZoneDdlCommandHandlerTest.java
+++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/ddl/DistributionZoneDdlCommandHandlerTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.sql.engine.exec.ddl;
 
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully;
 import static org.apache.ignite.internal.util.CompletableFutures.nullCompletedFuture;
 import static org.hamcrest.MatcherAssert.assertThat;
@@ -58,6 +59,7 @@ public class DistributionZoneDdlCommandHandlerTest extends IgniteAbstractTest {
     public void testCreateZone() {
         CreateZoneCommand cmd = new CreateZoneCommand();
         cmd.zoneName(ZONE_NAME);
+        cmd.storageProfiles(DEFAULT_STORAGE_PROFILE);
 
         invokeHandler(cmd);
 
diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/rel/TableScanNodeExecutionTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/rel/TableScanNodeExecutionTest.java
index 9afaa4e1fd..7e2e9ffd60 100644
--- a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/rel/TableScanNodeExecutionTest.java
+++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/rel/TableScanNodeExecutionTest.java
@@ -17,7 +17,7 @@
 
 package org.apache.ignite.internal.sql.engine.exec.rel;
 
-import static org.apache.ignite.internal.replicator.ReplicaManager.DEFAULT_IDLE_SAFE_TIME_PROPAGATION_PERIOD_MILLISECONDS;
+import static org.apache.ignite.internal.replicator.ReplicatorConstants.DEFAULT_IDLE_SAFE_TIME_PROPAGATION_PERIOD_MILLISECONDS;
 import static org.apache.ignite.internal.sql.engine.util.TypeUtils.rowSchemaFromRelTypes;
 import static org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully;
 import static org.apache.ignite.internal.util.IgniteUtils.closeAll;
diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/TestBuilders.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/TestBuilders.java
index 6c224e33f2..1df154c968 100644
--- a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/TestBuilders.java
+++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/TestBuilders.java
@@ -621,7 +621,7 @@ public class TestBuilders {
 
             var parserService = new ParserServiceImpl();
             var prepareService = new PrepareServiceImpl(clusterName, 0, CaffeineCacheFactory.INSTANCE,
-                    new DdlSqlToCommandConverter(Map.of(), () -> "aipersist"), PLANNING_TIMEOUT, PLANNING_THREAD_COUNT,
+                    new DdlSqlToCommandConverter(), PLANNING_TIMEOUT, PLANNING_THREAD_COUNT,
                     mock(MetricManager.class));
 
             Map<String, List<String>> owningNodesByTableName = new HashMap<>();
@@ -663,7 +663,7 @@ public class TestBuilders {
                             String nodeNameSep = SystemViewManagerImpl.NODE_ATTRIBUTES_LIST_SEPARATOR;
                             String nodeNamesString = String.join(nodeNameSep, systemViewForNode);
 
-                            return new LogicalNode(logicalNode, Map.of(), Map.of(attrName, nodeNamesString), Map.of());
+                            return new LogicalNode(logicalNode, Map.of(), Map.of(attrName, nodeNamesString), List.of());
                         }
                     })
                     .collect(Collectors.toList());
diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/AbstractDdlSqlToCommandConverterTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/AbstractDdlSqlToCommandConverterTest.java
index 52aa0fcaa1..0fa1d28165 100644
--- a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/AbstractDdlSqlToCommandConverterTest.java
+++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/AbstractDdlSqlToCommandConverterTest.java
@@ -21,7 +21,6 @@ import static org.apache.calcite.tools.Frameworks.newConfigBuilder;
 import static org.apache.ignite.internal.sql.engine.util.Commons.FRAMEWORK_CONFIG;
 
 import java.util.List;
-import java.util.Map;
 import java.util.UUID;
 import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql.parser.SqlParseException;
@@ -39,7 +38,7 @@ import org.apache.ignite.internal.testframework.BaseIgniteAbstractTest;
  */
 class AbstractDdlSqlToCommandConverterTest extends BaseIgniteAbstractTest {
     /** DDL SQL to command converter. */
-    DdlSqlToCommandConverter converter = new DdlSqlToCommandConverter(Map.of(), () -> "default");
+    DdlSqlToCommandConverter converter = new DdlSqlToCommandConverter();
 
     /**
      * Parses a given statement and returns a resulting AST.
diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverterTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverterTest.java
index 95b66ced76..74a038f1b1 100644
--- a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverterTest.java
+++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverterTest.java
@@ -23,9 +23,9 @@ import static org.apache.calcite.sql.type.SqlTypeName.FLOAT;
 import static org.apache.calcite.sql.type.SqlTypeName.INTERVAL_TYPES;
 import static org.apache.calcite.sql.type.SqlTypeName.NUMERIC_TYPES;
 import static org.apache.calcite.sql.type.SqlTypeName.REAL;
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.lang.IgniteStringFormatter.format;
 import static org.apache.ignite.internal.sql.engine.prepare.ddl.DdlSqlToCommandConverter.checkDuplicates;
-import static org.apache.ignite.internal.sql.engine.prepare.ddl.DdlSqlToCommandConverter.collectDataStorageNames;
 import static org.apache.ignite.internal.sql.engine.util.SqlTestUtils.assertThrowsSqlException;
 import static org.apache.ignite.internal.sql.engine.util.SqlTestUtils.generateValueByType;
 import static org.apache.ignite.internal.sql.engine.util.TypeUtils.columnType;
@@ -35,7 +35,6 @@ import static org.hamcrest.CoreMatchers.instanceOf;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.allOf;
 import static org.hamcrest.Matchers.containsString;
-import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.hasItem;
 import static org.hamcrest.Matchers.hasSize;
 import static org.hamcrest.Matchers.startsWith;
@@ -54,7 +53,6 @@ import java.time.Period;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 import java.util.UUID;
@@ -90,33 +88,6 @@ import org.junit.jupiter.params.provider.ValueSource;
  * For {@link DdlSqlToCommandConverter} testing.
  */
 public class DdlSqlToCommandConverterTest extends AbstractDdlSqlToCommandConverterTest {
-    @Test
-    void testCollectDataStorageNames() {
-        assertThat(collectDataStorageNames(Set.of()), equalTo(Map.of()));
-
-        assertThat(
-                collectDataStorageNames(Set.of("rocksdb")),
-                equalTo(Map.of("ROCKSDB", "rocksdb"))
-        );
-
-        assertThat(
-                collectDataStorageNames(Set.of("ROCKSDB")),
-                equalTo(Map.of("ROCKSDB", "ROCKSDB"))
-        );
-
-        assertThat(
-                collectDataStorageNames(Set.of("rocksDb", "pageMemory")),
-                equalTo(Map.of("ROCKSDB", "rocksDb", "PAGEMEMORY", "pageMemory"))
-        );
-
-        IllegalStateException exception = assertThrows(
-                IllegalStateException.class,
-                () -> collectDataStorageNames(Set.of("rocksdb", "rocksDb"))
-        );
-
-        assertThat(exception.getMessage(), startsWith("Duplicate key"));
-    }
-
     @Test
     void testCheckDuplicates() {
         IllegalStateException exception = assertThrows(
@@ -138,7 +109,7 @@ public class DdlSqlToCommandConverterTest extends AbstractDdlSqlToCommandConvert
 
     @Test
     public void tableWithoutPkShouldThrowErrorWhenSysPropDefault() throws SqlParseException {
-        var node = parse("CREATE TABLE t (val int)");
+        var node = parse("CREATE TABLE t (val int) WITH STORAGE_PROFILE='" + DEFAULT_STORAGE_PROFILE + "'");
 
         assertThat(node, instanceOf(SqlDdl.class));
 
@@ -153,7 +124,7 @@ public class DdlSqlToCommandConverterTest extends AbstractDdlSqlToCommandConvert
     @Test
     @WithSystemProperty(key = "IMPLICIT_PK_ENABLED", value = "false")
     public void tableWithoutPkShouldThrowErrorWhenSysPropDisabled() throws SqlParseException {
-        var node = parse("CREATE TABLE t (val int)");
+        var node = parse("CREATE TABLE t (val int) WITH STORAGE_PROFILE='" + DEFAULT_STORAGE_PROFILE + "'");
 
         assertThat(node, instanceOf(SqlDdl.class));
 
@@ -168,7 +139,7 @@ public class DdlSqlToCommandConverterTest extends AbstractDdlSqlToCommandConvert
     @Test
     @WithSystemProperty(key = "IMPLICIT_PK_ENABLED", value = "true")
     public void tableWithoutPkShouldInjectImplicitPkWhenSysPropEnabled() throws SqlParseException {
-        var node = parse("CREATE TABLE t (val int)");
+        var node = parse("CREATE TABLE t (val int) WITH STORAGE_PROFILE='" + DEFAULT_STORAGE_PROFILE + "'");
 
         assertThat(node, instanceOf(SqlDdl.class));
 
@@ -595,7 +566,8 @@ public class DdlSqlToCommandConverterTest extends AbstractDdlSqlToCommandConvert
 
     @Test
     public void tableWithAutogenPkColumn() throws SqlParseException {
-        var node = parse("CREATE TABLE t (id varchar default gen_random_uuid primary key, val int)");
+        var node = parse("CREATE TABLE t (id varchar default gen_random_uuid primary key, val int) WITH STORAGE_PROFILE='"
+                + DEFAULT_STORAGE_PROFILE + "'");
 
         assertThat(node, instanceOf(SqlDdl.class));
 
@@ -621,6 +593,31 @@ public class DdlSqlToCommandConverterTest extends AbstractDdlSqlToCommandConvert
         );
     }
 
+    @Test
+    public void tableWithoutStorageProfileShouldThrowError() throws SqlParseException {
+        var node = parse("CREATE TABLE t (val int) with storage_profile=''");
+
+        assertThat(node, instanceOf(SqlDdl.class));
+
+        var ex = assertThrows(
+                IgniteException.class,
+                () -> converter.convert((SqlDdl) node, createContext())
+        );
+
+        assertThat(ex.getMessage(), containsString("String cannot be empty"));
+
+        var newNode = parse("CREATE TABLE t (val int) WITH PRIMARY_ZONE='ZONE', storage_profile=''");
+
+        assertThat(node, instanceOf(SqlDdl.class));
+
+        ex = assertThrows(
+                IgniteException.class,
+                () -> converter.convert((SqlDdl) newNode, createContext())
+        );
+
+        assertThat(ex.getMessage(), containsString("String cannot be empty"));
+    }
+
     private static Matcher<ColumnDefinition> columnThat(String description, Function<ColumnDefinition, Boolean> checker) {
         return new CustomMatcher<>(description) {
             @Override
diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DistributionZoneSqlToCommandConverterTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DistributionZoneSqlToCommandConverterTest.java
index 6d444f0dce..f53f391838 100644
--- a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DistributionZoneSqlToCommandConverterTest.java
+++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DistributionZoneSqlToCommandConverterTest.java
@@ -17,7 +17,9 @@
 
 package org.apache.ignite.internal.sql.engine.prepare.ddl;
 
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.lang.IgniteStringFormatter.format;
+import static org.apache.ignite.internal.sql.engine.prepare.ddl.ZoneOptionEnum.STORAGE_PROFILES;
 import static org.hamcrest.CoreMatchers.instanceOf;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
@@ -47,11 +49,15 @@ public class DistributionZoneSqlToCommandConverterTest extends AbstractDdlSqlToC
     private static final List<String> NUMERIC_OPTIONS = Arrays.asList("PARTITIONS", "REPLICAS", "DATA_NODES_AUTO_ADJUST",
             "DATA_NODES_AUTO_ADJUST_SCALE_UP", "DATA_NODES_AUTO_ADJUST_SCALE_DOWN");
 
-    private static final List<String> STRING_OPTIONS = Arrays.asList("AFFINITY_FUNCTION", "DATA_NODES_FILTER", "DATA_STORAGE_ENGINE");
+    private static final List<String> STRING_OPTIONS = Arrays.asList(
+            "AFFINITY_FUNCTION",
+            "DATA_NODES_FILTER",
+            "STORAGE_PROFILES"
+    );
 
     @Test
     public void testCreateZone() throws SqlParseException {
-        SqlNode node = parse("CREATE ZONE test");
+        SqlNode node = parse("CREATE ZONE test WITH STORAGE_PROFILES='" + DEFAULT_STORAGE_PROFILE + "'");
 
         assertThat(node, instanceOf(SqlDdl.class));
 
@@ -73,7 +79,9 @@ public class DistributionZoneSqlToCommandConverterTest extends AbstractDdlSqlToC
                 + "data_nodes_filter='\"attr1\" && \"attr2\"', "
                 + "data_nodes_auto_adjust_scale_up=100, "
                 + "data_nodes_auto_adjust_scale_down=200, "
-                + "data_nodes_auto_adjust=300");
+                + "data_nodes_auto_adjust=300, "
+                + "storage_profiles='lru_rocks, segmented_aipersist' "
+        );
 
         assertThat(node, instanceOf(SqlDdl.class));
 
@@ -88,6 +96,7 @@ public class DistributionZoneSqlToCommandConverterTest extends AbstractDdlSqlToC
         assertThat(createZone.dataNodesAutoAdjustScaleUp(), equalTo(100));
         assertThat(createZone.dataNodesAutoAdjustScaleDown(), equalTo(200));
         assertThat(createZone.dataNodesAutoAdjust(), equalTo(300));
+        assertThat(createZone.storageProfiles(), equalTo("lru_rocks, segmented_aipersist"));
 
         // Check option validation.
         node = parse("CREATE ZONE test with partitions=-1");
@@ -95,6 +104,34 @@ public class DistributionZoneSqlToCommandConverterTest extends AbstractDdlSqlToC
 
         node = parse("CREATE ZONE test with replicas=-1");
         expectOptionValidationError((SqlDdl) node, "REPLICAS");
+
+        node = parse("CREATE ZONE test with storage_profiles='' ");
+        expectOptionValidationError((SqlDdl) node, "STORAGE_PROFILES");
+    }
+
+    @Test
+    public void testCreateZoneWithoutStorageProfileOptionShouldThrowError() throws SqlParseException {
+        SqlNode node =  parse("CREATE ZONE test");
+
+        assertThat(node, instanceOf(SqlDdl.class));
+
+        var ex = assertThrows(
+                IgniteException.class,
+                () -> converter.convert((SqlDdl) node, createContext())
+        );
+
+        assertThat(ex.getMessage(), containsString(STORAGE_PROFILES + " option cannot be null"));
+
+        SqlNode newNode =  parse("CREATE ZONE test with replicas=1");
+
+        assertThat(newNode, instanceOf(SqlDdl.class));
+
+        ex = assertThrows(
+                IgniteException.class,
+                () -> converter.convert((SqlDdl) newNode, createContext())
+        );
+
+        assertThat(ex.getMessage(), containsString(STORAGE_PROFILES + " option cannot be null"));
     }
 
     @Test
diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/schema/SqlSchemaManagerImplTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/schema/SqlSchemaManagerImplTest.java
index 9a5b496259..6e3708a0f8 100644
--- a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/schema/SqlSchemaManagerImplTest.java
+++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/schema/SqlSchemaManagerImplTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.sql.engine.schema;
 
+import static org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
 import static org.apache.ignite.internal.sql.engine.util.TypeUtils.columnType2NativeType;
 import static org.apache.ignite.internal.testframework.IgniteTestUtils.assertThrowsWithCause;
 import static org.apache.ignite.internal.testframework.IgniteTestUtils.await;
@@ -59,6 +60,7 @@ import org.apache.ignite.internal.catalog.commands.CreateZoneCommand;
 import org.apache.ignite.internal.catalog.commands.DefaultValue;
 import org.apache.ignite.internal.catalog.commands.MakeIndexAvailableCommand;
 import org.apache.ignite.internal.catalog.commands.StartBuildingIndexCommand;
+import org.apache.ignite.internal.catalog.commands.StorageProfileParams;
 import org.apache.ignite.internal.catalog.commands.TableHashPrimaryKey;
 import org.apache.ignite.internal.catalog.commands.TablePrimaryKey;
 import org.apache.ignite.internal.catalog.commands.TableSortedPrimaryKey;
@@ -205,6 +207,7 @@ public class SqlSchemaManagerImplTest extends BaseIgniteAbstractTest {
         await(catalogManager.execute(CreateZoneCommand.builder()
                 .partitions(partitions)
                 .zoneName("ABC")
+                .storageProfilesParams(List.of(StorageProfileParams.builder().storageProfile(DEFAULT_STORAGE_PROFILE).build()))
                 .build())
         );
 
diff --git a/modules/sql-engine/src/test/resources/META-INF/services/org.apache.ignite.configuration.ConfigurationModule b/modules/sql-engine/src/test/resources/META-INF/services/org.apache.ignite.configuration.ConfigurationModule
deleted file mode 100644
index 43a08d979d..0000000000
--- a/modules/sql-engine/src/test/resources/META-INF/services/org.apache.ignite.configuration.ConfigurationModule
+++ /dev/null
@@ -1 +0,0 @@
-org.apache.ignite.internal.storage.impl.TestPersistStorageConfigurationModule
diff --git a/modules/storage-api/README.md b/modules/storage-api/README.md
index 4c942c15bc..f6895249b1 100644
--- a/modules/storage-api/README.md
+++ b/modules/storage-api/README.md
@@ -53,4 +53,4 @@ String dataRegion = dataStorageView.dateRegion();
 ```
 
 
-To get the data storage engine, you need to use `org.apache.ignite.internal.storage.DataStorageManager.engine(org.apache.ignite.configuration.schemas.store.DataStorageConfiguration)`.
\ No newline at end of file
+To get the data storage engine, you need to use `org.apache.ignite.internal.storage.DataStorageManager.engine(org.apache.ignite.configuration.schemas.store.DataStorageConfiguration)`.
diff --git a/modules/storage-api/build.gradle b/modules/storage-api/build.gradle
index 7332b094d6..bb4d866e5c 100644
--- a/modules/storage-api/build.gradle
+++ b/modules/storage-api/build.gradle
@@ -26,7 +26,6 @@ dependencies {
 
     implementation project(':ignite-api')
     implementation project(':ignite-schema')
-    implementation project(':ignite-distribution-zones')
     implementation project(':ignite-configuration')
     implementation project(":ignite-core")
     implementation project(":ignite-catalog")
@@ -38,7 +37,6 @@ dependencies {
     testAnnotationProcessor project(":ignite-configuration-annotation-processor")
     testImplementation project(':ignite-core')
     testImplementation project(':ignite-configuration')
-    testImplementation project(':ignite-distribution-zones')
     testImplementation project(':ignite-schema')
     testImplementation(testFixtures(project(':ignite-schema')))
     testImplementation(testFixtures(project(':ignite-core')))
@@ -52,7 +50,6 @@ dependencies {
 
     testFixturesImplementation project(':ignite-core')
     testFixturesImplementation project(':ignite-configuration')
-    testFixturesImplementation project(':ignite-distribution-zones')
     testFixturesImplementation project(':ignite-schema')
     testFixturesImplementation project(':ignite-api')
     testFixturesImplementation project(':ignite-catalog')
diff --git a/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/DataStorageManager.java b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/DataStorageManager.java
index 9576cfd893..67074211cb 100644
--- a/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/DataStorageManager.java
+++ b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/DataStorageManager.java
@@ -20,15 +20,12 @@ package org.apache.ignite.internal.storage;
 import static org.apache.ignite.internal.util.CompletableFutures.nullCompletedFuture;
 
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.concurrent.CompletableFuture;
-import java.util.function.Consumer;
-import org.apache.ignite.configuration.annotation.Value;
-import org.apache.ignite.internal.configuration.tree.ConfigurationSource;
-import org.apache.ignite.internal.configuration.tree.ConstructableTreeNode;
+import java.util.stream.Collectors;
 import org.apache.ignite.internal.manager.IgniteComponent;
-import org.apache.ignite.internal.schema.configuration.storage.DataStorageChange;
-import org.apache.ignite.internal.schema.configuration.storage.DataStorageConfigurationSchema;
+import org.apache.ignite.internal.storage.configurations.StorageConfiguration;
+import org.apache.ignite.internal.storage.configurations.StorageProfileConfiguration;
+import org.apache.ignite.internal.storage.configurations.StorageProfileView;
 import org.apache.ignite.internal.storage.engine.StorageEngine;
 import org.apache.ignite.internal.tostring.S;
 import org.apache.ignite.internal.util.IgniteUtils;
@@ -39,21 +36,32 @@ public class DataStorageManager implements IgniteComponent {
     /** Mapping: {@link DataStorageModule#name} -> {@link StorageEngine}. */
     private final Map<String, StorageEngine> engines;
 
+    /** Mapping: {@link StorageProfileConfiguration#name()} -> {@link StorageEngine#name()}. */
+    private Map<String, String> profilesToEngines;
+
+    /** Storage configuration. **/
+    private StorageConfiguration storageConfiguration;
+
     /**
      * Constructor.
      *
      * @param engines Storage engines unique by {@link DataStorageModule#name name}.
+     * @param storageConfiguration Storage configuration. Needed to extract the storage profiles configurations after start.
      */
-    public DataStorageManager(Map<String, StorageEngine> engines) {
+    public DataStorageManager(Map<String, StorageEngine> engines, StorageConfiguration storageConfiguration) {
         assert !engines.isEmpty();
 
         this.engines = engines;
+        this.storageConfiguration = storageConfiguration;
     }
 
     @Override
     public CompletableFuture<Void> start() throws StorageException {
         engines.values().forEach(StorageEngine::start);
 
+        profilesToEngines = storageConfiguration.value().profiles().stream()
+                .collect(Collectors.toMap(StorageProfileView::name, StorageProfileView::engine));
+
         return nullCompletedFuture();
     }
 
@@ -63,66 +71,17 @@ public class DataStorageManager implements IgniteComponent {
     }
 
     /**
-     * Returns the data storage engine by name, {@code null} if absent.
+     * Get storage engine by storage profile name.
      *
-     * @param name Storage engine name.
+     * @param storageProfile Name of storage profile.
+     * @return Storage engine of the input storage profile or {@code null} if storage profile is not exist on the current node.
      */
-    public @Nullable StorageEngine engine(String name) {
-        return engines.get(name);
-    }
+    public @Nullable StorageEngine engineByStorageProfile(String storageProfile) {
+        String engine = profilesToEngines.get(storageProfile);
 
-    /**
-     * Creates a consumer that will change the {@link DataStorageConfigurationSchema data storage}.
-     *
-     * @param dataStorage Data storage.
-     * @param values {@link Value Values} for the data storage. Mapping: field name -> field value.
-     */
-    // TODO: IGNITE-20263 Get rid of
-    public Consumer<DataStorageChange> zoneDataStorageConsumer(String dataStorage, Map<String, Object> values) {
-        ConfigurationSource configurationSource = new ConfigurationSource() {
-            /** {@inheritDoc} */
-            @Override
-            public String polymorphicTypeId(String fieldName) {
-                throw new UnsupportedOperationException("polymorphicTypeId");
-            }
-
-            /** {@inheritDoc} */
-            @Override
-            public void descend(ConstructableTreeNode node) {
-                for (Entry<String, Object> e : values.entrySet()) {
-                    assert e.getKey() != null;
-                    assert e.getValue() != null : e.getKey();
-
-                    ConfigurationSource leafSource = new ConfigurationSource() {
-                        /** {@inheritDoc} */
-                        @Override
-                        public <T> T unwrap(Class<T> clazz) {
-                            return clazz.cast(e.getValue());
-                        }
-
-                        /** {@inheritDoc} */
-                        @Override
-                        public void descend(ConstructableTreeNode node) {
-                            throw new UnsupportedOperationException("descend");
-                        }
-
-                        /** {@inheritDoc} */
-                        @Override
-                        public String polymorphicTypeId(String fieldName) {
-                            throw new UnsupportedOperationException("polymorphicTypeId");
-                        }
-                    };
-
-                    node.construct(e.getKey(), leafSource, true);
-                }
-            }
-        };
-
-        return zoneDataStorageChange -> {
-            zoneDataStorageChange.convert(dataStorage);
-
-            configurationSource.descend((ConstructableTreeNode) zoneDataStorageChange);
-        };
+        assert engine != null : "Unknown storage profile '" + storageProfile + "'";
+
+        return engines.get(engine);
     }
 
     @Override
diff --git a/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/DataStorageModule.java b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/DataStorageModule.java
index 8b0e95f11f..c62a0d3b0f 100644
--- a/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/DataStorageModule.java
+++ b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/DataStorageModule.java
@@ -22,7 +22,7 @@ import org.apache.ignite.internal.components.LogSyncer;
 import org.apache.ignite.internal.components.LongJvmPauseDetector;
 import org.apache.ignite.internal.configuration.ConfigurationRegistry;
 import org.apache.ignite.internal.failure.FailureProcessor;
-import org.apache.ignite.internal.schema.configuration.storage.DataStorageConfigurationSchema;
+import org.apache.ignite.internal.storage.configurations.StorageProfileConfiguration;
 import org.apache.ignite.internal.storage.engine.StorageEngine;
 import org.jetbrains.annotations.Nullable;
 
@@ -33,7 +33,7 @@ public interface DataStorageModule {
     /**
      * Returns the unique name of the data storage.
      *
-     * <p>Used to map {@link DataStorageConfigurationSchema#name} to {@link StorageEngine}.
+     * <p>Used to map {@link StorageProfileConfiguration#engine()} to {@link StorageEngine}.
      */
     String name();
 
diff --git a/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/DataStorageModules.java b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/DataStorageModules.java
index d76f65501c..4a2be7a0ed 100644
--- a/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/DataStorageModules.java
+++ b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/DataStorageModules.java
@@ -17,25 +17,17 @@
 
 package org.apache.ignite.internal.storage;
 
-import static java.util.function.Predicate.not;
-import static java.util.stream.Collectors.toList;
 import static java.util.stream.Collectors.toUnmodifiableMap;
 
-import java.lang.reflect.Field;
 import java.nio.file.Path;
-import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
-import java.util.stream.Stream;
-import org.apache.ignite.configuration.annotation.PolymorphicConfigInstance;
-import org.apache.ignite.configuration.annotation.Value;
 import org.apache.ignite.internal.components.LogSyncer;
 import org.apache.ignite.internal.components.LongJvmPauseDetector;
 import org.apache.ignite.internal.configuration.ConfigurationRegistry;
 import org.apache.ignite.internal.failure.FailureProcessor;
-import org.apache.ignite.internal.schema.configuration.storage.DataStorageConfigurationSchema;
 import org.apache.ignite.internal.storage.engine.StorageEngine;
 import org.jetbrains.annotations.Nullable;
 
@@ -49,8 +41,7 @@ public class DataStorageModules {
     /**
      * Constructor.
      *
-     * <p>Modules are expected to have a unique {@link DataStorageModule#name}
-     * equal to {@link DataStorageConfigurationSchema#name schema name}.
+     * <p>Modules are expected to have a unique {@link DataStorageModule#name}.
      *
      * @param dataStorageModules Data storage modules.
      * @throws IllegalStateException If the module is not correct.
@@ -106,74 +97,4 @@ public class DataStorageModules {
                 )
         ));
     }
-
-    /**
-     * Collects {@link DataStorageConfigurationSchema data storage schema} fields (with {@link Value}).
-     *
-     * @param polymorphicSchemaExtensions {@link PolymorphicConfigInstance Polymorphic schema extensions} that contain extensions of {@link
-     *      DataStorageConfigurationSchema}.
-     * @return Mapping: {@link DataStorageModule#name Data storage name} -> filed name -> field type.
-     * @throws IllegalStateException If the {@link DataStorageConfigurationSchema data storage schemas} are not valid.
-     */
-    public Map<String, Map<String, Class<?>>> collectSchemasFields(Collection<Class<?>> polymorphicSchemaExtensions) {
-        Map<String, Class<? extends DataStorageConfigurationSchema>> schemas = polymorphicSchemaExtensions.stream()
-                .filter(DataStorageConfigurationSchema.class::isAssignableFrom)
-                .collect(toUnmodifiableMap(
-                        schemaCls -> schemaName((Class<? extends DataStorageConfigurationSchema>) schemaCls),
-                        schemaCls -> (Class<? extends DataStorageConfigurationSchema>) schemaCls
-                ));
-
-        checkSchemas(modules, schemas);
-
-        return modules.entrySet().stream().collect(toUnmodifiableMap(
-                Entry::getKey,
-                e -> schemaValueFields(schemas.get(e.getKey()))
-        ));
-    }
-
-    private Map<String, Class<?>> schemaValueFields(Class<? extends DataStorageConfigurationSchema> dataStorageSchema) {
-        return Stream.of(dataStorageSchema.getDeclaredFields())
-                .filter(field -> field.isAnnotationPresent(Value.class))
-                .collect(toUnmodifiableMap(
-                        Field::getName,
-                        Field::getType
-                ));
-    }
-
-    private static String schemaName(Class<? extends DataStorageConfigurationSchema> dataStorageSchema) {
-        PolymorphicConfigInstance polymorphicConfigInstance = dataStorageSchema.getAnnotation(PolymorphicConfigInstance.class);
-
-        assert polymorphicConfigInstance != null : dataStorageSchema;
-
-        return polymorphicConfigInstance.value();
-    }
-
-    private static void checkSchemas(
-            Map<String, DataStorageModule> modules,
-            Map<String, Class<? extends DataStorageConfigurationSchema>> schemas
-    ) {
-        if (!modules.keySet().equals(schemas.keySet())) {
-            List<String> dataStorageWithoutSchema = modules.keySet().stream()
-                    .filter(not(schemas::containsKey))
-                    .collect(toList());
-
-            if (!dataStorageWithoutSchema.isEmpty()) {
-                throw new IllegalStateException(
-                        "Missing configuration schemas (DataStorageConfigurationSchema heir) for data storage engines: "
-                                + dataStorageWithoutSchema
-                );
-            }
-
-            List<Class<? extends DataStorageConfigurationSchema>> schemasWithoutDataStorages = schemas.entrySet().stream()
-                    .filter(e -> !modules.containsKey(e.getKey()))
-                    .map(Entry::getValue)
-                    .collect(toList());
-
-            if (!schemasWithoutDataStorages.isEmpty()) {
-                throw new IllegalStateException(
-                        "Missing data storage engines for schemas: " + schemasWithoutDataStorages
-                );
-            }
-        }
-    }
 }
diff --git a/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/impl/TestPersistStorageConfigurationModule.java b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/configurations/StorageConfigurationModule.java
similarity index 59%
rename from modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/impl/TestPersistStorageConfigurationModule.java
rename to modules/storage-api/src/main/java/org/apache/ignite/internal/storage/configurations/StorageConfigurationModule.java
index f94721acc0..4632ac1b71 100644
--- a/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/impl/TestPersistStorageConfigurationModule.java
+++ b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/configurations/StorageConfigurationModule.java
@@ -15,8 +15,9 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.storage.impl;
+package org.apache.ignite.internal.storage.configurations;
 
+import com.google.auto.service.AutoService;
 import java.util.Collection;
 import java.util.List;
 import org.apache.ignite.configuration.ConfigurationModule;
@@ -24,29 +25,19 @@ import org.apache.ignite.configuration.RootKey;
 import org.apache.ignite.configuration.annotation.ConfigurationType;
 
 /**
- * Configuration module for mock configuration {@link TestPersistStorageConfigurationSchema}.
- *
- * <p>Important: don't use @AutoService here,
- * because it will produce the collision between the real PersistentPageMemoryDataStorageConfigurationSchema
- * and the {@link TestPersistStorageConfigurationSchema} in the 'test' configuration of the current module
- * (because test configuration always depends on testFixtures and main configuration).
+ * Storages configuration module.
  */
-public class TestPersistStorageConfigurationModule implements ConfigurationModule {
+@AutoService(ConfigurationModule.class)
+public class StorageConfigurationModule implements ConfigurationModule {
     /** {@inheritDoc} */
     @Override
     public ConfigurationType type() {
-        return ConfigurationType.DISTRIBUTED;
+        return ConfigurationType.LOCAL;
     }
 
     /** {@inheritDoc} */
     @Override
     public Collection<RootKey<?, ?>> rootKeys() {
-        return List.of();
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public Collection<Class<?>> polymorphicSchemaExtensions() {
-        return List.of(TestPersistStorageConfigurationSchema.class);
+        return List.of(StorageConfiguration.KEY);
     }
 }
diff --git a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/configuration/StorageProfilesConfigurationSchema.java b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/configurations/StorageConfigurationSchema.java
similarity index 62%
rename from modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/configuration/StorageProfilesConfigurationSchema.java
rename to modules/storage-api/src/main/java/org/apache/ignite/internal/storage/configurations/StorageConfigurationSchema.java
index 0dea143ed0..8ba7fb3d2a 100644
--- a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/configuration/StorageProfilesConfigurationSchema.java
+++ b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/configurations/StorageConfigurationSchema.java
@@ -15,20 +15,30 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.cluster.management.configuration;
+package org.apache.ignite.internal.storage.configurations;
 
+import static org.apache.ignite.configuration.annotation.ConfigurationType.LOCAL;
+
+import org.apache.ignite.configuration.annotation.ConfigValue;
 import org.apache.ignite.configuration.annotation.ConfigurationRoot;
-import org.apache.ignite.configuration.annotation.ConfigurationType;
 import org.apache.ignite.configuration.annotation.NamedConfigValue;
 
 /**
- * TODO: add java doc https://issues.apache.org/jira/browse/IGNITE-20564.
+ * Root for the storage engine and storage profiles configurations.
  */
-@ConfigurationRoot(rootName = "storageProfiles", type = ConfigurationType.LOCAL)
-public class StorageProfilesConfigurationSchema {
+@ConfigurationRoot(rootName = "storage", type = LOCAL)
+public class StorageConfigurationSchema {
+
+    /**
+     * Storage engines configuration.
+     */
+    @ConfigValue
+    public StorageEngineConfigurationSchema engines;
+
     /**
-     * TODO: add java doc https://issues.apache.org/jira/browse/IGNITE-20564.
+     * Storage profiles configuration.
      */
     @NamedConfigValue
-    public StorageProfileConfigurationSchema storageProfiles;
+    public StorageProfileConfigurationSchema profiles;
+
 }
diff --git a/modules/api/src/main/java/org/apache/ignite/catalog/ZoneEngine.java b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/configurations/StorageEngineConfigurationSchema.java
similarity index 79%
rename from modules/api/src/main/java/org/apache/ignite/catalog/ZoneEngine.java
rename to modules/storage-api/src/main/java/org/apache/ignite/internal/storage/configurations/StorageEngineConfigurationSchema.java
index 4e33a6d770..4ba6576c79 100644
--- a/modules/api/src/main/java/org/apache/ignite/catalog/ZoneEngine.java
+++ b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/configurations/StorageEngineConfigurationSchema.java
@@ -15,11 +15,13 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.catalog;
+package org.apache.ignite.internal.storage.configurations;
+
+import org.apache.ignite.configuration.annotation.Config;
 
 /**
- * Engine to use for distribution zone.
+ * Storage engine configuration schema.
  */
-public enum ZoneEngine {
-    AIMEM, ROCKSDB, DEFAULT
+@Config
+public class StorageEngineConfigurationSchema {
 }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/storage/DataStorageConfigurationSchema.java b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/configurations/StorageProfileConfigurationSchema.java
similarity index 74%
rename from modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/storage/DataStorageConfigurationSchema.java
rename to modules/storage-api/src/main/java/org/apache/ignite/internal/storage/configurations/StorageProfileConfigurationSchema.java
index 9b124b48d2..7673405b87 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/storage/DataStorageConfigurationSchema.java
+++ b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/configurations/StorageProfileConfigurationSchema.java
@@ -15,18 +15,23 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.schema.configuration.storage;
+package org.apache.ignite.internal.storage.configurations;
 
+import org.apache.ignite.configuration.annotation.InjectedName;
 import org.apache.ignite.configuration.annotation.PolymorphicConfig;
 import org.apache.ignite.configuration.annotation.PolymorphicId;
 
 /**
- * Configuration schema for data storage.
+ * Storage profile configuration schema.
  */
-// TODO: IGNITE-20263 Get rid of
 @PolymorphicConfig
-public class DataStorageConfigurationSchema {
-    /** Name of data storage. */
-    @PolymorphicId(hasDefault = true)
-    public String name = "aipersist";
+public class StorageProfileConfigurationSchema {
+
+    /** Storage engine name. */
+    @PolymorphicId
+    public String engine;
+
+    @InjectedName
+    public String name;
+
 }
diff --git a/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/engine/StorageTableDescriptor.java b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/engine/StorageTableDescriptor.java
index c8aa4366af..265b5c4258 100644
--- a/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/engine/StorageTableDescriptor.java
+++ b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/engine/StorageTableDescriptor.java
@@ -25,19 +25,19 @@ public class StorageTableDescriptor {
 
     private final int partitions;
 
-    private final String dataRegion;
+    private final String storageProfile;
 
     /**
      * Constructor.
      *
      * @param id Table ID.
      * @param partitions Count of partitions.
-     * @param dataRegion Data region name.
+     * @param storageProfile Storage profile name.
      */
-    public StorageTableDescriptor(int id, int partitions, String dataRegion) {
+    public StorageTableDescriptor(int id, int partitions, String storageProfile) {
         this.id = id;
         this.partitions = partitions;
-        this.dataRegion = dataRegion;
+        this.storageProfile = storageProfile;
     }
 
     /**
@@ -55,9 +55,9 @@ public class StorageTableDescriptor {
     }
 
     /**
-     * Returns the data region name.
+     * Returns the storage profile name.
      */
-    public String getDataRegion() {
-        return dataRegion;
+    public String getStorageProfile() {
+        return storageProfile;
     }
 }
diff --git a/modules/storage-api/src/test/java/org/apache/ignite/internal/storage/DataStorageManagerTest.java b/modules/storage-api/src/test/java/org/apache/ignite/internal/storage/DataStorageManagerTest.java
deleted file mode 100644
index 2f99df82bf..0000000000
--- a/modules/storage-api/src/test/java/org/apache/ignite/internal/storage/DataStorageManagerTest.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.storage;
-
-import static org.apache.ignite.internal.storage.DataStorageModulesTest.FirstDataStorageConfigurationSchema.FIRST;
-import static org.apache.ignite.internal.storage.DataStorageModulesTest.SecondDataStorageConfigurationSchema.SECOND;
-import static org.apache.ignite.internal.storage.DataStorageModulesTest.createMockedDataStorageModule;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.instanceOf;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.mockito.Mockito.mock;
-
-import java.nio.file.Path;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.UUID;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import org.apache.ignite.configuration.ConfigurationWrongPolymorphicTypeIdException;
-import org.apache.ignite.internal.components.LogSyncer;
-import org.apache.ignite.internal.configuration.ConfigurationRegistry;
-import org.apache.ignite.internal.configuration.testframework.ConfigurationExtension;
-import org.apache.ignite.internal.configuration.testframework.InjectConfiguration;
-import org.apache.ignite.internal.failure.FailureProcessor;
-import org.apache.ignite.internal.schema.configuration.storage.DataStorageConfiguration;
-import org.apache.ignite.internal.schema.configuration.storage.DataStorageView;
-import org.apache.ignite.internal.storage.DataStorageModulesTest.FirstDataStorageConfigurationSchema;
-import org.apache.ignite.internal.storage.DataStorageModulesTest.SecondDataStorageConfigurationSchema;
-import org.apache.ignite.internal.testframework.BaseIgniteAbstractTest;
-import org.apache.ignite.internal.testframework.WorkDirectory;
-import org.apache.ignite.internal.testframework.WorkDirectoryExtension;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-
-/**
- * For {@link DataStorageManager} testing.
- */
-@ExtendWith(WorkDirectoryExtension.class)
-@ExtendWith(ConfigurationExtension.class)
-public class DataStorageManagerTest extends BaseIgniteAbstractTest {
-    @WorkDirectory
-    private Path workDir;
-
-    @InjectConfiguration(
-            polymorphicExtensions = {
-                    FirstDataStorageConfigurationSchema.class,
-                    SecondDataStorageConfigurationSchema.class
-            }
-    )
-    private DataStorageConfiguration dataStorageConfig;
-
-    @Test
-    void testTableDataStorageConsumerError() {
-        DataStorageModules dataStorageModules = new DataStorageModules(List.of(
-                createMockedDataStorageModule(FIRST),
-                createMockedDataStorageModule(SECOND)
-        ));
-
-        DataStorageManager dataStorageManager = new DataStorageManager(
-                dataStorageModules.createStorageEngines(
-                        "test",
-                        mock(ConfigurationRegistry.class),
-                        workDir,
-                        null,
-                        mock(FailureProcessor.class),
-                        mock(LogSyncer.class)
-                )
-        );
-
-        // Check random polymorphicTypeId.
-        ExecutionException exception = assertThrows(
-                ExecutionException.class,
-                () -> dataStorageConfig
-                        .change(dataStorageManager.zoneDataStorageConsumer(UUID.randomUUID().toString(), Map.of()))
-                        .get(1, TimeUnit.SECONDS)
-        );
-
-        assertThat(exception.getCause(), instanceOf(ConfigurationWrongPolymorphicTypeIdException.class));
-
-        // Check random field name.
-        exception = assertThrows(
-                ExecutionException.class,
-                () -> dataStorageConfig
-                        .change(dataStorageManager.zoneDataStorageConsumer(FIRST, Map.of(UUID.randomUUID().toString(), 1)))
-                        .get(1, TimeUnit.SECONDS)
-        );
-
-        assertThat(exception.getCause(), instanceOf(NoSuchElementException.class));
-
-        // Check other field type.
-        exception = assertThrows(
-                ExecutionException.class,
-                () -> dataStorageConfig
-                        .change(dataStorageManager.zoneDataStorageConsumer(FIRST, Map.of("strVal", 1)))
-                        .get(1, TimeUnit.SECONDS)
-        );
-
-        assertThat(exception.getCause(), instanceOf(ClassCastException.class));
-    }
-
-    @Test
-    void testTableDataStorageConsumerSuccess() throws Exception {
-        DataStorageModules dataStorageModules = new DataStorageModules(List.of(
-                createMockedDataStorageModule(FIRST),
-                createMockedDataStorageModule(SECOND)
-        ));
-
-        DataStorageManager dataStorageManager = new DataStorageManager(
-                dataStorageModules.createStorageEngines(
-                        "test",
-                        mock(ConfigurationRegistry.class),
-                        workDir,
-                        null,
-                        mock(FailureProcessor.class),
-                        mock(LogSyncer.class)
-                )
-        );
-
-        DataStorageView dataStorageView = dataStorageConfig.value();
-
-        // Just change type and check defaults.
-        dataStorageConfig
-                .change(dataStorageManager.zoneDataStorageConsumer(FIRST, Map.of()))
-                .get(1, TimeUnit.SECONDS);
-
-        dataStorageView = dataStorageConfig.value();
-
-        assertThat(dataStorageView, instanceOf(FirstDataStorageView.class));
-
-        assertThat(((FirstDataStorageView) dataStorageView).strVal(), equalTo("foo"));
-        assertThat(((FirstDataStorageView) dataStorageView).intVal(), equalTo(100));
-
-        // Change type and check values.
-        dataStorageConfig
-                .change(dataStorageManager.zoneDataStorageConsumer(SECOND, Map.of("strVal", "foobar", "longVal", 666L)))
-                .get(1, TimeUnit.SECONDS);
-
-        dataStorageView = dataStorageConfig.value();
-
-        assertThat(dataStorageView, instanceOf(SecondDataStorageView.class));
-
-        assertThat(((SecondDataStorageView) dataStorageView).strVal(), equalTo("foobar"));
-        assertThat(((SecondDataStorageView) dataStorageView).longVal(), equalTo(666L));
-    }
-}
diff --git a/modules/storage-api/src/test/java/org/apache/ignite/internal/storage/DataStorageModulesTest.java b/modules/storage-api/src/test/java/org/apache/ignite/internal/storage/DataStorageModulesTest.java
index d6a68eaa85..dd07e2e255 100644
--- a/modules/storage-api/src/test/java/org/apache/ignite/internal/storage/DataStorageModulesTest.java
+++ b/modules/storage-api/src/test/java/org/apache/ignite/internal/storage/DataStorageModulesTest.java
@@ -17,11 +17,8 @@
 
 package org.apache.ignite.internal.storage;
 
-import static org.apache.ignite.internal.storage.DataStorageModulesTest.FirstDataStorageConfigurationSchema.FIRST;
-import static org.apache.ignite.internal.storage.DataStorageModulesTest.SecondDataStorageConfigurationSchema.SECOND;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.aMapWithSize;
-import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.startsWith;
 import static org.junit.jupiter.api.Assertions.assertNotSame;
 import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -33,12 +30,9 @@ import static org.mockito.Mockito.when;
 import java.nio.file.Path;
 import java.util.List;
 import java.util.Map;
-import org.apache.ignite.configuration.annotation.PolymorphicConfigInstance;
-import org.apache.ignite.configuration.annotation.Value;
 import org.apache.ignite.internal.components.LogSyncer;
 import org.apache.ignite.internal.configuration.ConfigurationRegistry;
 import org.apache.ignite.internal.failure.FailureProcessor;
-import org.apache.ignite.internal.schema.configuration.storage.DataStorageConfigurationSchema;
 import org.apache.ignite.internal.storage.engine.StorageEngine;
 import org.apache.ignite.internal.testframework.BaseIgniteAbstractTest;
 import org.apache.ignite.internal.testframework.WorkDirectory;
@@ -54,33 +48,9 @@ public class DataStorageModulesTest extends BaseIgniteAbstractTest {
     @WorkDirectory
     private Path workDir;
 
-    /**
-     * Test extension of {@link DataStorageConfigurationSchema}.
-     */
-    @PolymorphicConfigInstance(FIRST)
-    public static class FirstDataStorageConfigurationSchema extends DataStorageConfigurationSchema {
-        static final String FIRST = "first";
+    private static final String FIRST = "first";
 
-        @Value(hasDefault = true)
-        public String strVal = "foo";
-
-        @Value(hasDefault = true)
-        public int intVal = 100;
-    }
-
-    /**
-     * Test extension of {@link DataStorageConfigurationSchema}.
-     */
-    @PolymorphicConfigInstance(SECOND)
-    public static class SecondDataStorageConfigurationSchema extends DataStorageConfigurationSchema {
-        static final String SECOND = "second";
-
-        @Value(hasDefault = true)
-        public String strVal = "bar";
-
-        @Value(hasDefault = true)
-        public long longVal = 500L;
-    }
+    private static final String SECOND = "second";
 
     @Test
     void testDuplicateName() {
@@ -121,72 +91,6 @@ public class DataStorageModulesTest extends BaseIgniteAbstractTest {
         assertNotSame(engines.get(FIRST), engines.get(SECOND));
     }
 
-    @Test
-    void testCollectSchemasFieldsDuplicateKey() {
-        DataStorageModules dataStorageModules = new DataStorageModules(List.of(
-                createMockedDataStorageModule(FIRST),
-                createMockedDataStorageModule(SECOND)
-        ));
-
-        IllegalStateException exception = assertThrows(
-                IllegalStateException.class,
-                () -> dataStorageModules.collectSchemasFields(
-                        List.of(FirstDataStorageConfigurationSchema.class, FirstDataStorageConfigurationSchema.class)
-                )
-        );
-
-        assertThat(exception.getMessage(), startsWith("Duplicate key"));
-    }
-
-    @Test
-    void testCollectSchemasFieldsMissingConfigurationSchemas() {
-        DataStorageModules dataStorageModules = new DataStorageModules(List.of(
-                createMockedDataStorageModule(FIRST),
-                createMockedDataStorageModule(SECOND)
-        ));
-
-        IllegalStateException exception = assertThrows(
-                IllegalStateException.class,
-                () -> dataStorageModules.collectSchemasFields(List.of(FirstDataStorageConfigurationSchema.class))
-        );
-
-        assertThat(exception.getMessage(), startsWith("Missing configuration schemas"));
-    }
-
-    @Test
-    void testCollectSchemasFieldsMissingDataStorageEngines() {
-        DataStorageModules dataStorageModules = new DataStorageModules(List.of(
-                createMockedDataStorageModule(FIRST)
-        ));
-
-        IllegalStateException exception = assertThrows(
-                IllegalStateException.class,
-                () -> dataStorageModules.collectSchemasFields(
-                        List.of(FirstDataStorageConfigurationSchema.class, SecondDataStorageConfigurationSchema.class)
-                )
-        );
-
-        assertThat(exception.getMessage(), startsWith("Missing data storage engines"));
-    }
-
-    @Test
-    void testCollectSchemasFields() {
-        DataStorageModules dataStorageModules = new DataStorageModules(List.of(
... 4171 lines suppressed ...