diff --git a/services/backup/src/Reactors/server/AddAttachmentsUtility.cpp b/services/backup/src/Reactors/server/AddAttachmentsUtility.cpp
--- a/services/backup/src/Reactors/server/AddAttachmentsUtility.cpp
+++ b/services/backup/src/Reactors/server/AddAttachmentsUtility.cpp
@@ -1,5 +1,7 @@
 #include "AddAttachmentsUtility.h"
 
+#include "blob_client/src/lib.rs.h"
+
 #include <glog/logging.h>
 
 #include "BackupItem.h"
@@ -49,7 +51,7 @@
       }
       database::DatabaseManager::getInstance().putLogItem(*logItem);
     }
-  } catch (std::runtime_error &e) {
+  } catch (std::exception &e) {
     LOG(ERROR) << e.what();
     status = grpc::Status(grpc::StatusCode::INTERNAL, e.what());
   }
@@ -72,10 +74,23 @@
   // put into S3
   std::condition_variable blobPutDoneCV;
   std::mutex blobPutDoneCVMutex;
-  // todo:blob perform put
-  // todo:blob perform put:add chunk (std::move(data))
-  // todo:blob perform put:add chunk ("")
-  // todo:blob perform put:wait for completion
+  put_client_initialize_cxx();
+  put_client_write_cxx(
+      tools::getBlobPutField(blob::PutRequest::DataCase::kHolder),
+      holder.c_str());
+  put_client_blocking_read_cxx();
+  put_client_write_cxx(
+      tools::getBlobPutField(blob::PutRequest::DataCase::kBlobHash),
+      newLogItem->getDataHash().c_str());
+  rust::String responseStr = put_client_blocking_read_cxx();
+  // data exists?
+  if (!(bool)tools::charPtrToInt(responseStr.c_str())) {
+    put_client_write_cxx(
+        tools::getBlobPutField(blob::PutRequest::DataCase::kDataChunk),
+        std::move(data).c_str());
+    put_client_blocking_read_cxx();
+  }
+  put_client_terminate_cxx();
   return newLogItem;
 }