diff --git a/lib/tunnelbroker/tunnelbroker-context.js b/lib/tunnelbroker/tunnelbroker-context.js
--- a/lib/tunnelbroker/tunnelbroker-context.js
+++ b/lib/tunnelbroker/tunnelbroker-context.js
@@ -62,6 +62,7 @@
     }
   | {
       +connected: false,
+      +retryCount: number,
     };
 
 type TunnelbrokerContextType = {
@@ -87,6 +88,8 @@
   +secondaryTunnelbrokerConnection?: SecondaryTunnelbrokerConnection,
 };
 
+const clientTunnelbrokerSocketReconnectDelay = 2000; // ms
+
 function getTunnelbrokerDeviceType(): TunnelbrokerDeviceTypes {
   return isWebPlatform(getConfig().platformDetails.platform) ? 'web' : 'mobile';
 }
@@ -142,7 +145,7 @@
     React.useRef<?TunnelbrokerInitializationMessage>(null);
 
   const [socketState, setSocketState] = React.useState<TunnelbrokerSocketState>(
-    { connected: false },
+    { connected: false, retryCount: 0 },
   );
   const listeners = React.useRef<Set<TunnelbrokerSocketListener>>(new Set());
   const socket = React.useRef<?WebSocket>(null);
@@ -165,7 +168,7 @@
     stopHeartbeatTimeout();
     heartbeatTimeoutID.current = setTimeout(() => {
       socket.current?.close();
-      setSocketState({ connected: false });
+      setSocketState({ connected: false, retryCount: 0 });
     }, tunnelbrokerHeartbeatTimeout);
   }, [stopHeartbeatTimeout]);
 
@@ -220,10 +223,25 @@
 
         tunnelbrokerSocket.onclose = () => {
           // this triggers the effect hook again and reconnect
-          setSocketState({ connected: false });
+          setSocketState(prev => ({
+            connected: false,
+            retryCount: prev.connected ? 0 : prev.retryCount,
+          }));
           onClose?.();
           socket.current = null;
           console.log('Connection to Tunnelbroker closed');
+          setTimeout(() => {
+            if (!socket.current && initMessage) {
+              console.log(
+                'Retrying Tunnelbroker connection. Attempt:',
+                socketState.retryCount + 1,
+              );
+              setSocketState(prev => ({
+                connected: false,
+                retryCount: prev.connected ? 0 : prev.retryCount + 1,
+              }));
+            }
+          }, clientTunnelbrokerSocketReconnectDelay);
         };
         tunnelbrokerSocket.onerror = e => {
           console.log('Tunnelbroker socket error:', e.message);
@@ -272,7 +290,7 @@
                 'received ConnectionInitializationResponse with status: Success for already connected socket',
               );
             } else {
-              setSocketState({ connected: false });
+              setSocketState({ connected: false, retryCount: 0 });
               console.log(
                 'creating session with Tunnelbroker error:',
                 message.status.data,
@@ -320,6 +338,7 @@
     onClose,
     createInitMessage,
     socketState.connected,
+    socketState.retryCount,
   ]);
 
   const sendMessage: (request: DeviceToTunnelbrokerRequest) => Promise<void> =
diff --git a/native/push/push-handler.react.js b/native/push/push-handler.react.js
--- a/native/push/push-handler.react.js
+++ b/native/push/push-handler.react.js
@@ -141,6 +141,7 @@
       }
     | {
         +connected: false,
+        +retryCount: number,
       },
 };
 type State = {