diff --git a/native/cpp/CommonCpp/NativeModules/InternalModules/GlobalDBSingleton.h b/native/cpp/CommonCpp/NativeModules/InternalModules/GlobalDBSingleton.h
new file mode 100644
--- /dev/null
+++ b/native/cpp/CommonCpp/NativeModules/InternalModules/GlobalDBSingleton.h
@@ -0,0 +1,16 @@
+#pragma once
+
+#include "../../Tools/WorkerThread.h"
+
+#include <atomic>
+
+namespace comm {
+class GlobalDBSingleton {
+  std::unique_ptr<WorkerThread> databaseThread;
+
+public:
+  static GlobalDBSingleton instance;
+  void scheduleOrRun(const taskType task);
+  void enableMultithreading();
+};
+} // namespace comm
diff --git a/native/cpp/CommonCpp/NativeModules/InternalModules/GlobalDBSingleton.cpp b/native/cpp/CommonCpp/NativeModules/InternalModules/GlobalDBSingleton.cpp
new file mode 100644
--- /dev/null
+++ b/native/cpp/CommonCpp/NativeModules/InternalModules/GlobalDBSingleton.cpp
@@ -0,0 +1,27 @@
+#include "GlobalDBSingleton.h"
+
+#include <stdexcept>
+
+namespace comm {
+GlobalDBSingleton GlobalDBSingleton::instance;
+
+// Do not use the following API directly in native code on
+// iOS. Use GlobalDBSingletonIOSProxy instead, which takes
+// care of synchronization. On Android we decided to enable
+// multithreading from the start of the app, so synchronization
+// is not an issue
+
+void GlobalDBSingleton::scheduleOrRun(const taskType task) {
+  if (this->databaseThread != nullptr) {
+    this->databaseThread->scheduleTask(task);
+    return;
+  }
+  task();
+}
+
+void GlobalDBSingleton::enableMultithreading() {
+  if (this->databaseThread == nullptr) {
+    this->databaseThread = std::make_unique<WorkerThread>("database");
+  }
+}
+} // namespace comm
diff --git a/native/ios/Comm.xcodeproj/project.pbxproj b/native/ios/Comm.xcodeproj/project.pbxproj
--- a/native/ios/Comm.xcodeproj/project.pbxproj
+++ b/native/ios/Comm.xcodeproj/project.pbxproj
@@ -67,6 +67,7 @@
 		CB4821AF27CFB19D001AB7E1 /* PlatformSpecificTools.mm in Sources */ = {isa = PBXBuildFile; fileRef = 71762A74270D8AAE00F565ED /* PlatformSpecificTools.mm */; };
 		CB4821B127CFB1FA001AB7E1 /* GlobalNetworkSingleton.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 726E5D762731A5E10032361D /* GlobalNetworkSingleton.cpp */; };
 		CB4821B227CFB20E001AB7E1 /* SQLiteQueryExecutor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 71BE84412636A944002849D2 /* SQLiteQueryExecutor.cpp */; };
+		CBF332CD28E302EE00E80062 /* GlobalDBSingleton.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CBF332CC28E302C600E80062 /* GlobalDBSingleton.cpp */; };
 		CBFE58292885852B003B94C9 /* ThreadOperations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CBFE58282885852B003B94C9 /* ThreadOperations.cpp */; };
 		D7DB6E0F85B2DBE15B01EC21 /* libPods-Comm.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 994BEBDD4E4959F69CEA0BC3 /* libPods-Comm.a */; };
 		F02C296C528B51ADAB5AA19D /* libPods-NotificationService.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3EE4DCB430B05EC9DE7D7B01 /* libPods-NotificationService.a */; };
@@ -222,6 +223,8 @@
 		CB38F2BE286C6C980010535C /* DeleteEntryMessageSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DeleteEntryMessageSpec.h; path = PersistentStorageUtilities/MessageOperationsUtilities/MessageSpecs/DeleteEntryMessageSpec.h; sourceTree = "<group>"; };
 		CB38F2BF286C6C980010535C /* UpdateRelationshipMessageSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UpdateRelationshipMessageSpec.h; path = PersistentStorageUtilities/MessageOperationsUtilities/MessageSpecs/UpdateRelationshipMessageSpec.h; sourceTree = "<group>"; };
 		CB3C621327CE66540054F24C /* libEXSecureStore.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libEXSecureStore.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		CBF332CB28E302C600E80062 /* GlobalDBSingleton.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GlobalDBSingleton.h; sourceTree = "<group>"; };
+		CBF332CC28E302C600E80062 /* GlobalDBSingleton.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = GlobalDBSingleton.cpp; sourceTree = "<group>"; };
 		CBFE58272885852B003B94C9 /* ThreadOperations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadOperations.h; path = PersistentStorageUtilities/ThreadOperationsUtilities/ThreadOperations.h; sourceTree = "<group>"; };
 		CBFE58282885852B003B94C9 /* ThreadOperations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadOperations.cpp; path = PersistentStorageUtilities/ThreadOperationsUtilities/ThreadOperations.cpp; sourceTree = "<group>"; };
 		F53DA7B3F26C2798DCE74A94 /* Pods-Comm.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Comm.debug.xcconfig"; path = "Target Support Files/Pods-Comm/Pods-Comm.debug.xcconfig"; sourceTree = "<group>"; };
@@ -467,6 +470,8 @@
 		726E5D722731A4240032361D /* InternalModules */ = {
 			isa = PBXGroup;
 			children = (
+				CBF332CC28E302C600E80062 /* GlobalDBSingleton.cpp */,
+				CBF332CB28E302C600E80062 /* GlobalDBSingleton.h */,
 				726E5D732731A4790032361D /* NetworkModule.cpp */,
 				726E5D742731A4790032361D /* NetworkModule.h */,
 				726E5D762731A5E10032361D /* GlobalNetworkSingleton.cpp */,
@@ -1016,6 +1021,7 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				CBF332CD28E302EE00E80062 /* GlobalDBSingleton.cpp in Sources */,
 				FC2DF95628BFCFE90017C4AF /* tunnelbroker.pb.cc in Sources */,
 				CB38B48628771CDD00171182 /* TemporaryMessageStorage.mm in Sources */,
 				CB38B48428771CAF00171182 /* EncryptedFileUtils.mm in Sources */,