diff --git a/services/tunnelbroker/src/Database/DatabaseManager.h b/services/tunnelbroker/src/Database/DatabaseManager.h
--- a/services/tunnelbroker/src/Database/DatabaseManager.h
+++ b/services/tunnelbroker/src/Database/DatabaseManager.h
@@ -13,6 +13,7 @@
 #include <aws/dynamodb/model/DescribeTableResult.h>
 #include <aws/dynamodb/model/GetItemRequest.h>
 #include <aws/dynamodb/model/PutItemRequest.h>
+#include <aws/dynamodb/model/QueryRequest.h>
 
 #include <memory>
 #include <string>
@@ -51,6 +52,8 @@
 
   void putMessageItem(const MessageItem &item);
   std::shared_ptr<MessageItem> findMessageItem(const std::string &messageID);
+  std::vector<std::shared_ptr<MessageItem>>
+  findMessageItemsByReceiver(const std::string &toDeviceID);
   void removeMessageItem(const std::string &messageID);
 };
 
diff --git a/services/tunnelbroker/src/Database/DatabaseManager.cpp b/services/tunnelbroker/src/Database/DatabaseManager.cpp
--- a/services/tunnelbroker/src/Database/DatabaseManager.cpp
+++ b/services/tunnelbroker/src/Database/DatabaseManager.cpp
@@ -201,6 +201,34 @@
   return std::move(this->innerFindItem<MessageItem>(request));
 }
 
+std::vector<std::shared_ptr<MessageItem>>
+DatabaseManager::findMessageItemsByReceiver(const std::string &toDeviceID) {
+  std::vector<std::shared_ptr<MessageItem>> result;
+
+  Aws::DynamoDB::Model::QueryRequest req;
+  req.SetTableName(MessageItem().getTableName());
+  req.SetKeyConditionExpression(
+      MessageItem::FIELD_TO_DEVICE_ID + " = :valueToMatch");
+
+  AttributeValues attributeValues;
+  attributeValues.emplace(":valueToMatch", toDeviceID);
+
+  req.SetExpressionAttributeValues(attributeValues);
+  req.SetIndexName(MessageItem::INDEX_TO_DEVICE_ID);
+
+  const Aws::DynamoDB::Model::QueryOutcome &outcome =
+      getDynamoDBClient()->Query(req);
+  if (!outcome.IsSuccess()) {
+    throw std::runtime_error(outcome.GetError().GetMessage());
+  }
+  const Aws::Vector<AttributeValues> &items = outcome.GetResult().GetItems();
+  for (auto &item : items) {
+    result.push_back(std::make_shared<MessageItem>(item));
+  }
+
+  return result;
+}
+
 void DatabaseManager::removeMessageItem(const std::string &messageID) {
   this->innerRemoveItem(*(createItemByType<MessageItem>()), messageID);
 }
diff --git a/services/tunnelbroker/src/Database/MessageItem.h b/services/tunnelbroker/src/Database/MessageItem.h
--- a/services/tunnelbroker/src/Database/MessageItem.h
+++ b/services/tunnelbroker/src/Database/MessageItem.h
@@ -27,6 +27,7 @@
   static const std::string FIELD_BLOB_HASHES;
   static const std::string FIELD_EXPIRE;
   static const std::string FIELD_CREATED_AT;
+  static const std::string INDEX_TO_DEVICE_ID;
 
   std::string getPrimaryKey() const override;
   std::string getTableName() const override;
diff --git a/services/tunnelbroker/src/Database/MessageItem.cpp b/services/tunnelbroker/src/Database/MessageItem.cpp
--- a/services/tunnelbroker/src/Database/MessageItem.cpp
+++ b/services/tunnelbroker/src/Database/MessageItem.cpp
@@ -15,6 +15,7 @@
 const std::string MessageItem::FIELD_BLOB_HASHES = "BlobHashes";
 const std::string MessageItem::FIELD_EXPIRE = "Expire";
 const std::string MessageItem::FIELD_CREATED_AT = "CreatedAt";
+const std::string MessageItem::INDEX_TO_DEVICE_ID = "ToDeviceID-index";
 
 MessageItem::MessageItem(
     const std::string messageID,