diff --git a/lib/actions/link-actions.js b/lib/actions/link-actions.js
--- a/lib/actions/link-actions.js
+++ b/lib/actions/link-actions.js
@@ -50,10 +50,12 @@
     };
   };
 
-function useVerifyInviteLink(keyserverOverride?: {
-  +keyserverID: string,
-  +keyserverURL: string,
-}): (
+function useVerifyInviteLink(
+  keyserverOverride?: ?{
+    +keyserverID: string,
+    +keyserverURL: string,
+  },
+): (
   request: InviteLinkVerificationRequest,
 ) => Promise<InviteLinkVerificationResponse> {
   const keyserverID = keyserverOverride?.keyserverID ?? ashoatKeyserverID;
diff --git a/lib/shared/invite-links.js b/lib/shared/invite-links.js
--- a/lib/shared/invite-links.js
+++ b/lib/shared/invite-links.js
@@ -1,5 +1,8 @@
 // @flow
 
+import blobService from '../facts/blob-service.js';
+import { getBlobFetchableURL } from '../utils/blob-service.js';
+
 const inviteLinkErrorMessages: { +[string]: string } = {
   invalid_characters: 'Link cannot contain any spaces or special characters.',
   offensive_words: 'No offensive or abusive words allowed.',
@@ -15,4 +18,36 @@
   return `invite_${secret}`;
 }
 
-export { inviteLinkErrorMessages, defaultErrorMessage, inviteLinkBlobHash };
+export type KeyserverOverride = {
+  +keyserverID: string,
+  +keyserverURL: string,
+};
+
+async function getKeyserverOverrideForAnInviteLink(
+  secret: string,
+): Promise<?KeyserverOverride> {
+  const blobURL = getBlobFetchableURL(inviteLinkBlobHash(secret));
+  const result = await fetch(blobURL, {
+    method: blobService.httpEndpoints.GET_BLOB.method,
+  });
+  if (result.status !== 200) {
+    return null;
+  }
+  const resultText = await result.text();
+  const resultObject = JSON.parse(resultText);
+  if (resultObject.keyserverID && resultObject.keyserverURL) {
+    const keyserverURL: string = resultObject.keyserverURL;
+    return {
+      keyserverID: resultObject.keyserverID,
+      keyserverURL: keyserverURL.replace(/\/$/, ''),
+    };
+  }
+  return null;
+}
+
+export {
+  inviteLinkErrorMessages,
+  defaultErrorMessage,
+  inviteLinkBlobHash,
+  getKeyserverOverrideForAnInviteLink,
+};
diff --git a/native/navigation/deep-links-context-provider.react.js b/native/navigation/deep-links-context-provider.react.js
--- a/native/navigation/deep-links-context-provider.react.js
+++ b/native/navigation/deep-links-context-provider.react.js
@@ -15,6 +15,8 @@
   type ParsedDeepLinkData,
 } from 'lib/facts/links.js';
 import { isLoggedIn } from 'lib/selectors/user-selectors.js';
+import { getKeyserverOverrideForAnInviteLink } from 'lib/shared/invite-links.js';
+import type { KeyserverOverride } from 'lib/shared/invite-links.js';
 import type { SetState } from 'lib/types/hook-types.js';
 import { useDispatchActionPromise } from 'lib/utils/redux-promise-utils.js';
 
@@ -79,9 +81,13 @@
   }, []);
   useOnFirstLaunchEffect('ANDROID_REFERRER', checkInstallReferrer);
 
+  const [keyserverOverride, setKeyserverOverride] =
+    React.useState<?KeyserverOverride>(undefined);
+  const inviteLinkSecret = React.useRef<?string>(null);
+
   const loggedIn = useSelector(isLoggedIn);
   const dispatchActionPromise = useDispatchActionPromise();
-  const validateLink = useVerifyInviteLink();
+  const validateLink = useVerifyInviteLink(keyserverOverride);
   const navigation = useNavigation();
   React.useEffect(() => {
     void (async () => {
@@ -91,6 +97,8 @@
       // We're setting this to null so that we ensure that each link click
       // results in at most one validation and navigation.
       setCurrentLink(null);
+      setKeyserverOverride(undefined);
+      inviteLinkSecret.current = null;
 
       const parsedData: ParsedDeepLinkData = parseDataFromDeepLink(currentLink);
       if (!parsedData) {
@@ -99,28 +107,64 @@
 
       if (parsedData.type === 'invite-link') {
         const { secret } = parsedData.data;
+        inviteLinkSecret.current = secret;
+        try {
+          const newKeyserverOverride =
+            await getKeyserverOverrideForAnInviteLink(secret);
+          setKeyserverOverride(newKeyserverOverride);
+        } catch (e) {
+          console.log('Error while downloading an invite link blob', e);
+          navigation.navigate<'InviteLinkModal'>({
+            name: InviteLinkModalRouteName,
+            params: {
+              invitationDetails: {
+                status: 'invalid',
+              },
+              secret,
+            },
+          });
+        }
+      } else if (parsedData.type === 'qr-code') {
+        navigation.navigate(SecondaryDeviceQRCodeScannerRouteName);
+      }
+    })();
+  }, [currentLink, loggedIn, navigation]);
+
+  React.useEffect(() => {
+    const secret = inviteLinkSecret.current;
+    if (keyserverOverride === undefined || !secret) {
+      return;
+    }
+    setKeyserverOverride(undefined);
+
+    void (async () => {
+      let result;
+      try {
         const validateLinkPromise = validateLink({ secret });
         void dispatchActionPromise(
           verifyInviteLinkActionTypes,
           validateLinkPromise,
         );
-        const result = await validateLinkPromise;
+        result = await validateLinkPromise;
         if (result.status === 'already_joined') {
           return;
         }
-
-        navigation.navigate<'InviteLinkModal'>({
-          name: InviteLinkModalRouteName,
-          params: {
-            invitationDetails: result,
-            secret,
-          },
-        });
-      } else if (parsedData.type === 'qr-code') {
-        navigation.navigate(SecondaryDeviceQRCodeScannerRouteName);
+      } catch (e) {
+        console.log(e);
+        result = {
+          status: 'invalid',
+        };
       }
+
+      navigation.navigate<'InviteLinkModal'>({
+        name: InviteLinkModalRouteName,
+        params: {
+          invitationDetails: result,
+          secret,
+        },
+      });
     })();
-  }, [currentLink, dispatchActionPromise, loggedIn, navigation, validateLink]);
+  }, [dispatchActionPromise, keyserverOverride, navigation, validateLink]);
 
   const contextValue = React.useMemo(
     () => ({
diff --git a/web/invite-links/invite-link-handler.react.js b/web/invite-links/invite-link-handler.react.js
--- a/web/invite-links/invite-link-handler.react.js
+++ b/web/invite-links/invite-link-handler.react.js
@@ -8,6 +8,8 @@
 } from 'lib/actions/link-actions.js';
 import { useModalContext } from 'lib/components/modal-provider.react.js';
 import { isLoggedIn } from 'lib/selectors/user-selectors.js';
+import { getKeyserverOverrideForAnInviteLink } from 'lib/shared/invite-links.js';
+import type { KeyserverOverride } from 'lib/shared/invite-links.js';
 import { useDispatchActionPromise } from 'lib/utils/redux-promise-utils.js';
 import { useDispatch } from 'lib/utils/redux-utils.js';
 
@@ -17,45 +19,80 @@
 
 function InviteLinkHandler(): null {
   const inviteSecret = useSelector(state => state.navInfo.inviteSecret);
+  const inviteLinkSecret = React.useRef<?string>(null);
+  const [keyserverOverride, setKeyserverOverride] =
+    React.useState<?KeyserverOverride>(undefined);
   const loggedIn = useSelector(isLoggedIn);
 
   const dispatchActionPromise = useDispatchActionPromise();
   const dispatch = useDispatch();
-  const validateLink = useVerifyInviteLink();
   const { pushModal } = useModalContext();
   React.useEffect(() => {
-    if (!inviteSecret || !loggedIn) {
+    void (async () => {
+      if (!inviteSecret || !loggedIn) {
+        return;
+      }
+      dispatch({
+        type: updateNavInfoActionType,
+        payload: { inviteSecret: null },
+      });
+      setKeyserverOverride(undefined);
+      inviteLinkSecret.current = inviteSecret;
+
+      try {
+        const newKeyserverOverride =
+          await getKeyserverOverrideForAnInviteLink(inviteSecret);
+        setKeyserverOverride(newKeyserverOverride);
+      } catch (e) {
+        console.error('Error while downloading an invite link blob', e);
+        pushModal(
+          <AcceptInviteModal
+            verificationResponse={{
+              status: 'invalid',
+            }}
+            inviteSecret={inviteSecret}
+          />,
+        );
+      }
+    })();
+  }, [dispatch, inviteSecret, loggedIn, pushModal]);
+
+  const validateLink = useVerifyInviteLink(keyserverOverride);
+  React.useEffect(() => {
+    const secret = inviteLinkSecret.current;
+    if (keyserverOverride === undefined || !secret) {
       return;
     }
-    dispatch({
-      type: updateNavInfoActionType,
-      payload: { inviteSecret: null },
-    });
-    const validateLinkPromise = validateLink({ secret: inviteSecret });
-    void dispatchActionPromise(
-      verifyInviteLinkActionTypes,
-      validateLinkPromise,
-    );
+    setKeyserverOverride(undefined);
+
     void (async () => {
-      const result = await validateLinkPromise;
-      if (result.status === 'already_joined') {
-        return;
+      let result;
+      try {
+        const validateLinkPromise = validateLink({ secret });
+        void dispatchActionPromise(
+          verifyInviteLinkActionTypes,
+          validateLinkPromise,
+        );
+
+        result = await validateLinkPromise;
+        if (result.status === 'already_joined') {
+          return;
+        }
+      } catch (e) {
+        console.error('Error while verifying an invite link', e);
+        result = {
+          status: 'invalid',
+        };
       }
+
       pushModal(
         <AcceptInviteModal
           verificationResponse={result}
-          inviteSecret={inviteSecret}
+          inviteSecret={secret}
         />,
       );
     })();
-  }, [
-    dispatch,
-    dispatchActionPromise,
-    inviteSecret,
-    loggedIn,
-    pushModal,
-    validateLink,
-  ]);
+  }, [dispatchActionPromise, keyserverOverride, pushModal, validateLink]);
 
   return null;
 }