diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/events/prune/EventsPruner.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/events/prune/EventsPruner.kt
index 097ee6e35e..195315e870 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/events/prune/EventsPruner.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/events/prune/EventsPruner.kt
@@ -9,6 +9,7 @@ import im.vector.matrix.android.internal.database.RealmLiveEntityObserver
 import im.vector.matrix.android.internal.database.mapper.asDomain
 import im.vector.matrix.android.internal.database.model.EventEntity
 import im.vector.matrix.android.internal.database.query.where
+import im.vector.matrix.android.internal.util.WorkerParamsFactory
 import io.realm.RealmResults
 
 private const val PRUNE_EVENT_WORKER = "PRUNE_EVENT_WORKER"
@@ -20,8 +21,8 @@ internal class EventsPruner(monarchy: Monarchy) :
 
     override fun process(results: RealmResults<EventEntity>, updateIndexes: IntArray, deletionIndexes: IntArray) {
         val redactionEvents = results.map { it.asDomain() }
-        val pruneEventWorkerParams = PruneEventWorkerParams(redactionEvents, updateIndexes.toList(), deletionIndexes.toList())
-        val workData = pruneEventWorkerParams.toData()
+        val pruneEventWorkerParams = PruneEventWorker.Params(redactionEvents, updateIndexes.toList(), deletionIndexes.toList())
+        val workData = WorkerParamsFactory.toData(pruneEventWorkerParams)
 
         val sendWork = OneTimeWorkRequestBuilder<PruneEventWorker>()
                 .setInputData(workData)
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/events/prune/PruneEventWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/events/prune/PruneEventWorker.kt
index 6b2a11f011..cf0f6b6117 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/events/prune/PruneEventWorker.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/events/prune/PruneEventWorker.kt
@@ -4,6 +4,7 @@ import android.content.Context
 import androidx.work.Worker
 import androidx.work.WorkerParameters
 import arrow.core.Option
+import com.squareup.moshi.JsonClass
 import com.zhuinden.monarchy.Monarchy
 import im.vector.matrix.android.api.session.events.model.Event
 import im.vector.matrix.android.api.session.events.model.EventType
@@ -11,6 +12,7 @@ import im.vector.matrix.android.internal.database.mapper.asDomain
 import im.vector.matrix.android.internal.database.mapper.asEntity
 import im.vector.matrix.android.internal.database.model.EventEntity
 import im.vector.matrix.android.internal.database.query.where
+import im.vector.matrix.android.internal.util.WorkerParamsFactory
 import im.vector.matrix.android.internal.util.tryTransactionAsync
 import io.realm.Realm
 import org.koin.standalone.KoinComponent
@@ -20,10 +22,19 @@ internal class PruneEventWorker(context: Context,
                                 workerParameters: WorkerParameters
 ) : Worker(context, workerParameters), KoinComponent {
 
+    @JsonClass(generateAdapter = true)
+    internal data class Params(
+            val redactionEvents: List<Event>,
+            val updateIndexes: List<Int>,
+            val deletionIndexes: List<Int>
+    )
+
     private val monarchy by inject<Monarchy>()
 
     override fun doWork(): Result {
-        val params = PruneEventWorkerParams.fromData(inputData) ?: return Result.FAILURE
+        val params = WorkerParamsFactory.fromData<Params>(inputData)
+                ?: return Result.FAILURE
+
         val result = monarchy.tryTransactionAsync { realm ->
             params.updateIndexes.forEach { index ->
                 val data = params.redactionEvents[index]
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/events/prune/PruneEventWorkerParams.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/events/prune/PruneEventWorkerParams.kt
deleted file mode 100644
index 53815f38a3..0000000000
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/events/prune/PruneEventWorkerParams.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-package im.vector.matrix.android.internal.session.events.prune
-
-import androidx.work.Data
-import com.squareup.moshi.JsonClass
-import im.vector.matrix.android.api.session.events.model.Event
-import im.vector.matrix.android.internal.di.MoshiProvider
-
-@JsonClass(generateAdapter = true)
-internal data class PruneEventWorkerParams(
-        val redactionEvents: List<Event>,
-        val updateIndexes: List<Int>,
-        val deletionIndexes: List<Int>
-) {
-
-    fun toData(): Data {
-        val json = adapter.toJson(this)
-        return Data.Builder().putString(KEY, json).build()
-    }
-
-    companion object {
-
-        private val moshi = MoshiProvider.providesMoshi()
-        private val adapter = moshi.adapter(PruneEventWorkerParams::class.java)
-        private const val KEY = "PruneEventWorkerParams"
-
-        fun fromData(data: Data): PruneEventWorkerParams? {
-            val json = data.getString(KEY)
-            return if (json == null) {
-                null
-            } else {
-                adapter.fromJson(json)
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataWorker.kt
index 4905b93d3b..bed103e42f 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataWorker.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataWorker.kt
@@ -4,6 +4,8 @@ import android.content.Context
 import androidx.work.Worker
 import androidx.work.WorkerParameters
 import arrow.core.Try
+import com.squareup.moshi.JsonClass
+import im.vector.matrix.android.internal.util.WorkerParamsFactory
 import org.koin.standalone.KoinComponent
 import org.koin.standalone.inject
 
@@ -11,10 +13,19 @@ internal class GetGroupDataWorker(context: Context,
                                   workerParameters: WorkerParameters
 ) : Worker(context, workerParameters), KoinComponent {
 
+    @JsonClass(generateAdapter = true)
+    internal data class Params(
+            val groupIds: List<String>,
+            val updateIndexes: List<Int>,
+            val deletionIndexes: List<Int>
+    )
+
     private val getGroupDataRequest by inject<GetGroupDataRequest>()
 
     override fun doWork(): Result {
-        val params = GetGroupDataWorkerParams.fromData(inputData) ?: return Result.FAILURE
+        val params = WorkerParamsFactory.fromData<Params>(inputData)
+                ?: return Result.FAILURE
+
         val results = params.updateIndexes.map { index ->
             val groupId = params.groupIds[index]
             fetchGroupData(groupId)
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataWorkerParams.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataWorkerParams.kt
deleted file mode 100644
index 5dd9eb8750..0000000000
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataWorkerParams.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-package im.vector.matrix.android.internal.session.group
-
-import androidx.work.Data
-import com.squareup.moshi.JsonClass
-import im.vector.matrix.android.internal.di.MoshiProvider
-
-@JsonClass(generateAdapter = true)
-internal data class GetGroupDataWorkerParams(
-        val groupIds: List<String>,
-        val updateIndexes: List<Int>,
-        val deletionIndexes: List<Int>
-) {
-
-    fun toData(): Data {
-        val json = adapter.toJson(this)
-        return Data.Builder().putString(KEY, json).build()
-    }
-
-    companion object {
-
-        private val moshi = MoshiProvider.providesMoshi()
-        private val adapter = moshi.adapter(GetGroupDataWorkerParams::class.java)
-        private const val KEY = "GetGroupDataWorkerParams"
-
-        fun fromData(data: Data): GetGroupDataWorkerParams? {
-            val json = data.getString(KEY)
-            return if (json == null) {
-                null
-            } else {
-                adapter.fromJson(json)
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt
index a9dead4e69..be70a16038 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt
@@ -5,6 +5,7 @@ import com.zhuinden.monarchy.Monarchy
 import im.vector.matrix.android.internal.database.RealmLiveEntityObserver
 import im.vector.matrix.android.internal.database.model.GroupEntity
 import im.vector.matrix.android.internal.database.query.where
+import im.vector.matrix.android.internal.util.WorkerParamsFactory
 import io.realm.RealmResults
 
 private const val GET_GROUP_DATA_WORKER = "GET_GROUP_DATA_WORKER"
@@ -20,8 +21,8 @@ internal class GroupSummaryUpdater(monarchy: Monarchy
 
     override fun process(results: RealmResults<GroupEntity>, updateIndexes: IntArray, deletionIndexes: IntArray) {
         val groupIds = results.map { it.groupId }
-        val getGroupDataWorkerParams = GetGroupDataWorkerParams(groupIds, updateIndexes.toList(), deletionIndexes.toList())
-        val workData = getGroupDataWorkerParams.toData()
+        val getGroupDataWorkerParams = GetGroupDataWorker.Params(groupIds, updateIndexes.toList(), deletionIndexes.toList())
+        val workData = WorkerParamsFactory.toData(getGroupDataWorkerParams)
 
         val sendWork = OneTimeWorkRequestBuilder<GetGroupDataWorker>()
                 .setInputData(workData)
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt
index 347445ac1e..015d5858cf 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt
@@ -1,18 +1,13 @@
 package im.vector.matrix.android.internal.session.room.send
 
-import androidx.work.BackoffPolicy
-import androidx.work.Constraints
-import androidx.work.Data
-import androidx.work.ExistingWorkPolicy
-import androidx.work.NetworkType
-import androidx.work.OneTimeWorkRequestBuilder
-import androidx.work.WorkManager
+import androidx.work.*
 import im.vector.matrix.android.api.session.room.SendService
 import im.vector.matrix.android.api.util.Cancelable
 import im.vector.matrix.android.internal.util.CancelableWork
+import im.vector.matrix.android.internal.util.WorkerParamsFactory
 import java.util.concurrent.TimeUnit
 
-private const val SEND_WORK_NAME = "SEND_WORK_NAME"
+private const val SEND_WORK = "SEND_WORK"
 
 internal class DefaultSendService(private val roomId: String) : SendService {
 
@@ -22,20 +17,17 @@ internal class DefaultSendService(private val roomId: String) : SendService {
 
     override fun sendTextMessage(text: String): Cancelable {
 
-        val data = mapOf(
-                "roomId" to roomId,
-                "text" to text
-        )
-        val workData = Data.Builder().putAll(data).build()
+        val sendContentWorkerParams = SendEventWorker.Params(roomId, text)
+        val workData = WorkerParamsFactory.toData(sendContentWorkerParams)
 
-        val sendWork = OneTimeWorkRequestBuilder<SendContentWorker>()
+        val sendWork = OneTimeWorkRequestBuilder<SendEventWorker>()
                 .setConstraints(sendConstraints)
                 .setInputData(workData)
                 .setBackoffCriteria(BackoffPolicy.LINEAR, 10_000, TimeUnit.MILLISECONDS)
                 .build()
 
         val work = WorkManager.getInstance()
-                .beginUniqueWork(SEND_WORK_NAME, ExistingWorkPolicy.APPEND, sendWork)
+                .beginUniqueWork(SEND_WORK, ExistingWorkPolicy.APPEND, sendWork)
                 .enqueue()
 
         return CancelableWork(work)
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/SendContentWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/SendEventWorker.kt
similarity index 51%
rename from matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/SendContentWorker.kt
rename to matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/SendEventWorker.kt
index 1f972dfe2a..f490beb175 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/SendContentWorker.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/SendEventWorker.kt
@@ -3,32 +3,41 @@ package im.vector.matrix.android.internal.session.room.send
 import android.content.Context
 import androidx.work.Worker
 import androidx.work.WorkerParameters
+import com.squareup.moshi.JsonClass
 import im.vector.matrix.android.api.session.events.model.EventType
 import im.vector.matrix.android.api.session.room.model.MessageContent
 import im.vector.matrix.android.api.session.room.model.MessageType
 import im.vector.matrix.android.internal.network.executeRequest
 import im.vector.matrix.android.internal.session.room.RoomAPI
+import im.vector.matrix.android.internal.util.WorkerParamsFactory
 import org.koin.standalone.KoinComponent
 import org.koin.standalone.inject
 
-internal class SendContentWorker(context: Context, params: WorkerParameters)
+internal class SendEventWorker(context: Context, params: WorkerParameters)
     : Worker(context, params), KoinComponent {
 
+
+    @JsonClass(generateAdapter = true)
+    internal data class Params(
+            val roomId: String,
+            val text: String
+    )
+
     private val roomAPI by inject<RoomAPI>()
 
     override fun doWork(): Result {
 
-        val roomId = inputData.getString("roomId")
-        val text = inputData.getString("text")
-
-        val fakeId = roomId + "-" + System.currentTimeMillis()
-
-        if (roomId == null || text == null) {
-            return Result.FAILURE
-        }
+        val sendWorkerParameters = WorkerParamsFactory.fromData<Params>(inputData)
+                ?: return Result.FAILURE
 
+        val fakeId = sendWorkerParameters.roomId + "-" + System.currentTimeMillis()
         val result = executeRequest<SendResponse> {
-            apiCall = roomAPI.send(fakeId, roomId, EventType.MESSAGE, MessageContent(MessageType.MSGTYPE_TEXT, text))
+            apiCall = roomAPI.send(
+                    fakeId,
+                    sendWorkerParameters.roomId,
+                    EventType.MESSAGE,
+                    MessageContent(MessageType.MSGTYPE_TEXT, sendWorkerParameters.text)
+            )
         }
         return result.fold({ Result.RETRY }, { Result.SUCCESS })
     }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/WorkerParamsFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/WorkerParamsFactory.kt
new file mode 100644
index 0000000000..59f11e39d9
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/WorkerParamsFactory.kt
@@ -0,0 +1,27 @@
+package im.vector.matrix.android.internal.util
+
+import androidx.work.Data
+import im.vector.matrix.android.internal.di.MoshiProvider
+
+object WorkerParamsFactory {
+
+    const val KEY = "WORKER_PARAMS_JSON"
+
+    inline fun <reified T> toData(params: T): Data {
+        val moshi = MoshiProvider.providesMoshi()
+        val adapter = moshi.adapter(T::class.java)
+        val json = adapter.toJson(params)
+        return Data.Builder().putString(KEY, json).build()
+    }
+
+    inline fun <reified T> fromData(data: Data): T? {
+        val json = data.getString(KEY)
+        return if (json == null) {
+            null
+        } else {
+            val moshi = MoshiProvider.providesMoshi()
+            val adapter = moshi.adapter(T::class.java)
+            adapter.fromJson(json)
+        }
+    }
+}
\ No newline at end of file