diff --git a/lib/ops/community-store-ops.js b/lib/ops/community-store-ops.js
--- a/lib/ops/community-store-ops.js
+++ b/lib/ops/community-store-ops.js
@@ -43,6 +43,19 @@
   | RemoveCommunitiesOperation
   | RemoveAllCommunitiesOperation;
 
+function convertCommunityInfoToClientDBCommunityInfo({
+  id,
+  communityInfo,
+}: {
+  +id: string,
+  +communityInfo: CommunityInfo,
+}): ClientDBCommunityInfo {
+  return {
+    id,
+    communityInfo: JSON.stringify(communityInfo),
+  };
+}
+
 const communityStoreOpsHandlers: BaseStoreOpsHandlers<
   CommunityStore,
   CommunityStoreOperation,
@@ -89,10 +102,7 @@
 
       return {
         type: 'replace_community',
-        payload: {
-          id: operation.payload.id,
-          communityInfo: JSON.stringify(operation.payload.communityInfo),
-        },
+        payload: convertCommunityInfoToClientDBCommunityInfo(operation.payload),
       };
     });
   },
@@ -110,4 +120,7 @@
   },
 };
 
-export { communityStoreOpsHandlers };
+export {
+  communityStoreOpsHandlers,
+  convertCommunityInfoToClientDBCommunityInfo,
+};
diff --git a/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h b/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h
--- a/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h
+++ b/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h
@@ -1,6 +1,7 @@
 #pragma once
 
 #include "../CryptoTools/Persist.h"
+#include "entities/CommunityInfo.h"
 #include "entities/Draft.h"
 #include "entities/KeyserverInfo.h"
 #include "entities/Message.h"
@@ -72,6 +73,10 @@
   virtual void removeKeyservers(const std::vector<std::string> &ids) const = 0;
   virtual void removeAllKeyservers() const = 0;
   virtual std::vector<KeyserverInfo> getAllKeyservers() const = 0;
+  virtual void replaceCommunity(const CommunityInfo &community_info) const = 0;
+  virtual void removeCommunities(const std::vector<std::string> &ids) const = 0;
+  virtual void removeAllCommunities() const = 0;
+  virtual std::vector<CommunityInfo> getAllCommunities() const = 0;
   virtual void beginTransaction() const = 0;
   virtual void commitTransaction() const = 0;
   virtual void rollbackTransaction() const = 0;
diff --git a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h
--- a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h
+++ b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h
@@ -3,6 +3,7 @@
 #include "../CryptoTools/Persist.h"
 #include "DatabaseQueryExecutor.h"
 #include "NativeSQLiteConnectionManager.h"
+#include "entities/CommunityInfo.h"
 #include "entities/Draft.h"
 #include "entities/KeyserverInfo.h"
 #include "entities/UserInfo.h"
@@ -87,6 +88,10 @@
   void removeKeyservers(const std::vector<std::string> &ids) const override;
   void removeAllKeyservers() const override;
   std::vector<KeyserverInfo> getAllKeyservers() const override;
+  void replaceCommunity(const CommunityInfo &community_info) const override;
+  void removeCommunities(const std::vector<std::string> &ids) const override;
+  void removeAllCommunities() const override;
+  std::vector<CommunityInfo> getAllCommunities() const override;
   void beginTransaction() const override;
   void commitTransaction() const override;
   void rollbackTransaction() const override;
diff --git a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp
--- a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp
+++ b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp
@@ -1,6 +1,7 @@
 #include "SQLiteQueryExecutor.h"
 #include "Logger.h"
 
+#include "entities/CommunityInfo.h"
 #include "entities/EntityQueryHelpers.h"
 #include "entities/KeyserverInfo.h"
 #include "entities/Metadata.h"
@@ -1491,6 +1492,48 @@
       SQLiteQueryExecutor::getConnection(), getAllUsersSQL);
 }
 
+void SQLiteQueryExecutor::replaceCommunity(
+    const CommunityInfo &community_info) const {
+  static std::string replaceCommunitySQL =
+      "REPLACE INTO communities (id, community_info) "
+      "VALUES (?, ?);";
+  replaceEntity<CommunityInfo>(
+      SQLiteQueryExecutor::getConnection(),
+      replaceCommunitySQL,
+      community_info);
+}
+
+void SQLiteQueryExecutor::removeAllCommunities() const {
+  static std::string removeAllCommunitiesSQL = "DELETE FROM communities;";
+  removeAllEntities(
+      SQLiteQueryExecutor::getConnection(), removeAllCommunitiesSQL);
+}
+
+void SQLiteQueryExecutor::removeCommunities(
+    const std::vector<std::string> &ids) const {
+  if (!ids.size()) {
+    return;
+  }
+
+  std::stringstream removeCommunitiesByKeysSQLStream;
+  removeCommunitiesByKeysSQLStream << "DELETE FROM communities "
+                                      "WHERE id IN "
+                                   << getSQLStatementArray(ids.size()) << ";";
+
+  removeEntitiesByKeys(
+      SQLiteQueryExecutor::getConnection(),
+      removeCommunitiesByKeysSQLStream.str(),
+      ids);
+}
+
+std::vector<CommunityInfo> SQLiteQueryExecutor::getAllCommunities() const {
+  static std::string getAllCommunitiesSQL =
+      "SELECT * "
+      "FROM communities;";
+  return getAllEntities<CommunityInfo>(
+      SQLiteQueryExecutor::getConnection(), getAllCommunitiesSQL);
+}
+
 void SQLiteQueryExecutor::beginTransaction() const {
   executeQuery(SQLiteQueryExecutor::getConnection(), "BEGIN TRANSACTION;");
 }
diff --git a/native/cpp/CommonCpp/DatabaseManagers/entities/CommunityInfo.h b/native/cpp/CommonCpp/DatabaseManagers/entities/CommunityInfo.h
new file mode 100644
--- /dev/null
+++ b/native/cpp/CommonCpp/DatabaseManagers/entities/CommunityInfo.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "SQLiteDataConverters.h"
+#include <sqlite3.h>
+#include <string>
+
+namespace comm {
+
+struct CommunityInfo {
+  std::string id;
+  std::string community_info;
+
+  static CommunityInfo fromSQLResult(sqlite3_stmt *sqlRow, int idx) {
+    return CommunityInfo{
+        getStringFromSQLRow(sqlRow, idx), getStringFromSQLRow(sqlRow, idx + 1)};
+  }
+
+  int bindToSQL(sqlite3_stmt *sql, int idx) const {
+    bindStringToSQL(id, sql, idx);
+    return bindStringToSQL(community_info, sql, idx + 1);
+  }
+};
+
+} // namespace comm
diff --git a/web/cpp/SQLiteQueryExecutorBindings.cpp b/web/cpp/SQLiteQueryExecutorBindings.cpp
--- a/web/cpp/SQLiteQueryExecutorBindings.cpp
+++ b/web/cpp/SQLiteQueryExecutorBindings.cpp
@@ -48,6 +48,9 @@
   value_object<MessageStoreThread>("MessageStoreThreads")
       .field("id", &MessageStoreThread::id)
       .field("startReached", &MessageStoreThread::start_reached);
+  value_object<CommunityInfo>("CommunityInfo")
+      .field("id", &CommunityInfo::id)
+      .field("communityInfo", &CommunityInfo::community_info);
 
   value_object<WebThread>("WebThread")
       .field("id", &WebThread::id)
@@ -158,6 +161,11 @@
       .function(
           "removeAllKeyservers", &SQLiteQueryExecutor::removeAllKeyservers)
       .function("getAllKeyservers", &SQLiteQueryExecutor::getAllKeyservers)
+      .function("replaceCommunity", &SQLiteQueryExecutor::replaceCommunity)
+      .function("removeCommunities", &SQLiteQueryExecutor::removeCommunities)
+      .function(
+          "removeAllCommunities", &SQLiteQueryExecutor::removeAllCommunities)
+      .function("getAllCommunities", &SQLiteQueryExecutor::getAllCommunities)
       .function("beginTransaction", &SQLiteQueryExecutor::beginTransaction)
       .function("commitTransaction", &SQLiteQueryExecutor::commitTransaction)
       .function(
diff --git a/web/database/_generated/comm_query_executor.wasm b/web/database/_generated/comm_query_executor.wasm
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001

literal 0
Hc$@<O00001

diff --git a/web/database/queries/communities-queries.test.js b/web/database/queries/communities-queries.test.js
new file mode 100644
--- /dev/null
+++ b/web/database/queries/communities-queries.test.js
@@ -0,0 +1,132 @@
+// @flow
+
+import {
+  convertCommunityInfoToClientDBCommunityInfo,
+  communityStoreOpsHandlers,
+} from 'lib/ops/community-store-ops.js';
+import type { CommunityInfo } from 'lib/types/community-types.js';
+
+import { getDatabaseModule } from '../db-module.js';
+import type { EmscriptenModule } from '../types/module.js';
+import type { SQLiteQueryExecutor } from '../types/sqlite-query-executor.js';
+import { clearSensitiveData } from '../utils/db-utils.js';
+
+const FILE_PATH = 'test.sqlite';
+
+const TEST_COMMUNITY_1: CommunityInfo = {
+  enabledApps: {
+    calendar: false,
+    wiki: false,
+    tasks: true,
+    files: true,
+  },
+};
+
+const TEST_COMMUNITY_2: CommunityInfo = {
+  enabledApps: {
+    calendar: true,
+    wiki: false,
+    tasks: false,
+    files: false,
+  },
+};
+
+describe('Community Store queries', () => {
+  let queryExecutor: ?SQLiteQueryExecutor = null;
+  let dbModule: ?EmscriptenModule = null;
+
+  beforeAll(async () => {
+    dbModule = getDatabaseModule();
+  });
+
+  beforeEach(() => {
+    if (!dbModule) {
+      return;
+    }
+
+    queryExecutor = new dbModule.SQLiteQueryExecutor(FILE_PATH);
+    queryExecutor?.replaceCommunity(
+      convertCommunityInfoToClientDBCommunityInfo({
+        communityInfo: TEST_COMMUNITY_1,
+        id: '1',
+      }),
+    );
+    queryExecutor?.replaceCommunity(
+      convertCommunityInfoToClientDBCommunityInfo({
+        communityInfo: TEST_COMMUNITY_2,
+        id: '2',
+      }),
+    );
+  });
+
+  afterEach(() => {
+    if (!dbModule || !queryExecutor) {
+      return;
+    }
+
+    clearSensitiveData(dbModule, FILE_PATH, queryExecutor);
+  });
+
+  it('should return all communities', () => {
+    const communities = queryExecutor?.getAllCommunities();
+
+    expect(communities).toHaveLength(2);
+  });
+
+  it('should remove all communities', () => {
+    queryExecutor?.removeAllCommunities();
+    const communities = queryExecutor?.getAllCommunities();
+
+    expect(communities).toHaveLength(0);
+  });
+
+  it('should update community enabled apps', () => {
+    const community2Updated: CommunityInfo = {
+      enabledApps: {
+        calendar: true,
+        wiki: true,
+        tasks: true,
+        files: true,
+      },
+    };
+
+    queryExecutor?.replaceCommunity(
+      convertCommunityInfoToClientDBCommunityInfo({
+        communityInfo: community2Updated,
+        id: '2',
+      }),
+    );
+
+    const communities = queryExecutor?.getAllCommunities();
+    if (!communities) {
+      throw new Error('communities not defined');
+    }
+
+    expect(communities).toHaveLength(2);
+
+    const communitiesFromDB =
+      communityStoreOpsHandlers.translateClientDBData(communities);
+
+    expect(communitiesFromDB['2']).toBeDefined();
+    expect(communitiesFromDB['2'].enabledApps.calendar).toBe(true);
+    expect(communitiesFromDB['2'].enabledApps.wiki).toBe(true);
+    expect(communitiesFromDB['2'].enabledApps.tasks).toBe(true);
+    expect(communitiesFromDB['2'].enabledApps.files).toBe(true);
+  });
+
+  it('should remove community', () => {
+    queryExecutor?.removeCommunities(['2']);
+
+    const communities = queryExecutor?.getAllCommunities();
+    if (!communities) {
+      throw new Error('communities not defined');
+    }
+
+    expect(communities.length).toBe(1);
+
+    const communitiesFromDB =
+      communityStoreOpsHandlers.translateClientDBData(communities);
+
+    expect(communitiesFromDB['1']).toBeDefined();
+  });
+});
diff --git a/web/database/types/sqlite-query-executor.js b/web/database/types/sqlite-query-executor.js
--- a/web/database/types/sqlite-query-executor.js
+++ b/web/database/types/sqlite-query-executor.js
@@ -1,5 +1,6 @@
 // @flow
 
+import type { ClientDBCommunityInfo } from 'lib/ops/community-store-ops.js';
 import type { ClientDBKeyserverInfo } from 'lib/ops/keyserver-store-ops.js';
 import type { ClientDBReport } from 'lib/ops/report-store-ops.js';
 import type { ClientDBUserInfo } from 'lib/ops/user-store-ops.js';
@@ -99,6 +100,11 @@
   removeAllKeyservers(): void;
   getAllKeyservers(): ClientDBKeyserverInfo[];
 
+  replaceCommunity(communityInfo: ClientDBCommunityInfo): void;
+  removeCommunities(ids: $ReadOnlyArray<string>): void;
+  removeAllCommunities(): void;
+  getAllCommunities(): ClientDBCommunityInfo[];
+
   beginTransaction(): void;
   commitTransaction(): void;
   rollbackTransaction(): void;