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
@@ -12,6 +12,7 @@
 #include "entities/OlmPersistSession.h"
 #include "entities/PersistItem.h"
 #include "entities/Report.h"
+#include "entities/SyncedMetadataEntry.h"
 #include "entities/Thread.h"
 #include "entities/UserInfo.h"
 
@@ -86,6 +87,12 @@
   virtual void removeAllIntegrityThreadHashes() const = 0;
   virtual std::vector<IntegrityThreadHash>
   getAllIntegrityThreadHashes() const = 0;
+  virtual void replaceSyncedMetadataEntry(
+      const SyncedMetadataEntry &synced_metadata_entry) const = 0;
+  virtual void
+  removeSyncedMetadata(const std::vector<std::string> &names) const = 0;
+  virtual void removeAllSyncedMetadata() const = 0;
+  virtual std::vector<SyncedMetadataEntry> getAllSyncedMetadata() 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
@@ -99,6 +99,12 @@
       const std::vector<std::string> &ids) const override;
   void removeAllIntegrityThreadHashes() const override;
   std::vector<IntegrityThreadHash> getAllIntegrityThreadHashes() const override;
+  void replaceSyncedMetadataEntry(
+      const SyncedMetadataEntry &synced_metadata_entry) const override;
+  void
+  removeSyncedMetadata(const std::vector<std::string> &names) const override;
+  void removeAllSyncedMetadata() const override;
+  std::vector<SyncedMetadataEntry> getAllSyncedMetadata() 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
@@ -6,6 +6,7 @@
 #include "entities/IntegrityThreadHash.h"
 #include "entities/KeyserverInfo.h"
 #include "entities/Metadata.h"
+#include "entities/SyncedMetadataEntry.h"
 #include "entities/UserInfo.h"
 #include <fstream>
 #include <iostream>
@@ -1684,6 +1685,51 @@
       SQLiteQueryExecutor::getConnection(), getAllIntegrityThreadHashesSQL);
 }
 
+void SQLiteQueryExecutor::replaceSyncedMetadataEntry(
+    const SyncedMetadataEntry &synced_metadata_entry) const {
+  static std::string replaceSyncedMetadataEntrySQL =
+      "REPLACE INTO synced_metadata (name, data) "
+      "VALUES (?, ?);";
+  replaceEntity<SyncedMetadataEntry>(
+      SQLiteQueryExecutor::getConnection(),
+      replaceSyncedMetadataEntrySQL,
+      synced_metadata_entry);
+}
+
+void SQLiteQueryExecutor::removeAllSyncedMetadata() const {
+  static std::string removeAllSyncedMetadataSQL =
+      "DELETE FROM synced_metadata;";
+  removeAllEntities(
+      SQLiteQueryExecutor::getConnection(), removeAllSyncedMetadataSQL);
+}
+
+void SQLiteQueryExecutor::removeSyncedMetadata(
+    const std::vector<std::string> &names) const {
+  if (!names.size()) {
+    return;
+  }
+
+  std::stringstream removeSyncedMetadataByNamesSQLStream;
+  removeSyncedMetadataByNamesSQLStream << "DELETE FROM synced_metadata "
+                                          "WHERE name IN "
+                                       << getSQLStatementArray(names.size())
+                                       << ";";
+
+  removeEntitiesByKeys(
+      SQLiteQueryExecutor::getConnection(),
+      removeSyncedMetadataByNamesSQLStream.str(),
+      names);
+}
+
+std::vector<SyncedMetadataEntry>
+SQLiteQueryExecutor::getAllSyncedMetadata() const {
+  static std::string getAllSyncedMetadataSQL =
+      "SELECT * "
+      "FROM synced_metadata;";
+  return getAllEntities<SyncedMetadataEntry>(
+      SQLiteQueryExecutor::getConnection(), getAllSyncedMetadataSQL);
+}
+
 void SQLiteQueryExecutor::beginTransaction() const {
   executeQuery(SQLiteQueryExecutor::getConnection(), "BEGIN TRANSACTION;");
 }
diff --git a/native/cpp/CommonCpp/DatabaseManagers/entities/SyncedMetadataEntry.h b/native/cpp/CommonCpp/DatabaseManagers/entities/SyncedMetadataEntry.h
new file mode 100644
--- /dev/null
+++ b/native/cpp/CommonCpp/DatabaseManagers/entities/SyncedMetadataEntry.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "SQLiteDataConverters.h"
+#include <sqlite3.h>
+#include <string>
+
+namespace comm {
+
+struct SyncedMetadataEntry {
+  std::string name;
+  std::string data;
+
+  static SyncedMetadataEntry fromSQLResult(sqlite3_stmt *sqlRow, int idx) {
+    return SyncedMetadataEntry{
+        getStringFromSQLRow(sqlRow, idx), getStringFromSQLRow(sqlRow, idx + 1)};
+  }
+
+  int bindToSQL(sqlite3_stmt *sql, int idx) const {
+    bindStringToSQL(name, sql, idx);
+    return bindStringToSQL(data, 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
@@ -55,6 +55,9 @@
   value_object<IntegrityThreadHash>("IntegrityThreadHash")
       .field("id", &IntegrityThreadHash::id)
       .field("threadHash", &IntegrityThreadHash::thread_hash);
+  value_object<SyncedMetadataEntry>("SyncedMetadataEntry")
+      .field("name", &SyncedMetadataEntry::name)
+      .field("data", &SyncedMetadataEntry::data);
 
   value_object<WebThread>("WebThread")
       .field("id", &WebThread::id)
@@ -190,6 +193,11 @@
       .function(
           "getAllIntegrityThreadHashes",
           &SQLiteQueryExecutor::getAllIntegrityThreadHashes)
+      .function("replaceSyncedMetadataEntry", &SQLiteQueryExecutor::replaceSyncedMetadataEntry)
+      .function("removeSyncedMetadata", &SQLiteQueryExecutor::removeSyncedMetadata)
+      .function(
+          "removeAllSyncedMetadata", &SQLiteQueryExecutor::removeAllSyncedMetadata)
+      .function("getAllSyncedMetadata", &SQLiteQueryExecutor::getAllSyncedMetadata)
       .function("beginTransaction", &SQLiteQueryExecutor::beginTransaction)
       .function("commitTransaction", &SQLiteQueryExecutor::commitTransaction)
       .function(
diff --git a/web/shared-worker/_generated/comm-query-executor.js b/web/shared-worker/_generated/comm-query-executor.js
--- a/web/shared-worker/_generated/comm-query-executor.js
+++ b/web/shared-worker/_generated/comm-query-executor.js
@@ -125,17 +125,17 @@
 1]&&(b=b.substr(0,b.length-1)),N.mkdir(b,c,0),0}catch(d){if("undefined"==typeof N||!(d instanceof N.Ma))throw d;return-d.Ra}},U:function(a,b,c,d){try{b=y(b);var f=d&256;b=P(a,b,d&4096);return fb(f?N.lstat:N.stat,b,c)}catch(g){if("undefined"==typeof N||!(g instanceof N.Ma))throw g;return-g.Ra}},v:function(a,b,c,d){gb=d;try{b=y(b);b=P(a,b);var f=d?hb():0;return N.open(b,c,f).fd}catch(g){if("undefined"==typeof N||!(g instanceof N.Ma))throw g;return-g.Ra}},L:function(a,b,c,d){try{b=y(b);b=P(a,b);if(0>=
 d)return-28;var f=N.readlink(b),g=Math.min(d,ta(f)),k=B[c+g];A(f,z,c,d+1);B[c+g]=k;return g}catch(h){if("undefined"==typeof N||!(h instanceof N.Ma))throw h;return-h.Ra}},K:function(a,b,c,d){try{return b=y(b),d=y(d),b=P(a,b),d=P(c,d),N.rename(b,d),0}catch(f){if("undefined"==typeof N||!(f instanceof N.Ma))throw f;return-f.Ra}},r:function(a){try{return a=y(a),N.rmdir(a),0}catch(b){if("undefined"==typeof N||!(b instanceof N.Ma))throw b;return-b.Ra}},W:function(a,b){try{return a=y(a),fb(N.stat,a,b)}catch(c){if("undefined"==
 typeof N||!(c instanceof N.Ma))throw c;return-c.Ra}},s:function(a,b,c){try{return b=y(b),b=P(a,b),0===c?N.unlink(b):512===c?N.rmdir(b):v("Invalid flags passed to unlinkat"),0}catch(d){if("undefined"==typeof N||!(d instanceof N.Ma))throw d;return-d.Ra}},I:function(a,b,c){try{b=y(b);b=P(a,b,!0);if(c){var d=ib(c),f=E[c+8>>2];g=1E3*d+f/1E6;c+=16;d=ib(c);f=E[c+8>>2];k=1E3*d+f/1E6}else var g=Date.now(),k=g;N.ae(b,g,k);return 0}catch(h){if("undefined"==typeof N||!(h instanceof N.Ma))throw h;return-h.Ra}},
-f:function(a){var b=jb[a];delete jb[a];var c=b.rc,d=b.pb,f=b.Lc,g=f.map(k=>k.zd).concat(f.map(k=>k.Sd));ub([a],g,k=>{var h={};f.forEach((n,q)=>{var p=k[q],t=n.Sb,x=n.yd,l=k[q+f.length],u=n.Rd,w=n.Td;h[n.rd]={read:C=>p.fromWireType(t(x,C)),write:(C,K)=>{var H=[];u(w,C,l.toWireType(H,K));kb(H)}}});return[{name:b.name,fromWireType:function(n){var q={},p;for(p in h)q[p]=h[p].read(n);d(n);return q},toWireType:function(n,q){for(var p in h)if(!(p in q))throw new TypeError('Missing field:  "'+p+'"');var t=
+e:function(a){var b=jb[a];delete jb[a];var c=b.rc,d=b.pb,f=b.Lc,g=f.map(k=>k.zd).concat(f.map(k=>k.Sd));ub([a],g,k=>{var h={};f.forEach((n,q)=>{var p=k[q],t=n.Sb,x=n.yd,l=k[q+f.length],u=n.Rd,w=n.Td;h[n.rd]={read:C=>p.fromWireType(t(x,C)),write:(C,K)=>{var H=[];u(w,C,l.toWireType(H,K));kb(H)}}});return[{name:b.name,fromWireType:function(n){var q={},p;for(p in h)q[p]=h[p].read(n);d(n);return q},toWireType:function(n,q){for(var p in h)if(!(p in q))throw new TypeError('Missing field:  "'+p+'"');var t=
 c();for(p in h)h[p].write(t,q[p]);null!==n&&n.push(d,t);return t},argPackAdvance:8,readValueFromPointer:lb,ib:d}]})},F:function(){},fa:function(a,b,c,d,f){var g=vb(c);b=S(b);R(a,{name:b,fromWireType:function(k){return!!k},toWireType:function(k,h){return h?d:f},argPackAdvance:8,readValueFromPointer:function(k){if(1===c)var h=B;else if(2===c)h=D;else if(4===c)h=E;else throw new TypeError("Unknown boolean type size: "+b);return this.fromWireType(h[k>>g])},ib:null})},ka:function(a,b,c,d,f,g,k,h,n,q,p,
 t,x){p=S(p);g=W(f,g);h&&(h=W(k,h));q&&(q=W(n,q));x=W(t,x);var l=pb(p);Mb(l,function(){Zb("Cannot construct "+p+" due to unbound types",[d])});ub([a,b,c],d?[d]:[],function(u){u=u[0];if(d){var w=u.Ta;var C=w.Eb}else C=U.prototype;u=qb(l,function(){if(Object.getPrototypeOf(this)!==K)throw new xb("Use 'new' to construct "+p);if(void 0===H.tb)throw new xb(p+" has no accessible constructor");var I=H.tb[arguments.length];if(void 0===I)throw new xb("Tried to invoke ctor of "+p+" with invalid number of parameters ("+
 arguments.length+") - expected ("+Object.keys(H.tb).toString()+") parameters instead!");return I.apply(this,arguments)});var K=Object.create(C,{constructor:{value:u}});u.prototype=K;var H=new Nb(p,u,K,x,w,g,h,q);w=new V(p,H,!0,!1);C=new V(p+"*",H,!1,!1);var Ga=new V(p+" const*",H,!1,!0);Db[a]={pointerType:C,jd:Ga};Ub(l,u);return[w,C,Ga]})},ja:function(a,b,c,d,f,g){0<b||v();var k=$b(b,c);f=W(d,f);ub([],[a],function(h){h=h[0];var n="constructor "+h.name;void 0===h.Ta.tb&&(h.Ta.tb=[]);if(void 0!==h.Ta.tb[b-
 1])throw new xb("Cannot register multiple constructors with identical number of parameters ("+(b-1)+") for class '"+h.name+"'! Overload resolution is currently only performed using the parameter count, not actual type info!");h.Ta.tb[b-1]=()=>{Zb("Cannot construct "+h.name+" due to unbound types",k)};ub([],k,function(q){q.splice(1,0,null);h.Ta.tb[b-1]=bc(n,q,null,f,g);return[]});return[]})},a:function(a,b,c,d,f,g,k,h){var n=$b(c,d);b=S(b);g=W(f,g);ub([],[a],function(q){function p(){Zb("Cannot call "+
 t+" due to unbound types",n)}q=q[0];var t=q.name+"."+b;b.startsWith("@@")&&(b=Symbol[b.substring(2)]);h&&q.Ta.Nd.push(b);var x=q.Ta.Eb,l=x[b];void 0===l||void 0===l.$a&&l.className!==q.name&&l.Qb===c-2?(p.Qb=c-2,p.className=q.name,x[b]=p):(Lb(x,b,t),x[b].$a[c-2]=p);ub([],n,function(u){u=bc(t,u,q,g,k);void 0===x[b].$a?(u.Qb=c-2,x[b]=u):x[b].$a[c-2]=u;return[]});return[]})},ea:function(a,b){b=S(b);R(a,{name:b,fromWireType:function(c){var d=ec(c);dc(c);return d},toWireType:function(c,d){return Sb(d)},
 argPackAdvance:8,readValueFromPointer:lb,ib:null})},x:function(a,b,c){c=vb(c);b=S(b);R(a,{name:b,fromWireType:function(d){return d},toWireType:function(d,f){return f},argPackAdvance:8,readValueFromPointer:fc(b,c),ib:null})},ha:function(a,b,c,d,f,g){var k=$b(b,c);a=S(a);f=W(d,f);Mb(a,function(){Zb("Cannot call "+a+" due to unbound types",k)},b-1);ub([],k,function(h){h=[h[0],null].concat(h.slice(1));Ub(a,bc(a,h,null,f,g),b-1);return[]})},i:function(a,b,c,d,f){b=S(b);-1===f&&(f=4294967295);f=vb(c);var g=
-h=>h;if(0===d){var k=32-8*c;g=h=>h<<k>>>k}c=b.includes("unsigned")?function(h,n){return n>>>0}:function(h,n){return n};R(a,{name:b,fromWireType:g,toWireType:c,argPackAdvance:8,readValueFromPointer:gc(b,f,0!==d),ib:null})},e:function(a,b,c){function d(g){g>>=2;var k=F;return new f(ua,k[g+1],k[g])}var f=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array][b];c=S(c);R(a,{name:c,fromWireType:d,argPackAdvance:8,readValueFromPointer:d},{Ad:!0})},y:function(a,b){b=
+h=>h;if(0===d){var k=32-8*c;g=h=>h<<k>>>k}c=b.includes("unsigned")?function(h,n){return n>>>0}:function(h,n){return n};R(a,{name:b,fromWireType:g,toWireType:c,argPackAdvance:8,readValueFromPointer:gc(b,f,0!==d),ib:null})},g:function(a,b,c){function d(g){g>>=2;var k=F;return new f(ua,k[g+1],k[g])}var f=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array][b];c=S(c);R(a,{name:c,fromWireType:d,argPackAdvance:8,readValueFromPointer:d},{Ad:!0})},y:function(a,b){b=
 S(b);var c="std::string"===b;R(a,{name:b,fromWireType:function(d){var f=F[d>>2],g=d+4;if(c)for(var k=g,h=0;h<=f;++h){var n=g+h;if(h==f||0==z[n]){k=y(k,n-k);if(void 0===q)var q=k;else q+=String.fromCharCode(0),q+=k;k=n+1}}else{q=Array(f);for(h=0;h<f;++h)q[h]=String.fromCharCode(z[g+h]);q=q.join("")}X(d);return q},toWireType:function(d,f){f instanceof ArrayBuffer&&(f=new Uint8Array(f));var g="string"==typeof f;g||f instanceof Uint8Array||f instanceof Uint8ClampedArray||f instanceof Int8Array||T("Cannot pass non-string to std::string");
 var k=c&&g?ta(f):f.length;var h=wc(4+k+1),n=h+4;F[h>>2]=k;if(c&&g)A(f,z,n,k+1);else if(g)for(g=0;g<k;++g){var q=f.charCodeAt(g);255<q&&(X(n),T("String has UTF-16 code units that do not fit in 8 bits"));z[n+g]=q}else for(g=0;g<k;++g)z[n+g]=f[g];null!==d&&d.push(X,h);return h},argPackAdvance:8,readValueFromPointer:lb,ib:function(d){X(d)}})},p:function(a,b,c){c=S(c);if(2===b){var d=ic;var f=jc;var g=kc;var k=()=>va;var h=1}else 4===b&&(d=lc,f=mc,g=nc,k=()=>F,h=2);R(a,{name:c,fromWireType:function(n){for(var q=
-F[n>>2],p=k(),t,x=n+4,l=0;l<=q;++l){var u=n+4+l*b;if(l==q||0==p[u>>h])x=d(x,u-x),void 0===t?t=x:(t+=String.fromCharCode(0),t+=x),x=u+b}X(n);return t},toWireType:function(n,q){"string"!=typeof q&&T("Cannot pass non-string to C++ string type "+c);var p=g(q),t=wc(4+p+b);F[t>>2]=p>>h;f(q,t+4,p+b);null!==n&&n.push(X,t);return t},argPackAdvance:8,readValueFromPointer:lb,ib:function(n){X(n)}})},g:function(a,b,c,d,f,g){jb[a]={name:S(b),rc:W(c,d),pb:W(f,g),Lc:[]}},d:function(a,b,c,d,f,g,k,h,n,q){jb[a].Lc.push({rd:S(b),
+F[n>>2],p=k(),t,x=n+4,l=0;l<=q;++l){var u=n+4+l*b;if(l==q||0==p[u>>h])x=d(x,u-x),void 0===t?t=x:(t+=String.fromCharCode(0),t+=x),x=u+b}X(n);return t},toWireType:function(n,q){"string"!=typeof q&&T("Cannot pass non-string to C++ string type "+c);var p=g(q),t=wc(4+p+b);F[t>>2]=p>>h;f(q,t+4,p+b);null!==n&&n.push(X,t);return t},argPackAdvance:8,readValueFromPointer:lb,ib:function(n){X(n)}})},f:function(a,b,c,d,f,g){jb[a]={name:S(b),rc:W(c,d),pb:W(f,g),Lc:[]}},d:function(a,b,c,d,f,g,k,h,n,q){jb[a].Lc.push({rd:S(b),
 zd:c,Sb:W(d,f),yd:g,Sd:k,Rd:W(h,n),Td:q})},ga:function(a,b){b=S(b);R(a,{Dd:!0,name:b,argPackAdvance:0,fromWireType:function(){},toWireType:function(){}})},o:function(){return Date.now()},aa:function(){return!0},k:function(a,b,c){a=ec(a);b=oc(b,"emval::as");var d=[],f=Sb(d);F[c>>2]=f;return b.toWireType(d,a)},A:function(a,b,c,d){a=rc[a];b=ec(b);c=qc(c);a(b,c,null,d)},na:dc,oa:function(a,b){var c=tc(a,b),d=c[0];b=d.name+"_$"+c.slice(1).map(function(p){return p.name}).join("_")+"$";var f=uc[b];if(void 0!==
 f)return f;f=["retType"];for(var g=[d],k="",h=0;h<a-1;++h)k+=(0!==h?", ":"")+"arg"+h,f.push("argType"+h),g.push(c[1+h]);var n="return function "+pb("methodCaller_"+b)+"(handle, name, destructors, args) {\n",q=0;for(h=0;h<a-1;++h)n+="    var arg"+h+" = argType"+h+".readValueFromPointer(args"+(q?"+"+q:"")+");\n",q+=c[h+1].argPackAdvance;n+="    var rv = handle[name]("+k+");\n";for(h=0;h<a-1;++h)c[h+1].deleteObject&&(n+="    argType"+h+".deleteObject(arg"+h+");\n");d.Dd||(n+="    return retType.toWireType(destructors, rv);\n");
 f.push(n+"};\n");a=ac(f).apply(null,g);f=sc(a);return uc[b]=f},z:function(a,b){a=ec(a);b=ec(b);return Sb(a[b])},C:function(a){4<a&&(Y[a].uc+=1)},B:function(){return Sb([])},ma:function(a){return Sb(qc(a))},la:function(a){var b=ec(a);kb(b);dc(a)},j:function(a,b){a=oc(a,"_emval_take_value");a=a.readValueFromPointer(b);return Sb(a)},ba:function(a,b){a=new Date(1E3*ib(a));E[b>>2]=a.getSeconds();E[b+4>>2]=a.getMinutes();E[b+8>>2]=a.getHours();E[b+12>>2]=a.getDate();E[b+16>>2]=a.getMonth();E[b+20>>2]=a.getFullYear()-
diff --git a/web/shared-worker/_generated/comm_query_executor.wasm b/web/shared-worker/_generated/comm_query_executor.wasm
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001

literal 0
Hc$@<O00001

diff --git a/web/shared-worker/queries/synced-metadata-queries.test.js b/web/shared-worker/queries/synced-metadata-queries.test.js
new file mode 100644
--- /dev/null
+++ b/web/shared-worker/queries/synced-metadata-queries.test.js
@@ -0,0 +1,98 @@
+// @flow
+
+import { syncedMetadataStoreOpsHandlers } from 'lib/ops/synced-metadata-store-ops.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';
+
+describe('SyncedMetadata Store queries', () => {
+  let queryExecutor: ?SQLiteQueryExecutor = null;
+  let dbModule: ?EmscriptenModule = null;
+
+  beforeAll(async () => {
+    dbModule = getDatabaseModule();
+  });
+
+  beforeEach(() => {
+    if (!dbModule) {
+      throw new Error('Database module is missing');
+    }
+    queryExecutor = new dbModule.SQLiteQueryExecutor(FILE_PATH);
+    if (!queryExecutor) {
+      throw new Error('SQLiteQueryExecutor is missing');
+    }
+    queryExecutor?.replaceSyncedMetadataEntry({
+      name: 'test_name_1',
+      data: 'test_data_1',
+    });
+    queryExecutor?.replaceSyncedMetadataEntry({
+      name: 'test_name_2',
+      data: 'test_data_2',
+    });
+    queryExecutor?.replaceSyncedMetadataEntry({
+      name: 'test_name_3',
+      data: 'test_data_3',
+    });
+  });
+
+  afterEach(() => {
+    if (!dbModule || !queryExecutor) {
+      return;
+    }
+
+    clearSensitiveData(dbModule, FILE_PATH, queryExecutor);
+  });
+
+  it('should return all synced metadata', () => {
+    const syncedMetadata = queryExecutor?.getAllSyncedMetadata();
+
+    expect(syncedMetadata).toHaveLength(3);
+  });
+
+  it('should remove all synced metadata', () => {
+    queryExecutor?.removeAllSyncedMetadata();
+    const syncedMetadata = queryExecutor?.getAllSyncedMetadata();
+
+    expect(syncedMetadata).toHaveLength(0);
+  });
+
+  it('should update synced metadata entry test_name_2', () => {
+    queryExecutor?.replaceSyncedMetadataEntry({
+      name: 'test_name_2',
+      data: 'updated_test_data_2',
+    });
+
+    const syncedMetadata = queryExecutor?.getAllSyncedMetadata();
+    if (!syncedMetadata) {
+      throw new Error('synced metadata not defined');
+    }
+
+    expect(syncedMetadata).toHaveLength(3);
+
+    const syncedMetadataFromDB =
+      syncedMetadataStoreOpsHandlers.translateClientDBData(syncedMetadata);
+
+    expect(syncedMetadataFromDB['test_name_2']).toBeDefined();
+    expect(syncedMetadataFromDB['test_name_2']).toBe('updated_test_data_2');
+  });
+
+  it('should remove synced metadata entry', () => {
+    queryExecutor?.removeSyncedMetadata(['test_name_1', 'test_name_3']);
+
+    const syncedMetadata = queryExecutor?.getAllSyncedMetadata();
+    if (!syncedMetadata) {
+      throw new Error('synced metadata not defined');
+    }
+
+    expect(syncedMetadata.length).toBe(1);
+
+    const syncedMetadataFromDB =
+      syncedMetadataStoreOpsHandlers.translateClientDBData(syncedMetadata);
+
+    expect(syncedMetadataFromDB['test_name_2']).toBeDefined();
+  });
+});
diff --git a/web/shared-worker/types/sqlite-query-executor.js b/web/shared-worker/types/sqlite-query-executor.js
--- a/web/shared-worker/types/sqlite-query-executor.js
+++ b/web/shared-worker/types/sqlite-query-executor.js
@@ -4,6 +4,7 @@
 import type { ClientDBIntegrityThreadHash } from 'lib/ops/integrity-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 { ClientDBSyncedMetadataEntry } from 'lib/ops/synced-metadata-store-ops.js';
 import type { ClientDBUserInfo } from 'lib/ops/user-store-ops.js';
 import type { ClientDBDraftInfo } from 'lib/types/draft-types.js';
 
@@ -122,6 +123,13 @@
   removeAllIntegrityThreadHashes(): void;
   getAllIntegrityThreadHashes(): ClientDBIntegrityThreadHash[];
 
+  replaceSyncedMetadataEntry(
+    syncedMetadataEntry: ClientDBSyncedMetadataEntry,
+  ): void;
+  removeSyncedMetadata(names: $ReadOnlyArray<string>): void;
+  removeAllSyncedMetadata(): void;
+  getAllSyncedMetadata(): ClientDBSyncedMetadataEntry[];
+
   beginTransaction(): void;
   commitTransaction(): void;
   rollbackTransaction(): void;