diff --git a/native/avatars/avatar-hooks.js b/native/avatars/avatar-hooks.js
--- a/native/avatars/avatar-hooks.js
+++ b/native/avatars/avatar-hooks.js
@@ -7,16 +7,24 @@
 import { useSafeAreaInsets } from 'react-native-safe-area-context';
 
 import { uploadMultimedia } from 'lib/actions/upload-actions.js';
+import {
+  updateUserAvatar,
+  updateUserAvatarActionTypes,
+} from 'lib/actions/user-actions.js';
 import {
   extensionFromFilename,
   filenameFromPathOrURI,
 } from 'lib/media/file-utils.js';
+import type { ImageAvatarDBContent } from 'lib/types/avatar-types.js';
 import type {
   MediaLibrarySelection,
   MediaMissionFailure,
   UploadMultimediaResult,
 } from 'lib/types/media-types.js';
-import { useServerCall } from 'lib/utils/action-utils.js';
+import {
+  useDispatchActionPromise,
+  useServerCall,
+} from 'lib/utils/action-utils.js';
 
 import SWMansionIcon from '../components/swmansion-icon.react.js';
 import { getCompatibleMediaURI } from '../media/identifier-utils.js';
@@ -67,11 +75,8 @@
   return processSelectedMedia;
 }
 
-function useSelectAndUploadFromGallery(): () => Promise<void> {
-  const processSelectedMedia = useProcessSelectedMedia();
-  const uploadProcessedMedia = useUploadProcessedMedia();
-
-  const selectAndUploadFromGallery = React.useCallback(async () => {
+function useSelectFromGallery(): () => Promise<?MediaLibrarySelection> {
+  const selectFromGallery = React.useCallback(async () => {
     try {
       const { assets, canceled } = await ImagePicker.launchImageLibraryAsync({
         mediaTypes: ImagePicker.MediaTypeOptions.Images,
@@ -105,18 +110,72 @@
         retries: 0,
       };
 
-      const processedMedia = await processSelectedMedia(selection);
-      if (!processedMedia.success) {
-        return;
-      }
-      await uploadProcessedMedia(processedMedia);
+      return selection;
     } catch (e) {
       console.log(e);
+      return undefined;
+    }
+  }, []);
+
+  return selectFromGallery;
+}
+
+function useSelectFromGalleryAndUpdateUserAvatar(): () => Promise<void> {
+  const dispatchActionPromise = useDispatchActionPromise();
+  const updateUserAvatarCall = useServerCall(updateUserAvatar);
+
+  const selectFromGallery = useSelectFromGallery();
+  const processSelectedMedia = useProcessSelectedMedia();
+  const uploadProcessedMedia = useUploadProcessedMedia();
+
+  const selectFromGalleryAndUpdateUserAvatar = React.useCallback(async () => {
+    const selection: ?MediaLibrarySelection = await selectFromGallery();
+    if (!selection) {
+      console.log('MEDIA_SELECTION_FAILED');
       return;
     }
-  }, [processSelectedMedia, uploadProcessedMedia]);
 
-  return selectAndUploadFromGallery;
+    const processedMedia = await processSelectedMedia(selection);
+    if (!processedMedia.success) {
+      console.log('MEDIA_PROCESSING_FAILED');
+      // TODO (atul): Clean up any temporary files.
+      return;
+    }
+
+    let uploadedMedia: ?UploadMultimediaResult;
+    try {
+      uploadedMedia = await uploadProcessedMedia(processedMedia);
+      // TODO (atul): Clean up any temporary files.
+    } catch {
+      console.log('MEDIA_UPLOAD_FAILED');
+      // TODO (atul): Clean up any temporary files.
+      return;
+    }
+
+    if (!uploadedMedia) {
+      console.log('MEDIA_UPLOAD_FAILED');
+      // TODO (atul): Clean up any temporary files.
+      return;
+    }
+
+    const imageAvatarUpdateRequest: ImageAvatarDBContent = {
+      type: 'image',
+      uploadID: uploadedMedia.id,
+    };
+
+    dispatchActionPromise(
+      updateUserAvatarActionTypes,
+      updateUserAvatarCall(imageAvatarUpdateRequest),
+    );
+  }, [
+    dispatchActionPromise,
+    processSelectedMedia,
+    selectFromGallery,
+    updateUserAvatarCall,
+    uploadProcessedMedia,
+  ]);
+
+  return selectFromGalleryAndUpdateUserAvatar;
 }
 
 type ShowAvatarActionSheetOptions = {
@@ -215,6 +274,6 @@
 export {
   useUploadProcessedMedia,
   useProcessSelectedMedia,
-  useSelectAndUploadFromGallery,
   useShowAvatarActionSheet,
+  useSelectFromGalleryAndUpdateUserAvatar,
 };
diff --git a/native/avatars/edit-thread-avatar.react.js b/native/avatars/edit-thread-avatar.react.js
--- a/native/avatars/edit-thread-avatar.react.js
+++ b/native/avatars/edit-thread-avatar.react.js
@@ -6,7 +6,7 @@
 import type { RawThreadInfo, ThreadInfo } from 'lib/types/thread-types.js';
 
 import {
-  useSelectAndUploadFromGallery,
+  useSelectFromGalleryAndUpdateUserAvatar,
   useShowAvatarActionSheet,
 } from './avatar-hooks.js';
 import EditAvatarBadge from './edit-avatar-badge.react.js';
@@ -20,14 +20,15 @@
 function EditThreadAvatar(props: Props): React.Node {
   const { threadInfo, onPressEmojiAvatarFlow, disabled } = props;
 
-  const selectAndUploadFromGallery = useSelectAndUploadFromGallery();
+  const selectFromGalleryAndUpdateUserAvatar =
+    useSelectFromGalleryAndUpdateUserAvatar();
 
   const actionSheetConfig = React.useMemo(
     () => [
       { id: 'emoji', onPress: onPressEmojiAvatarFlow },
-      { id: 'image', onPress: selectAndUploadFromGallery },
+      { id: 'image', onPress: selectFromGalleryAndUpdateUserAvatar },
     ],
-    [onPressEmojiAvatarFlow, selectAndUploadFromGallery],
+    [onPressEmojiAvatarFlow, selectFromGalleryAndUpdateUserAvatar],
   );
 
   const showAvatarActionSheet = useShowAvatarActionSheet(actionSheetConfig);
diff --git a/native/avatars/edit-user-avatar.react.js b/native/avatars/edit-user-avatar.react.js
--- a/native/avatars/edit-user-avatar.react.js
+++ b/native/avatars/edit-user-avatar.react.js
@@ -4,7 +4,7 @@
 import { TouchableOpacity } from 'react-native';
 
 import {
-  useSelectAndUploadFromGallery,
+  useSelectFromGalleryAndUpdateUserAvatar,
   useShowAvatarActionSheet,
 } from './avatar-hooks.js';
 import EditAvatarBadge from './edit-avatar-badge.react.js';
@@ -18,14 +18,15 @@
 function EditUserAvatar(props: Props): React.Node {
   const { userID, onPressEmojiAvatarFlow, disabled } = props;
 
-  const selectAndUploadFromGallery = useSelectAndUploadFromGallery();
+  const selectFromGalleryAndUpdateUserAvatar =
+    useSelectFromGalleryAndUpdateUserAvatar();
 
   const actionSheetConfig = React.useMemo(
     () => [
       { id: 'emoji', onPress: onPressEmojiAvatarFlow },
-      { id: 'image', onPress: selectAndUploadFromGallery },
+      { id: 'image', onPress: selectFromGalleryAndUpdateUserAvatar },
     ],
-    [onPressEmojiAvatarFlow, selectAndUploadFromGallery],
+    [onPressEmojiAvatarFlow, selectFromGalleryAndUpdateUserAvatar],
   );
 
   const showAvatarActionSheet = useShowAvatarActionSheet(actionSheetConfig);