diff --git a/3d_party/rapidjson/include/rapidjson/reader.h b/3d_party/rapidjson/include/rapidjson/reader.h
index 206b261417b9bc15594fec165685339123b639c0..9b28b268530ca29101b4e351fd4228899a223e4e 100644
--- a/3d_party/rapidjson/include/rapidjson/reader.h
+++ b/3d_party/rapidjson/include/rapidjson/reader.h
@@ -1223,8 +1223,7 @@ class GenericReader {
                     }
                     i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
                     significandDigit++;
-                }
-            else
+                } else
                 while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
                     if (RAPIDJSON_UNLIKELY(i >= 429496729)) { // 2^32 - 1 = 4294967295
                         if (RAPIDJSON_LIKELY(i != 429496729 || s.Peek() > '5')) {
@@ -1265,8 +1264,7 @@ class GenericReader {
                         }
                     i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
                     significandDigit++;
-                }
-            else
+                } else
                 while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
                     if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999))) // 2^64 - 1 = 18446744073709551615
                         if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5')) {
diff --git a/common/cpp/include/common/error.h b/common/cpp/include/common/error.h
index e4602afd5a948194d8d7eb2214a6c40d69945c15..71c32b6e80c816d207bb6639952419c70d67e7de 100644
--- a/common/cpp/include/common/error.h
+++ b/common/cpp/include/common/error.h
@@ -146,11 +146,11 @@ inline Error TextErrorWithType(const std::string& error, ErrorType error_type) {
 
 namespace ErrorTemplates {
 auto const kMemoryAllocationError = SimpleErrorTemplate {
-    "kMemoryAllocationError", ErrorType::kMemoryAllocationError
-};
+                                        "kMemoryAllocationError", ErrorType::kMemoryAllocationError
+                                    };
 auto const kEndOfFile = SimpleErrorTemplate {
-    "End of file", ErrorType::kEndOfFile
-};
+                            "End of file", ErrorType::kEndOfFile
+                        };
 
 }
 
diff --git a/common/cpp/include/common/io_error.h b/common/cpp/include/common/io_error.h
index 40c9d4dd7e2c62ad73531d0a4aa18ebbbdeff2d0..db3606b3b0a8ea5276a1489fc1b703168f96b379 100644
--- a/common/cpp/include/common/io_error.h
+++ b/common/cpp/include/common/io_error.h
@@ -72,68 +72,68 @@ static inline std::ostream& operator<<(std::ostream& os, const IOErrorTemplate&
 
 namespace IOErrorTemplates {
 auto const kUnknownIOError = IOErrorTemplate {
-    "Unknown Error", IOErrorType::kUnknownIOError
-};
+                                 "Unknown Error", IOErrorType::kUnknownIOError
+                             };
 
 auto const kFileNotFound = IOErrorTemplate {
-    "No such file or directory", IOErrorType::kFileNotFound
-};
+                               "No such file or directory", IOErrorType::kFileNotFound
+                           };
 auto const kReadError = IOErrorTemplate {
-    "Read error", IOErrorType::kReadError
-};
+                            "Read error", IOErrorType::kReadError
+                        };
 auto const kBadFileNumber = IOErrorTemplate {
-    "Bad file number", IOErrorType::kBadFileNumber
-};
+                                "Bad file number", IOErrorType::kBadFileNumber
+                            };
 auto const kResourceTemporarilyUnavailable = IOErrorTemplate {
-    "Resource temporarily unavailable", IOErrorType::kResourceTemporarilyUnavailable
-};
+                                                 "Resource temporarily unavailable", IOErrorType::kResourceTemporarilyUnavailable
+                                             };
 auto const kPermissionDenied = IOErrorTemplate {
-    "Permission denied", IOErrorType::kPermissionDenied
-};
+                                   "Permission denied", IOErrorType::kPermissionDenied
+                               };
 auto const kUnsupportedAddressFamily = IOErrorTemplate {
-    "Unsupported address family", IOErrorType::kUnsupportedAddressFamily
-};
+                                           "Unsupported address family", IOErrorType::kUnsupportedAddressFamily
+                                       };
 auto const kInvalidAddressFormat = IOErrorTemplate {
-    "Invalid address format", IOErrorType::kInvalidAddressFormat
-};
+                                       "Invalid address format", IOErrorType::kInvalidAddressFormat
+                                   };
 auto const kAddressAlreadyInUse = IOErrorTemplate {
-    "Address already in use", IOErrorType::kAddressAlreadyInUse
-};
+                                      "Address already in use", IOErrorType::kAddressAlreadyInUse
+                                  };
 auto const kConnectionRefused = IOErrorTemplate {
-    "Connection refused", IOErrorType::kConnectionRefused
-};
+                                    "Connection refused", IOErrorType::kConnectionRefused
+                                };
 auto const kConnectionResetByPeer = IOErrorTemplate {
-    "kConnectionResetByPeer", IOErrorType::kConnectionResetByPeer
-};
+                                        "kConnectionResetByPeer", IOErrorType::kConnectionResetByPeer
+                                    };
 auto const kTimeout = IOErrorTemplate {
-    "kTimeout", IOErrorType::kTimeout
-};
+                          "kTimeout", IOErrorType::kTimeout
+                      };
 auto const kFileAlreadyExists = IOErrorTemplate {
-    "kFileAlreadyExists", IOErrorType::kFileAlreadyExists
-};
+                                    "kFileAlreadyExists", IOErrorType::kFileAlreadyExists
+                                };
 auto const kNoSpaceLeft = IOErrorTemplate {
-    "kNoSpaceLeft", IOErrorType::kNoSpaceLeft
-};
+                              "kNoSpaceLeft", IOErrorType::kNoSpaceLeft
+                          };
 auto const kSocketOperationOnNonSocket = IOErrorTemplate {
-    "kSocketOperationOnNonSocket", IOErrorType::kSocketOperationOnNonSocket
-};
+                                             "kSocketOperationOnNonSocket", IOErrorType::kSocketOperationOnNonSocket
+                                         };
 auto const kInvalidMemoryAddress = IOErrorTemplate {
-    "kInvalidMemoryAddress", IOErrorType::kInvalidMemoryAddress
-};
+                                       "kInvalidMemoryAddress", IOErrorType::kInvalidMemoryAddress
+                                   };
 auto const kUnableToResolveHostname = IOErrorTemplate {
-    "kUnableToResolveHostname", IOErrorType::kUnableToResolveHostname
-};
+                                          "kUnableToResolveHostname", IOErrorType::kUnableToResolveHostname
+                                      };
 auto const kSocketOperationUnknownAtLevel =  IOErrorTemplate {
-    "kSocketOperationUnknownAtLevel", IOErrorType::kSocketOperationUnknownAtLevel
-};
+                                                 "kSocketOperationUnknownAtLevel", IOErrorType::kSocketOperationUnknownAtLevel
+                                             };
 
 auto const kSocketOperationValueOutOfBound =  IOErrorTemplate {
-    "kSocketOperationValueOutOfBound", IOErrorType::kSocketOperationValueOutOfBound
-};
+                                                  "kSocketOperationValueOutOfBound", IOErrorType::kSocketOperationValueOutOfBound
+                                              };
 
 auto const kAddressNotValid =  IOErrorTemplate {
-    "Address not valid", IOErrorType::kAddressNotValid
-};
+                                   "Address not valid", IOErrorType::kAddressNotValid
+                               };
 
 }
 
diff --git a/common/cpp/include/unittests/MockDatabase.h b/common/cpp/include/unittests/MockDatabase.h
new file mode 100644
index 0000000000000000000000000000000000000000..b1bb10efc1915a9707f7b30fa85585673fc72f37
--- /dev/null
+++ b/common/cpp/include/unittests/MockDatabase.h
@@ -0,0 +1,37 @@
+#ifndef HIDRA2_MOCKDATABASE_H
+#define HIDRA2_MOCKDATABASE_H
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "database/database.h"
+#include "common/error.h"
+
+namespace hidra2 {
+
+class MockDatabase : public Database {
+  public:
+    Error Connect(const std::string& address, const std::string& database,
+                  const std::string& collection ) override {
+        return Error{Connect_t(address, database, collection)};
+
+    }
+    Error Insert(const FileInfo& file, bool ignore_duplicates) const override {
+        return Error{Insert_t(file, ignore_duplicates)};
+    }
+
+    MOCK_METHOD3(Connect_t, SimpleError * (const std::string&, const std::string&, const std::string&));
+    MOCK_CONST_METHOD2(Insert_t, SimpleError * (const FileInfo&, bool));
+
+    // stuff to test db destructor is called and avoid "uninteresting call" messages
+    MOCK_METHOD0(Die, void());
+    virtual ~MockDatabase() override {
+        if (check_destructor)
+            Die();
+    }
+    bool check_destructor{false};
+};
+
+}
+
+#endif //HIDRA2_MOCKDATABASE_H
diff --git a/common/cpp/src/http_client/CMakeLists.txt b/common/cpp/src/http_client/CMakeLists.txt
index b274c9319e20e484c12d9f22f8668fda3f6a39f9..42e3f0659a252680128db9bf06b3c731f290ec05 100644
--- a/common/cpp/src/http_client/CMakeLists.txt
+++ b/common/cpp/src/http_client/CMakeLists.txt
@@ -1,7 +1,7 @@
 set(TARGET_NAME curl_http_client)
 set(SOURCE_FILES
         curl_http_client.cpp
-        )
+        ../../include/unittests/MockDatabase.h)
 
 
 ################################
diff --git a/producer/api/include/producer/producer_error.h b/producer/api/include/producer/producer_error.h
index cdcf69a742ad54dd6d248f654e56953ce6faf701..decf910834fe976b84b787e61e476bb22e17c8e1 100644
--- a/producer/api/include/producer/producer_error.h
+++ b/producer/api/include/producer/producer_error.h
@@ -53,23 +53,23 @@ class ProducerErrorTemplate : public SimpleErrorTemplate {
 
 namespace ProducerErrorTemplates {
 auto const kAlreadyConnected = ProducerErrorTemplate {
-    "Already connected", ProducerErrorType::kAlreadyConnected
-};
+                                   "Already connected", ProducerErrorType::kAlreadyConnected
+                               };
 auto const kConnectionNotReady = ProducerErrorTemplate {
-    "Connection not ready", ProducerErrorType::kConnectionNotReady
-};
+                                     "Connection not ready", ProducerErrorType::kConnectionNotReady
+                                 };
 
 auto const kFileTooLarge = ProducerErrorTemplate {
-    "File too large", ProducerErrorType::kFileTooLarge
-};
+                               "File too large", ProducerErrorType::kFileTooLarge
+                           };
 
 auto const kFileIdAlreadyInUse = ProducerErrorTemplate {
-    "File already in use", ProducerErrorType::kFileIdAlreadyInUse
-};
+                                     "File already in use", ProducerErrorType::kFileIdAlreadyInUse
+                                 };
 
 auto const kUnknownServerError = ProducerErrorTemplate {
-    "Unknown server error", ProducerErrorType::kUnknownServerError
-};
+                                     "Unknown server error", ProducerErrorType::kUnknownServerError
+                                 };
 
 
 };
diff --git a/receiver/CMakeLists.txt b/receiver/CMakeLists.txt
index 6f5ee995cbb7c61e4178e5c3687602836b493292..a5d795a7ccf763b0735c11fc5c603bc6df582889 100644
--- a/receiver/CMakeLists.txt
+++ b/receiver/CMakeLists.txt
@@ -7,7 +7,8 @@ set(SOURCE_FILES
         src/request_handler_file_write.cpp
         src/statistics.cpp
         src/statistics_sender_influx_db.cpp
-        src/receiver_config.cpp src/receiver_config.h)
+        src/receiver_config.cpp
+        src/request_handler_db_write.cpp)
 
 
 ################################
@@ -19,7 +20,7 @@ add_library(${TARGET_NAME} STATIC ${SOURCE_FILES} $<TARGET_OBJECTS:system_io> $<
          $<TARGET_OBJECTS:json_parser>)
 set_target_properties(${TARGET_NAME} PROPERTIES LINKER_LANGUAGE CXX)
 target_include_directories(${TARGET_NAME} PUBLIC ${HIDRA2_CXX_COMMON_INCLUDE_DIR} ${CURL_INCLUDE_DIRS})
-target_link_libraries(${TARGET_NAME} ${CURL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
+target_link_libraries(${TARGET_NAME} ${CURL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} database)
 
 
 add_executable(${TARGET_NAME}-bin src/main.cpp)
@@ -38,7 +39,9 @@ set(TEST_SOURCE_FILES
         unittests/test_statistics.cpp
         unittests/test_config.cpp
         unittests/test_request.cpp
+        unittests/test_request_factory.cpp
         unittests/test_request_handler_file_write.cpp
+        unittests/test_request_handler_db_writer.cpp
         unittests/test_statistics_sender_influx_db.cpp
         unittests/mock_receiver_config.cpp
         )
diff --git a/receiver/src/receiver_config.cpp b/receiver/src/receiver_config.cpp
index ba4e4b250daea114344e47c6c8c6a300e9f6ab0d..984218ee0b60eef9f854962db0ff116a2d223396 100644
--- a/receiver/src/receiver_config.cpp
+++ b/receiver/src/receiver_config.cpp
@@ -17,6 +17,10 @@ Error ReceiverConfigFactory::SetConfigFromFile(std::string file_name) {
     (err = parser.GetString("MonitorDbAddress", &config.monitor_db_uri)) ||
     (err = parser.GetUInt64("ListenPort", &config.listen_port)) ||
     (err = parser.GetBool("WriteToDisk", &config.write_to_disk)) ||
+    (err = parser.GetBool("WriteToDb", &config.write_to_db)) ||
+    (err = parser.GetString("BrokerDbAddress", &config.broker_db_uri)) ||
+    (err = parser.GetString("BrokerDbName", &config.broker_db_name)) ||
+
     (err = parser.GetString("MonitorDbName", &config.monitor_db_name));
     return err;
 }
diff --git a/receiver/src/receiver_config.h b/receiver/src/receiver_config.h
index f0aa92adf8e6317c698f2a5621de6407ad25d4c2..e348dc704ea13276fe16da498c92d3710a134969 100644
--- a/receiver/src/receiver_config.h
+++ b/receiver/src/receiver_config.h
@@ -9,8 +9,12 @@ namespace hidra2 {
 struct ReceiverConfig {
     std::string monitor_db_uri;
     std::string monitor_db_name;
+    std::string broker_db_uri;
+    std::string broker_db_name;
     uint64_t listen_port = 0;
     bool write_to_disk = false;
+    bool write_to_db = false;
+
 };
 
 const ReceiverConfig* GetReceiverConfig();
diff --git a/receiver/src/receiver_error.h b/receiver/src/receiver_error.h
index 42eb039d8e5720e23a98dfded74973b788233235..63da34f6fe47518ca7d55278a47e82b0f302d7ed 100644
--- a/receiver/src/receiver_error.h
+++ b/receiver/src/receiver_error.h
@@ -50,11 +50,11 @@ class ReceiverErrorTemplate : public SimpleErrorTemplate {
 
 namespace ReceiverErrorTemplates {
 auto const kInvalidOpCode = ReceiverErrorTemplate {
-    "Invalid Opcode", ReceiverErrorType::kInvalidOpCode
-};
+                                "Invalid Opcode", ReceiverErrorType::kInvalidOpCode
+                            };
 auto const kBadRequest = ReceiverErrorTemplate {
-    "Bad request", ReceiverErrorType::kBadRequest
-};
+                             "Bad request", ReceiverErrorType::kBadRequest
+                         };
 
 };
 }
diff --git a/receiver/src/request.cpp b/receiver/src/request.cpp
index 19ac5ca8a7dfd394f652412dcdb56e069ae0b54c..30862496da685bada5aff6ad2e456bc284e9adcb 100644
--- a/receiver/src/request.cpp
+++ b/receiver/src/request.cpp
@@ -60,6 +60,11 @@ void Request::AddHandler(const RequestHandler* handler) {
 }
 
 
+uint64_t Request::GetDataID() const {
+    return request_header_.data_id;
+}
+
+
 uint64_t Request::GetDataSize() const {
     return request_header_.data_size;
 }
@@ -72,7 +77,6 @@ std::string Request::GetFileName() const {
     return std::to_string(request_header_.data_id) + ".bin";
 }
 
-
 std::unique_ptr<Request> RequestFactory::GenerateRequest(const GenericNetworkRequestHeader&
         request_header, SocketDescriptor socket_fd,
         Error* err) const noexcept {
@@ -80,16 +84,22 @@ std::unique_ptr<Request> RequestFactory::GenerateRequest(const GenericNetworkReq
     switch (request_header.op_code) {
     case Opcode::kNetOpcodeSendData: {
         auto request = std::unique_ptr<Request> {new Request{request_header, socket_fd}};
+
         if (GetReceiverConfig()->write_to_disk) {
             request->AddHandler(&request_handler_filewrite_);
         }
+
+        if (GetReceiverConfig()->write_to_db) {
+            request->AddHandler(&request_handler_dbwrite_);
+        }
+
         return request;
     }
     default:
         *err = ReceiverErrorTemplates::kInvalidOpCode.Generate();
         return nullptr;
     }
-
 }
 
+
 }
\ No newline at end of file
diff --git a/receiver/src/request.h b/receiver/src/request.h
index b32a9e580401fa666c3fbcc404f03c68f8fb8ae8..5b297b83d2b5a67290495148bea62051d834e025 100644
--- a/receiver/src/request.h
+++ b/receiver/src/request.h
@@ -6,6 +6,7 @@
 #include "io/io.h"
 #include "request_handler.h"
 #include "request_handler_file_write.h"
+#include "request_handler_db_write.h"
 #include "statistics.h"
 
 namespace hidra2 {
@@ -20,6 +21,7 @@ class Request {
     void AddHandler(const RequestHandler*);
     const RequestHandlerList& GetListHandlers() const;
     virtual uint64_t GetDataSize() const;
+    virtual uint64_t GetDataID() const;
     virtual std::string GetFileName() const;
 
     virtual const FileData& GetData() const;
@@ -39,8 +41,10 @@ class RequestFactory {
                                                      SocketDescriptor socket_fd, Error* err) const noexcept;
   private:
     RequestHandlerFileWrite request_handler_filewrite_;
+    RequestHandlerDbWrite request_handler_dbwrite_;
 };
 
 }
 
 #endif //HIDRA2_REQUEST_H
+
diff --git a/receiver/src/request_handler_db_write.cpp b/receiver/src/request_handler_db_write.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b3b73bfb0d8d8f47ca9ae73630ca802c45fa558d
--- /dev/null
+++ b/receiver/src/request_handler_db_write.cpp
@@ -0,0 +1,43 @@
+#include "request_handler_db_write.h"
+#include "request.h"
+#include "receiver_config.h"
+
+namespace hidra2 {
+
+Error RequestHandlerDbWrite::ProcessRequest(const Request& request) const {
+    if (Error err = ConnectToDbIfNeeded() ) {
+        return err;
+    }
+
+    FileInfo file_info;
+    file_info.name = request.GetFileName();
+    file_info.size = request.GetDataSize();
+    file_info.id = request.GetDataID();
+    return db_client__->Insert(file_info, false);
+
+}
+
+RequestHandlerDbWrite::RequestHandlerDbWrite()  {
+    DatabaseFactory factory;
+    Error err;
+    db_client__ = factory.Create(&err);
+}
+
+StatisticEntity RequestHandlerDbWrite::GetStatisticEntity() const {
+    return StatisticEntity::kDatabase;
+}
+
+Error RequestHandlerDbWrite::ConnectToDbIfNeeded() const {
+    if (!connected_to_db) {
+        Error err = db_client__->Connect(GetReceiverConfig()->broker_db_uri, GetReceiverConfig()->broker_db_name,
+                                         kDBCollectionName);
+        if (err) {
+            return err;
+        }
+        connected_to_db = true;
+    }
+    return nullptr;
+}
+
+
+}
\ No newline at end of file
diff --git a/receiver/src/request_handler_db_write.h b/receiver/src/request_handler_db_write.h
new file mode 100644
index 0000000000000000000000000000000000000000..ddd57350abd5cb4bb35c6a20935c479dd252dbf0
--- /dev/null
+++ b/receiver/src/request_handler_db_write.h
@@ -0,0 +1,24 @@
+#ifndef HIDRA2_REQUEST_HANDLER_DB_WRITE_H
+#define HIDRA2_REQUEST_HANDLER_DB_WRITE_H
+
+#include "request_handler.h"
+#include "database/database.h"
+
+#include "io/io.h"
+
+namespace hidra2 {
+
+class RequestHandlerDbWrite final: public RequestHandler {
+  public:
+    RequestHandlerDbWrite();
+    StatisticEntity GetStatisticEntity() const override;
+    Error ProcessRequest(const Request& request) const override;
+    std::unique_ptr<Database> db_client__;
+  private:
+    Error ConnectToDbIfNeeded() const;
+    mutable bool connected_to_db = false;
+};
+
+}
+
+#endif //HIDRA2_REQUEST_HANDLER_DB_WRITE_H
diff --git a/receiver/unittests/mock_receiver_config.cpp b/receiver/unittests/mock_receiver_config.cpp
index 7819fe13a934464ce8ddd2fbbb8f8abd90d7403c..c1d5108bfa7b5ac22a1605a03620aae5d5daa6dc 100644
--- a/receiver/unittests/mock_receiver_config.cpp
+++ b/receiver/unittests/mock_receiver_config.cpp
@@ -17,8 +17,12 @@ Error SetReceiverConfig (const ReceiverConfig& config) {
 
     auto config_string = std::string("{\"MonitorDbAddress\":") + "\"" + config.monitor_db_uri + "\"";
     config_string += "," + std::string("\"MonitorDbName\":") + "\"" + config.monitor_db_name + "\"";
+    config_string += "," + std::string("\"BrokerDbName\":") + "\"" + config.broker_db_name + "\"";
+    config_string += "," + std::string("\"BrokerDbAddress\":") + "\"" + config.broker_db_uri + "\"";
     config_string += "," + std::string("\"ListenPort\":") + std::to_string(config.listen_port);
     config_string += "," + std::string("\"WriteToDisk\":") + (config.write_to_disk ? "true" : "false");
+    config_string += "," + std::string("\"WriteToDb\":") + (config.write_to_db ? "true" : "false");
+
     config_string += "}";
 
     EXPECT_CALL(mock_io, ReadFileToString_t("fname", _)).WillOnce(
diff --git a/receiver/unittests/test_config.cpp b/receiver/unittests/test_config.cpp
index ea15cede3b0eb2ba3bb0511f4d3381ee575a1454..008b965a59949b4fdae28580caa528aea00996aa 100644
--- a/receiver/unittests/test_config.cpp
+++ b/receiver/unittests/test_config.cpp
@@ -53,7 +53,9 @@ TEST_F(ConfigTests, ReadSettings) {
     test_config.monitor_db_name = "db_test";
     test_config.monitor_db_uri = "localhost:8086";
     test_config.write_to_disk = true;
-
+    test_config.write_to_db = true;
+    test_config.broker_db_uri = "localhost:27017";
+    test_config.broker_db_name = "test";
 
     auto err = hidra2::SetReceiverConfig(test_config);
 
@@ -62,8 +64,11 @@ TEST_F(ConfigTests, ReadSettings) {
     ASSERT_THAT(err, Eq(nullptr));
     ASSERT_THAT(config->monitor_db_uri, Eq("localhost:8086"));
     ASSERT_THAT(config->monitor_db_name, Eq("db_test"));
+    ASSERT_THAT(config->broker_db_uri, Eq("localhost:27017"));
+    ASSERT_THAT(config->broker_db_name, Eq("test"));
     ASSERT_THAT(config->listen_port, Eq(4200));
     ASSERT_THAT(config->write_to_disk, true);
+    ASSERT_THAT(config->write_to_db, true);
 
 }
 
diff --git a/receiver/unittests/test_request.cpp b/receiver/unittests/test_request.cpp
index 1d1e175279e9c6f3a2588b6a014c48ad22f9969c..9a213b69bf16a9be2d3ab81055e220105191d574 100644
--- a/receiver/unittests/test_request.cpp
+++ b/receiver/unittests/test_request.cpp
@@ -6,6 +6,8 @@
 #include "../src/request.h"
 #include "../src/request_handler.h"
 #include "../src/request_handler_file_write.h"
+#include "../src/request_handler_db_write.h"
+#include "database/database.h"
 
 #include "mock_statistics.h"
 #include "mock_receiver_config.h"
@@ -40,7 +42,7 @@ using hidra2::StatisticEntity;
 
 using hidra2::ReceiverConfig;
 using hidra2::SetReceiverConfig;
-
+using hidra2::RequestFactory;
 
 namespace {
 
@@ -58,47 +60,6 @@ class MockReqestHandler : public hidra2::RequestHandler {
 
 };
 
-class FactoryTests : public Test {
-  public:
-    hidra2::RequestFactory factory;
-    Error err{nullptr};
-    GenericNetworkRequestHeader generic_request_header;
-    ReceiverConfig config;
-    void SetUp() override {
-        config.write_to_disk = true;
-        SetReceiverConfig(config);
-    }
-    void TearDown() override {
-    }
-};
-
-TEST_F(FactoryTests, ErrorOnWrongCode) {
-    generic_request_header.op_code = hidra2::Opcode::kNetOpcodeUnknownOp;
-    auto request = factory.GenerateRequest(generic_request_header, 1, &err);
-
-    ASSERT_THAT(err, Ne(nullptr));
-}
-
-TEST_F(FactoryTests, ReturnsDataRequestOnkNetOpcodeSendDataCode) {
-    generic_request_header.op_code = hidra2::Opcode::kNetOpcodeSendData;
-    auto request = factory.GenerateRequest(generic_request_header, 1, &err);
-
-    ASSERT_THAT(err, Eq(nullptr));
-    ASSERT_THAT(dynamic_cast<hidra2::Request*>(request.get()), Ne(nullptr));
-    ASSERT_THAT(dynamic_cast<const hidra2::RequestHandlerFileWrite*>(request->GetListHandlers()[0]), Ne(nullptr));
-}
-
-TEST_F(FactoryTests, DoNotAddWriterIfNotWanted) {
-    generic_request_header.op_code = hidra2::Opcode::kNetOpcodeSendData;
-    config.write_to_disk = false;
-    SetReceiverConfig(config);
-
-    auto request = factory.GenerateRequest(generic_request_header, 1, &err);
-    ASSERT_THAT(err, Eq(nullptr));
-    ASSERT_THAT(request->GetListHandlers().size(), Eq(0));
-}
-
-
 
 class RequestTests : public Test {
   public:
@@ -212,6 +173,13 @@ TEST_F(RequestTests, GetDataIsNotNullptr) {
 
 }
 
+TEST_F(RequestTests, GetDataID) {
+    auto id = request->GetDataID();
+
+    ASSERT_THAT(id, Eq(data_id_));
+}
+
+
 
 TEST_F(RequestTests, GetDataSize) {
     auto size = request->GetDataSize();
diff --git a/receiver/unittests/test_request_factory.cpp b/receiver/unittests/test_request_factory.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ec8b93855ee7104b04ed8b526f282b2806f7deb5
--- /dev/null
+++ b/receiver/unittests/test_request_factory.cpp
@@ -0,0 +1,106 @@
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+#include "unittests/MockIO.h"
+#include "unittests/MockDatabase.h"
+#include "../src/connection.h"
+#include "../src/receiver_error.h"
+#include "../src/request.h"
+#include "../src/request_handler.h"
+#include "../src/request_handler_file_write.h"
+#include "../src/request_handler_db_write.h"
+#include "database/database.h"
+
+#include "mock_statistics.h"
+#include "mock_receiver_config.h"
+
+
+using ::testing::Test;
+using ::testing::Return;
+using ::testing::_;
+using ::testing::DoAll;
+using ::testing::SetArgReferee;
+using ::testing::Gt;
+using ::testing::Eq;
+using ::testing::Ne;
+using ::testing::Mock;
+using ::testing::NiceMock;
+using ::testing::InSequence;
+using ::testing::SetArgPointee;
+using ::hidra2::Error;
+using ::hidra2::ErrorInterface;
+using ::hidra2::GenericNetworkRequestHeader;
+using ::hidra2::GenericNetworkResponse;
+using ::hidra2::Opcode;
+using ::hidra2::Connection;
+using ::hidra2::MockIO;
+using hidra2::Request;
+using hidra2::MockStatistics;
+
+using hidra2::StatisticEntity;
+
+using hidra2::ReceiverConfig;
+using hidra2::SetReceiverConfig;
+using hidra2::RequestFactory;
+
+namespace {
+
+
+class FactoryTests : public Test {
+  public:
+    RequestFactory factory;
+    Error err{nullptr};
+    GenericNetworkRequestHeader generic_request_header;
+    ReceiverConfig config;
+
+    void SetUp() override {
+        generic_request_header.op_code = hidra2::Opcode::kNetOpcodeSendData;
+        config.write_to_disk = true;
+        config.write_to_db = true;
+        SetReceiverConfig(config);
+    }
+    void TearDown() override {
+    }
+};
+
+TEST_F(FactoryTests, ErrorOnWrongCode) {
+    generic_request_header.op_code = hidra2::Opcode::kNetOpcodeUnknownOp;
+    auto request = factory.GenerateRequest(generic_request_header, 1, &err);
+
+    ASSERT_THAT(err, Ne(nullptr));
+}
+
+TEST_F(FactoryTests, ReturnsDataRequestOnkNetOpcodeSendDataCode) {
+    generic_request_header.op_code = hidra2::Opcode::kNetOpcodeSendData;
+    auto request = factory.GenerateRequest(generic_request_header, 1, &err);
+
+    ASSERT_THAT(err, Eq(nullptr));
+    ASSERT_THAT(dynamic_cast<hidra2::Request*>(request.get()), Ne(nullptr));
+    ASSERT_THAT(dynamic_cast<const hidra2::RequestHandlerFileWrite*>(request->GetListHandlers()[0]), Ne(nullptr));
+    ASSERT_THAT(dynamic_cast<const hidra2::RequestHandlerDbWrite*>(request->GetListHandlers().back()), Ne(nullptr));
+}
+
+TEST_F(FactoryTests, DoNotAddDiskWriterIfNotWanted) {
+    config.write_to_disk = false;
+
+    SetReceiverConfig(config);
+
+    auto request = factory.GenerateRequest(generic_request_header, 1, &err);
+    ASSERT_THAT(err, Eq(nullptr));
+    ASSERT_THAT(request->GetListHandlers().size(), Eq(1));
+    ASSERT_THAT(dynamic_cast<const hidra2::RequestHandlerDbWrite*>(request->GetListHandlers().back()), Ne(nullptr));
+}
+
+TEST_F(FactoryTests, DoNotAddDbWriterIfNotWanted) {
+    config.write_to_db = false;
+
+    SetReceiverConfig(config);
+
+    auto request = factory.GenerateRequest(generic_request_header, 1, &err);
+    ASSERT_THAT(err, Eq(nullptr));
+    ASSERT_THAT(request->GetListHandlers().size(), Eq(1));
+    ASSERT_THAT(dynamic_cast<const hidra2::RequestHandlerFileWrite*>(request->GetListHandlers()[0]), Ne(nullptr));
+}
+
+
+}
diff --git a/receiver/unittests/test_request_handler_db_writer.cpp b/receiver/unittests/test_request_handler_db_writer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..99075925a536429a92458a0c59bc1e731afbf040
--- /dev/null
+++ b/receiver/unittests/test_request_handler_db_writer.cpp
@@ -0,0 +1,194 @@
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+#include "unittests/MockIO.h"
+#include "unittests/MockDatabase.h"
+
+#include "../src/receiver_error.h"
+#include "../src/request.h"
+#include "../src/request_handler.h"
+#include "../src/request_handler_db_write.h"
+#include "common/networking.h"
+#include "../../common/cpp/src/database/mongodb_client.h"
+#include "mock_receiver_config.h"
+#include "common/data_structs.h"
+
+
+using hidra2::FileInfo;
+using ::testing::Test;
+using ::testing::Return;
+using ::testing::ReturnRef;
+using ::testing::_;
+using ::testing::DoAll;
+using ::testing::SetArgReferee;
+using ::testing::Gt;
+using ::testing::Eq;
+using ::testing::Ne;
+using ::testing::Mock;
+using ::testing::NiceMock;
+using ::testing::InSequence;
+using ::testing::SetArgPointee;
+using ::hidra2::Error;
+using ::hidra2::ErrorInterface;
+using ::hidra2::FileDescriptor;
+using ::hidra2::SocketDescriptor;
+using ::hidra2::MockIO;
+using hidra2::Request;
+using hidra2::RequestHandlerDbWrite;
+using ::hidra2::GenericNetworkRequestHeader;
+
+using hidra2::MockDatabase;
+using hidra2::RequestFactory;
+using hidra2::SetReceiverConfig;
+using hidra2::ReceiverConfig;
+
+
+namespace {
+
+class MockRequest: public Request {
+  public:
+    MockRequest(const GenericNetworkRequestHeader& request_header, SocketDescriptor socket_fd):
+        Request(request_header, socket_fd) {};
+
+    MOCK_CONST_METHOD0(GetFileName, std::string());
+    MOCK_CONST_METHOD0(GetDataSize, uint64_t());
+    MOCK_CONST_METHOD0(GetDataID, uint64_t());
+    MOCK_CONST_METHOD0(GetData, const hidra2::FileData & ());
+};
+
+class DbWriterHandlerTests : public Test {
+  public:
+    RequestHandlerDbWrite handler;
+    NiceMock<MockIO> mock_io;
+    std::unique_ptr<NiceMock<MockRequest>> mock_request;
+    NiceMock<MockDatabase> mock_db;
+    ReceiverConfig config;
+    void SetUp() override {
+        GenericNetworkRequestHeader request_header;
+        request_header.data_id = 2;
+        handler.db_client__ = std::unique_ptr<hidra2::Database> {&mock_db};
+        mock_request.reset(new NiceMock<MockRequest> {request_header, 1});
+    }
+    void TearDown() override {
+        handler.db_client__.release();
+    }
+};
+
+TEST(DBWritewr, HandlerHasCorrectDbFactory) {
+    RequestHandlerDbWrite handler;
+    ASSERT_THAT(dynamic_cast<hidra2::MongoDBClient*>(handler.db_client__.get()), Ne(nullptr));
+}
+
+
+TEST_F(DbWriterHandlerTests, CheckStatisticEntity) {
+    auto entity = handler.GetStatisticEntity();
+    ASSERT_THAT(entity, Eq(hidra2::StatisticEntity::kDatabase));
+}
+
+
+TEST_F(DbWriterHandlerTests, ProcessRequestCallsConnectDbWhenNotConnected) {
+    config.broker_db_name = "test";
+    config.broker_db_uri = "127.0.0.1:27017";
+    SetReceiverConfig(config);
+
+    EXPECT_CALL(mock_db, Connect_t("127.0.0.1:27017", "test", hidra2::kDBCollectionName)).
+    WillOnce(testing::Return(nullptr));
+
+    auto err = handler.ProcessRequest(*mock_request);
+    ASSERT_THAT(err, Eq(nullptr));
+}
+
+TEST_F(DbWriterHandlerTests, ProcessRequestReturnsErrorWhenCannotConnect) {
+
+    EXPECT_CALL(mock_db, Connect_t(_, _, hidra2::kDBCollectionName)).
+    WillOnce(testing::Return(new hidra2::SimpleError("")));
+
+    auto err = handler.ProcessRequest(*mock_request);
+
+    ASSERT_THAT(err, Ne(nullptr));
+
+}
+
+
+TEST_F(DbWriterHandlerTests, ProcessRequestDoesNotCallConnectSecondTime) {
+
+    EXPECT_CALL(mock_db, Connect_t(_, _, hidra2::kDBCollectionName)).
+    WillOnce(testing::Return(nullptr));
+
+    handler.ProcessRequest(*mock_request);
+    handler.ProcessRequest(*mock_request);
+}
+
+MATCHER_P(CompareFileInfo, file, "") {
+    if (arg.size != file.size) return false;
+    if (arg.name != file.name) return false;
+    if (arg.id != file.id) return false;
+
+    return true;
+}
+
+
+
+TEST_F(DbWriterHandlerTests, CallsInsert) {
+
+    EXPECT_CALL(mock_db, Connect_t(_, _, hidra2::kDBCollectionName)).
+    WillOnce(testing::Return(nullptr));
+
+    std::string expected_file_name = "2.bin";
+    uint64_t expected_file_size = 10;
+    uint64_t expected_id = 15;
+    EXPECT_CALL(*mock_request, GetDataSize())
+    .WillOnce(Return(expected_file_size))
+    ;
+
+    EXPECT_CALL(*mock_request, GetFileName())
+    .WillOnce(Return(expected_file_name))
+    ;
+
+    EXPECT_CALL(*mock_request, GetDataID())
+    .WillOnce(Return(expected_id))
+    ;
+
+    FileInfo file_info;
+    file_info.size = expected_file_size;
+    file_info.name = expected_file_name;
+    file_info.id = expected_id;
+
+
+    EXPECT_CALL(mock_db, Insert_t(CompareFileInfo(file_info), _)).
+    WillOnce(testing::Return(nullptr));
+
+    handler.ProcessRequest(*mock_request);
+}
+
+
+/*
+TEST_F(DbWriterHandlerTests, CallsWriteFile) {
+    std::string expected_file_name = "2.bin";
+    uint64_t expected_file_size = 10;
+    EXPECT_CALL(*mock_request, GetDataSize())
+    .WillOnce(Return(expected_file_size))
+    ;
+
+    hidra2::FileData data;
+    EXPECT_CALL(*mock_request, GetData())
+    .WillOnce(ReturnRef(data))
+    ;
+
+    EXPECT_CALL(*mock_request, GetFileName())
+    .WillOnce(Return(expected_file_name))
+    ;
+
+
+    EXPECT_CALL(mock_io, WriteDataToFile_t("files/" + expected_file_name, _, expected_file_size))
+    .WillOnce(
+        Return(hidra2::IOErrorTemplates::kUnknownIOError.Generate().release())
+    );
+
+    auto err = handler.ProcessRequest(*mock_request);
+
+    ASSERT_THAT(err, Eq(hidra2::IOErrorTemplates::kUnknownIOError));
+}
+
+*/
+}
\ No newline at end of file
diff --git a/tests/automatic/curl_http_client/curl_http_client_command/CMakeLists.txt b/tests/automatic/curl_http_client/curl_http_client_command/CMakeLists.txt
index 503b9e91b51343704ccd80b856da664d5c99aab7..3738e79d412d78df63f830582bb415c40510d043 100644
--- a/tests/automatic/curl_http_client/curl_http_client_command/CMakeLists.txt
+++ b/tests/automatic/curl_http_client/curl_http_client_command/CMakeLists.txt
@@ -19,7 +19,7 @@ target_link_libraries(${TARGET_NAME} test_common hidra2-worker)
 ################################
 
 #add_test_setup_cleanup(${TARGET_NAME})
-add_integration_test(${TARGET_NAME}  get_google "GET google.com moved 302")
+add_integration_test(${TARGET_NAME}  get_google "GET google.com moved 301")
 add_integration_test(${TARGET_NAME}  get_badaddress "GET google.com/badaddress found 404")
 add_integration_test(${TARGET_NAME}  get_badaddress2 "GET 111 clienterror 404")
 add_integration_test(${TARGET_NAME}  post "POST httpbin.org/post testdata 200")
diff --git a/tests/automatic/producer_receiver/check_monitoring/check_linux.sh b/tests/automatic/producer_receiver/check_monitoring/check_linux.sh
index 3b4b82ec54b48718f5b00412ca0e9a83ddbbdd0e..5eeb022b926ff0efa59dbc3496a5af90c2749ef2 100644
--- a/tests/automatic/producer_receiver/check_monitoring/check_linux.sh
+++ b/tests/automatic/producer_receiver/check_monitoring/check_linux.sh
@@ -1,6 +1,7 @@
 #!/usr/bin/env bash
 
 database_name=db_test
+mongo_database_name=test_run
 
 set -e
 
@@ -11,7 +12,7 @@ Cleanup() {
 	influx -execute "drop database ${database_name}"
     kill $receiverid
 	rm -rf files
-
+    echo "db.dropDatabase()" | mongo ${mongo_database_name}
 }
 
 influx -execute "create database ${database_name}"
diff --git a/tests/automatic/producer_receiver/transfer_single_file/check_linux.sh b/tests/automatic/producer_receiver/transfer_single_file/check_linux.sh
index d7c69e6a25b6189b0d84220d635a15b386f29449..0c38e3337548bfc7f49630f374da1afc4482bf40 100644
--- a/tests/automatic/producer_receiver/transfer_single_file/check_linux.sh
+++ b/tests/automatic/producer_receiver/transfer_single_file/check_linux.sh
@@ -4,10 +4,13 @@ set -e
 
 trap Cleanup EXIT
 
+database_name=test_run
+
 Cleanup() {
 	echo cleanup
 	rm -rf files
     kill $receiverid
+    echo "db.dropDatabase()" | mongo ${database_name}
 }
 
 nohup $2 receiver.json &>/dev/null &
diff --git a/tests/automatic/producer_receiver/transfer_single_file/check_windows.bat b/tests/automatic/producer_receiver/transfer_single_file/check_windows.bat
index ee15242cd4354e178f16d6e4059b635cf01b3db4..988e6881f534c81be333279ebf46f74481551822 100644
--- a/tests/automatic/producer_receiver/transfer_single_file/check_windows.bat
+++ b/tests/automatic/producer_receiver/transfer_single_file/check_windows.bat
@@ -24,5 +24,8 @@ exit /b 1
 :clean
 Taskkill /IM "%short_recv_name%" /F
 rmdir /S /Q files
+SET database_name=test_run
+SET mongo_exe="c:\Program Files\MongoDB\Server\3.6\bin\mongo.exe"
+echo db.dropDatabase() | %mongo_exe% %database_name%
 
 
diff --git a/tests/automatic/settings/receiver.json b/tests/automatic/settings/receiver.json
index e23a556d1cd5a8c03ce0c32b37b7b73161bfa89d..5939e7d82c0811804e36472acafafa2b48d09f10 100644
--- a/tests/automatic/settings/receiver.json
+++ b/tests/automatic/settings/receiver.json
@@ -1,6 +1,9 @@
 {
   "MonitorDbAddress":"localhost:8086",
   "MonitorDbName": "db_test",
+  "BrokerDbAddress":"localhost:27017",
+  "BrokerDbName": "test_run",
   "ListenPort":4200,
-  "WriteToDisk":true
+  "WriteToDisk":true,
+  "WriteToDb":true
 }
\ No newline at end of file
diff --git a/worker/tools/folder_to_db/unittests/test_folder_to_db.cpp b/worker/tools/folder_to_db/unittests/test_folder_to_db.cpp
index cd9f6991b7b0284efe3761217db56baebeeb43fe..5746bce28e8ac7b1e2aba9199e1eefe8e85f690c 100644
--- a/worker/tools/folder_to_db/unittests/test_folder_to_db.cpp
+++ b/worker/tools/folder_to_db/unittests/test_folder_to_db.cpp
@@ -9,6 +9,7 @@
 #include "database/database.h"
 
 #include "common/data_structs.h"
+#include "unittests/MockDatabase.h"
 
 #include "../src/folder_db_importer.h"
 
@@ -26,18 +27,7 @@ using ::testing::NiceMock;
 using ::testing::Ref;
 using ::testing::Return;
 
-using hidra2::FolderToDbImporter;
-using hidra2::Database;
-using hidra2::DatabaseFactory;
-using hidra2::IO;
-using hidra2::kDBCollectionName;
-using hidra2::FileInfos;
-using hidra2::FileInfo;
-using hidra2::MockIO;
-using hidra2::Error;
-using hidra2::TextError;
-using hidra2::SimpleError;
-
+using namespace hidra2;
 
 
 namespace {
@@ -45,12 +35,12 @@ namespace {
 
 TEST(FolderDBConverter, SetCorrectIO) {
     FolderToDbImporter converter{};
-    ASSERT_THAT(dynamic_cast<hidra2::SystemIO*>(converter.io__.get()), Ne(nullptr));
+    ASSERT_THAT(dynamic_cast<SystemIO*>(converter.io__.get()), Ne(nullptr));
 }
 
 TEST(FolderDBConverter, SetCorrectDBFactory) {
     FolderToDbImporter converter{};
-    ASSERT_THAT(dynamic_cast<hidra2::DatabaseFactory*>(converter.db_factory__.get()), Ne(nullptr));
+    ASSERT_THAT(dynamic_cast<DatabaseFactory*>(converter.db_factory__.get()), Ne(nullptr));
 }
 
 TEST(FolderDBConverter, SetNTasksCorrectly) {
@@ -70,29 +60,6 @@ TEST(FolderDBConverter, SetNTasksCorrectly) {
 }
 
 
-class MockDatabase : public Database {
-  public:
-    Error Connect(const std::string& address, const std::string& database,
-                  const std::string& collection ) override {
-        return Error{Connect_t(address, database, collection)};
-
-    }
-    Error Insert(const FileInfo& file, bool ignore_duplicates) const override {
-        return Error{Insert_t(file, ignore_duplicates)};
-    }
-
-    MOCK_METHOD3(Connect_t, SimpleError * (const std::string&, const std::string&, const std::string&));
-    MOCK_CONST_METHOD2(Insert_t, SimpleError * (const FileInfo&, bool));
-
-    // stuff to test db destructor is called and avoid "uninteresting call" messages
-    MOCK_METHOD0(Die, void());
-    virtual ~MockDatabase() override {
-        if (check_destructor)
-            Die();
-    }
-    bool check_destructor{false};
-};
-
 class MockDatabaseFactory : public DatabaseFactory {
   public:
     std::vector<NiceMock<MockDatabase>*> db;