diff --git a/platform/progress/backend/intellij.platform.progress.backend.iml b/platform/progress/backend/intellij.platform.progress.backend.iml
index cc47feec4168..02178f3399b6 100644
--- a/platform/progress/backend/intellij.platform.progress.backend.iml
+++ b/platform/progress/backend/intellij.platform.progress.backend.iml
@@ -10,5 +10,8 @@
+
+
+
\ No newline at end of file
diff --git a/platform/progress/backend/resources/intellij.platform.progress.backend.xml b/platform/progress/backend/resources/intellij.platform.progress.backend.xml
index 5d5af172a5ae..1d9ab52d2645 100644
--- a/platform/progress/backend/resources/intellij.platform.progress.backend.xml
+++ b/platform/progress/backend/resources/intellij.platform.progress.backend.xml
@@ -3,4 +3,12 @@
+
+
+
+
+
+
+
diff --git a/platform/progress/backend/src/BackendTaskStorage.kt b/platform/progress/backend/src/BackendTaskStorage.kt
new file mode 100644
index 000000000000..f2e442430480
--- /dev/null
+++ b/platform/progress/backend/src/BackendTaskStorage.kt
@@ -0,0 +1,37 @@
+// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package com.intellij.platform.progress.backend
+
+import com.intellij.platform.ide.progress.TaskInfoEntity
+import com.intellij.platform.ide.progress.TaskStorage
+import com.jetbrains.rhizomedb.ChangeScope
+import fleet.kernel.change
+import fleet.kernel.delete
+import fleet.kernel.shared
+import org.jetbrains.annotations.ApiStatus
+
+@ApiStatus.Internal
+class BackendTaskStorage : TaskStorage() {
+ override suspend fun createTaskInfoEntity(provider: ChangeScope.() -> TaskInfoEntity): TaskInfoEntity {
+ return change {
+ shared {
+ provider()
+ }
+ }
+ }
+
+ override suspend fun removeTaskInfoEntity(taskInfoEntity: TaskInfoEntity) {
+ change {
+ shared {
+ delete(taskInfoEntity)
+ }
+ }
+ }
+
+ override suspend fun updateTaskInfoEntity(updater: ChangeScope.() -> Unit) {
+ change {
+ shared {
+ updater()
+ }
+ }
+ }
+}
diff --git a/platform/progress/shared/src/TaskStorage.kt b/platform/progress/shared/src/TaskStorage.kt
new file mode 100644
index 000000000000..9e094b5b9c09
--- /dev/null
+++ b/platform/progress/shared/src/TaskStorage.kt
@@ -0,0 +1,112 @@
+// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package com.intellij.platform.ide.progress
+
+import com.intellij.openapi.components.service
+import com.intellij.platform.kernel.KernelService
+import com.intellij.platform.util.progress.ProgressState
+import com.jetbrains.rhizomedb.ChangeScope
+import fleet.kernel.withEntities
+import kotlinx.coroutines.withContext
+import org.jetbrains.annotations.ApiStatus
+
+/**
+ * Provides the ability to control how tasks are stored in Rhizome DB
+ * The implementation can decide where to store an object - in shared or local DB
+ * See [fleet.kernel.change] and [fleet.kernel.shared]
+ */
+@ApiStatus.Internal
+abstract class TaskStorage {
+
+ /**
+ * Adds a new task to the storage and returns the created [TaskInfoEntity].
+ *
+ * @param title The title of the task.
+ * @param cancellation Specifies if the task can be canceled.
+ * @return The created [TaskInfoEntity].
+ */
+ suspend fun addTask(
+ title: String,
+ cancellation: TaskCancellation,
+ ): TaskInfoEntity = withContext(KernelService.kernelCoroutineContext()) {
+ createTaskInfoEntity {
+ TaskInfoEntity.new {
+ it[TaskInfoEntity.Title] = title
+ it[TaskInfoEntity.TaskCancellationType] = cancellation
+ it[TaskInfoEntity.ProgressStateType] = null
+ it[TaskInfoEntity.TaskStatusType] = TaskStatus.RUNNING
+ }
+ }
+ }
+
+ /**
+ * Creates a new [TaskInfoEntity] using [provider] lambda
+ * The implementation can decide whether the entity should be created locally on in the shared DB scope.
+ *
+ * It's guaranteed that the method is called in the correct coroutine context,
+ * which includes kernel (see [KernelService.kernelCoroutineContext])
+ *
+ * @param provider The provider used to create the [TaskInfoEntity].
+ * @return The created [TaskInfoEntity].
+ */
+ protected abstract suspend fun createTaskInfoEntity(provider: ChangeScope.() -> TaskInfoEntity): TaskInfoEntity
+
+ /**
+ * Removes a task from Rhizome DB.
+ * NOTE: this doesn't cancel a running task, to cancel a task use [TaskManager.cancelTask]
+ *
+ * @param taskInfoEntity The task to be removed.
+ */
+ suspend fun removeTask(taskInfoEntity: TaskInfoEntity): Unit = withContext(KernelService.kernelCoroutineContext()) {
+ withEntities(taskInfoEntity) {
+ removeTaskInfoEntity(taskInfoEntity)
+ }
+ }
+
+ /**
+ * Removes the specified task from the storage.
+ * The implementation should use the same scope as in [createTaskInfoEntity] to remove the entity.
+ *
+ * It's guaranteed that only the task created by this instance of [TaskStorage]
+ * are going to be passed to this method.
+ *
+ * It is also guaranteed that the method is called in the correct coroutine context,
+ * which includes kernel (see [KernelService.kernelCoroutineContext])
+ *
+ * @param taskInfoEntity The task entity to be removed.
+ */
+ protected abstract suspend fun removeTaskInfoEntity(taskInfoEntity: TaskInfoEntity)
+
+ /**
+ * Updates the progress state of the given task.
+ * Old state is going to be overwritten, to receive all state updates use [updates]
+ *
+ * @param taskInfoEntity The task to be updated.
+ * @param state The new progress state to set on the task.
+ * @return Unit
+ */
+ suspend fun updateTask(taskInfoEntity: TaskInfoEntity, state: ProgressState): Unit = withContext(KernelService.kernelCoroutineContext()) {
+ withEntities(taskInfoEntity) {
+ updateTaskInfoEntity {
+ taskInfoEntity[TaskInfoEntity.ProgressStateType] = state
+ }
+ }
+ }
+
+ /**
+ * Updates a [TaskInfoEntity] in the storage using provided [updater]
+ *
+ * It's guaranteed that only the task created by this instance of [TaskStorage]
+ * are going to be passed to this method.
+ *
+ * It is also guaranteed that the method is called in the correct coroutine context,
+ * which includes kernel (see [KernelService.kernelCoroutineContext])
+ *
+ * @param updater A lambda provided with a [ChangeScope] receiver to modify the task information.
+ */
+ protected abstract suspend fun updateTaskInfoEntity(updater: ChangeScope.() -> Unit)
+
+ companion object {
+ @JvmStatic
+ fun getInstance(): TaskStorage = service()
+ }
+}