diff --git a/aggregation-manager-server/pom.xml b/aggregation-manager-server/pom.xml
index f72df101935087b497fda650bd741251e80a62fc..5b83ebcc96c73b2a7bcef902a2c7461af4524147 100644
--- a/aggregation-manager-server/pom.xml
+++ b/aggregation-manager-server/pom.xml
@@ -51,11 +51,26 @@
 			<groupId>org.springframework.boot</groupId>
 			<artifactId>spring-boot-starter-actuator</artifactId>
 		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-data-mongodb</artifactId>
+		</dependency>
+		<!-- gRPC -->
+		<dependency>
+			<groupId>net.devh</groupId>
+			<artifactId>grpc-server-spring-boot-starter</artifactId>
+		</dependency>
 		<!-- Own projects -->
 		<dependency>
 			<groupId>de.ozgcloud.aggregation</groupId>
 			<artifactId>aggregation-manager-interface</artifactId>
 		</dependency>
+		<!--dev
+		tools-->
+		<dependency>
+			<groupId>org.mapstruct</groupId>
+			<artifactId>mapstruct</artifactId>
+		</dependency>
 	</dependencies>
 
 	<build>
diff --git a/aggregation-manager-server/src/main/helm/templates/deployment.yaml b/aggregation-manager-server/src/main/helm/templates/deployment.yaml
index 1fac9cbcc4c4d51d0e1ef96085c1ba91158dcc24..e3916f77dff7c807d6414a05f9be08611bc55ad5 100644
--- a/aggregation-manager-server/src/main/helm/templates/deployment.yaml
+++ b/aggregation-manager-server/src/main/helm/templates/deployment.yaml
@@ -68,9 +68,24 @@ spec:
           value: {{ include "app.envSpringProfiles" . }}
         - name: ozgcloud_administration_address
           value: {{ include "app.getOzgcloudAdministrationAddress" . }}
+        {{- if not (.Values.database).useExternal }}
+        - name: spring_data_mongodb_uri
+          valueFrom:
+            secretKeyRef:
+              name: {{ (.Values.database).secretName }}
+              key: connectionString.standardSrv
+              optional: false
+        - name: spring_data_mongodb_database
+          value: {{ (.Values.database).databaseName }}
+        {{- end }}
         {{- with include "app.getCustomList" . }}
 {{ . | indent 8 }}
         {{- end }}
+        envFrom:
+          {{- if (.Values.database).useExternal }}
+          - secretRef:
+              name: {{ (.Values.database).secretName }}
+          {{- end }}
         ports:
           - containerPort: 8081
             name: metrics
diff --git a/aggregation-manager-server/src/main/helm/templates/network_policy.yaml b/aggregation-manager-server/src/main/helm/templates/network_policy.yaml
index 74138a34bca3f686944dd08abe10287689f7625e..b35a35c4232ec4a65ee0748da38b0458faef4b4e 100644
--- a/aggregation-manager-server/src/main/helm/templates/network_policy.yaml
+++ b/aggregation-manager-server/src/main/helm/templates/network_policy.yaml
@@ -50,6 +50,13 @@ spec:
 {{ toYaml . | indent 2 }}
 {{- end }}
   egress:
+    - to:
+      - podSelector:
+          matchLabels:
+            component: ozgcloud-mongodb
+      ports:
+        - port: 27017
+          protocol: TCP
     - to:
       - namespaceSelector:
           matchLabels:
diff --git a/aggregation-manager-server/src/main/helm/templates/service.yaml b/aggregation-manager-server/src/main/helm/templates/service.yaml
index 4af595e657094aac4bfd1b1e7d7386812f8577ae..201c90aac732912a2fbd7bf5a5a95c999720be9d 100644
--- a/aggregation-manager-server/src/main/helm/templates/service.yaml
+++ b/aggregation-manager-server/src/main/helm/templates/service.yaml
@@ -33,6 +33,9 @@ metadata:
 spec:
   type: ClusterIP
   ports:
+    - name: grpc-9090
+      port: 9090
+      protocol: TCP
     - name: metrics
       port: 8081
       protocol: TCP
diff --git a/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/data/AggregationData.java b/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/data/AggregationData.java
new file mode 100644
index 0000000000000000000000000000000000000000..7069b8c01eab27c3b3178d1afcd0870cd27db73d
--- /dev/null
+++ b/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/data/AggregationData.java
@@ -0,0 +1,31 @@
+package de.ozgcloud.aggregation.data;
+
+import java.time.ZonedDateTime;
+import java.util.Map;
+
+import org.springframework.data.annotation.Id;
+import org.springframework.data.annotation.TypeAlias;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+
+@Builder(toBuilder = true)
+@Getter
+@EqualsAndHashCode
+@TypeAlias("AggregationData")
+@Document(collection = AggregationData.COLLECTION)
+class AggregationData {
+
+	static final String COLLECTION = "AggregationData";
+
+	@Id
+	private String id;
+
+	private String kommune;
+	private String status;
+	private ZonedDateTime eingangDatum;
+	private String vorgangName;
+	private Map<String, Object> payload;
+}
diff --git a/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/data/AggregationDataGrpcService.java b/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/data/AggregationDataGrpcService.java
index b9cb0bf22f48e68e0c59fb304beb7e085323b3ad..3f77c59ae8419fd285b79915324c99ad256b0078 100644
--- a/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/data/AggregationDataGrpcService.java
+++ b/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/data/AggregationDataGrpcService.java
@@ -1,14 +1,19 @@
 package de.ozgcloud.aggregation.data;
 
+import org.springframework.beans.factory.annotation.Lookup;
+
 import de.ozgcloud.aggregation.data.AggregationDataServiceGrpc.AggregationDataServiceImplBase;
 import io.grpc.stub.StreamObserver;
+import net.devh.boot.grpc.server.service.GrpcService;
 
-class AggregationDataGrpcService extends AggregationDataServiceImplBase {
+@GrpcService
+abstract class AggregationDataGrpcService extends AggregationDataServiceImplBase {
 
 	@Override
 	public StreamObserver<GrpcSendAggregationDataRequest> sendAggregationData(StreamObserver<GrpcSendAggregationDataResponse> responseObserver) {
-		// Implement in OZG-7909
-		return null;
+		return getGrpcAggregationDataRequestObserver().withResponseObserver(responseObserver);
 	}
 
+	@Lookup
+	abstract GrpcAggregationDataRequestObserver getGrpcAggregationDataRequestObserver();
 }
diff --git a/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/data/AggregationDataMapper.java b/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/data/AggregationDataMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..fd10f9d28519959ed544264b795e826b67fad5fe
--- /dev/null
+++ b/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/data/AggregationDataMapper.java
@@ -0,0 +1,12 @@
+package de.ozgcloud.aggregation.data;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+
+@Mapper(uses = GrpcObjectMapper.class)
+interface AggregationDataMapper {
+
+	@Mapping(target = "kommune", ignore = true)
+	AggregationData fromGrpc(GrpcAggregationData grpcAggregationData);
+
+}
diff --git a/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/data/AggregationDataRepository.java b/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/data/AggregationDataRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..dcff9cc74e977f1b57bf272e6c021ba48205edc1
--- /dev/null
+++ b/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/data/AggregationDataRepository.java
@@ -0,0 +1,9 @@
+package de.ozgcloud.aggregation.data;
+
+import org.springframework.data.mongodb.repository.MongoRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+interface AggregationDataRepository extends MongoRepository<AggregationData, String>, CustomAggregationDataRepository {
+
+}
diff --git a/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/data/AggregationDataService.java b/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/data/AggregationDataService.java
new file mode 100644
index 0000000000000000000000000000000000000000..08d7e6f8d8206f9d9cad5d7ca8ac3b8b35acb631
--- /dev/null
+++ b/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/data/AggregationDataService.java
@@ -0,0 +1,17 @@
+package de.ozgcloud.aggregation.data;
+
+import org.springframework.stereotype.Service;
+
+import lombok.RequiredArgsConstructor;
+
+@Service
+@RequiredArgsConstructor
+class AggregationDataService {
+
+	private final AggregationDataRepository repository;
+
+	public void save(AggregationData aggregationData, String mappingName) {
+		repository.saveInCollection(aggregationData, mappingName);
+	}
+
+}
diff --git a/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/data/CustomAggregationDataRepository.java b/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/data/CustomAggregationDataRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..79ed3c19478caa446f5b8c54728476d13c402743
--- /dev/null
+++ b/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/data/CustomAggregationDataRepository.java
@@ -0,0 +1,6 @@
+package de.ozgcloud.aggregation.data;
+
+interface CustomAggregationDataRepository {
+
+	AggregationData saveInCollection(AggregationData aggregationData, String collectionName);
+}
diff --git a/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/data/CustomAggregationDataRepositoryImpl.java b/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/data/CustomAggregationDataRepositoryImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..4aed1a00136a80f3eaefdf58a931ab5ac31d0a04
--- /dev/null
+++ b/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/data/CustomAggregationDataRepositoryImpl.java
@@ -0,0 +1,17 @@
+package de.ozgcloud.aggregation.data;
+
+import org.springframework.data.mongodb.core.MongoTemplate;
+
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+class CustomAggregationDataRepositoryImpl implements CustomAggregationDataRepository {
+
+	private final MongoTemplate mongoTemplate;
+
+	@Override
+	public AggregationData saveInCollection(AggregationData aggregationData, String collectionName) {
+		return mongoTemplate.save(aggregationData, collectionName);
+	}
+
+}
diff --git a/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/data/GrpcAggregationDataRequestObserver.java b/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/data/GrpcAggregationDataRequestObserver.java
new file mode 100644
index 0000000000000000000000000000000000000000..d0974e7e30f793896cd24016187725dfa0a0587e
--- /dev/null
+++ b/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/data/GrpcAggregationDataRequestObserver.java
@@ -0,0 +1,41 @@
+package de.ozgcloud.aggregation.data;
+
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+import io.grpc.stub.StreamObserver;
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+@Component
+@Scope("prototype")
+class GrpcAggregationDataRequestObserver implements StreamObserver<GrpcSendAggregationDataRequest> {
+
+	private final AggregationDataMapper aggregationDataMapper;
+	private final AggregationDataService aggregationDataService;
+
+	private StreamObserver<GrpcSendAggregationDataResponse> responseObserver;
+
+	public GrpcAggregationDataRequestObserver withResponseObserver(StreamObserver<GrpcSendAggregationDataResponse> responseObserver) {
+		this.responseObserver = responseObserver;
+		return this;
+	}
+
+	@Override
+	public void onNext(GrpcSendAggregationDataRequest request) {
+		request.getAggregationDataList().stream().map(aggregationDataMapper::fromGrpc)
+				.forEach(data -> aggregationDataService.save(data.toBuilder().kommune(request.getMandant()).build(), request.getName()));
+	}
+
+	@Override
+	public void onError(Throwable t) {
+		responseObserver.onError(t);
+	}
+
+	@Override
+	public void onCompleted() {
+		responseObserver.onNext(GrpcSendAggregationDataResponse.getDefaultInstance());
+		responseObserver.onCompleted();
+	}
+
+}
diff --git a/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/data/GrpcObjectMapper.java b/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/data/GrpcObjectMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..11ecaf8f87ec3d06ee2428e04f8fdf1a79aa44f9
--- /dev/null
+++ b/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/data/GrpcObjectMapper.java
@@ -0,0 +1,44 @@
+package de.ozgcloud.aggregation.data;
+
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.stream.Collectors;
+
+import org.mapstruct.Mapper;
+
+@Mapper
+interface GrpcObjectMapper {
+
+	default Map<String, Object> toMap(GrpcObject object) {
+		return object.getPropertiesList().stream().map(this::mapProperty).collect(
+				Collectors.toMap(Entry::getKey, Entry::getValue));
+
+	}
+
+	default Entry<String, Object> mapProperty(GrpcProperty property) {
+		return Map.entry(property.getKey(), mapElement(property.getValue()));
+	}
+
+	default Object mapElement(GrpcElement element) {
+		if (element.hasStringValue()) {
+			return element.getStringValue();
+		}
+		if (element.hasLongValue()) {
+			return element.getLongValue();
+		}
+		if (element.hasDoubleValue()) {
+			return element.getDoubleValue();
+		}
+		if (element.hasBoolValue()) {
+			return element.getBoolValue();
+		}
+		if (element.hasObjectValue()) {
+			return toMap(element.getObjectValue());
+		}
+		if (element.hasListValue()) {
+			return element.getListValue().getElementsList().stream()
+					.map(this::mapElement).toList();
+		}
+		return null;
+	}
+}
diff --git a/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/mapping/AggregationMappingGrpcService.java b/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/mapping/AggregationMappingGrpcService.java
index 62813e122483fc66b2648bf3186c73be4769d753..4a4f4fd4547c7f74e03f4b575e4953918bf06ff9 100644
--- a/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/mapping/AggregationMappingGrpcService.java
+++ b/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/mapping/AggregationMappingGrpcService.java
@@ -2,7 +2,9 @@ package de.ozgcloud.aggregation.mapping;
 
 import de.ozgcloud.aggregation.mapping.AggregationMappingServiceGrpc.AggregationMappingServiceImplBase;
 import io.grpc.stub.StreamObserver;
+import net.devh.boot.grpc.server.service.GrpcService;
 
+@GrpcService
 class AggregationMappingGrpcService extends AggregationMappingServiceImplBase {
 
 	@Override
diff --git a/aggregation-manager-server/src/test/helm/deployment_database_test.yaml b/aggregation-manager-server/src/test/helm/deployment_database_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..cb3b4c83a32465b3ad01cd0259f6806a63e2c963
--- /dev/null
+++ b/aggregation-manager-server/src/test/helm/deployment_database_test.yaml
@@ -0,0 +1,62 @@
+#
+# Copyright (C) 2025 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test database settings
+release:
+  name: aggregation-manager-server
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+  imagePullSecret: image-pull-secret
+tests:
+  - it: should configure internal mongodb if not useExternal
+    set:
+      database.useExternal: false
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: spring_data_mongodb_uri
+            valueFrom:
+              secretKeyRef:
+                name: ozg-mongodb-admin-aggregation-manager-user
+                key: connectionString.standardSrv
+                optional: false
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: spring_data_mongodb_database
+            value: aggregation-manager-server-database
+  - it: should configure external mongodb if useExternal
+    set:
+      database.useExternal: true
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].envFrom
+          content:
+            secretRef:
+              name: ozg-mongodb-admin-aggregation-manager-user
diff --git a/aggregation-manager-server/src/test/helm/network_policy_test.yaml b/aggregation-manager-server/src/test/helm/network_policy_test.yaml
index 54308f5b7b065dc7cd9d7f2748ca2ab028d50f9a..d937238e7d91ec4172e50eca76bf7368e6da942e 100644
--- a/aggregation-manager-server/src/test/helm/network_policy_test.yaml
+++ b/aggregation-manager-server/src/test/helm/network_policy_test.yaml
@@ -63,6 +63,13 @@ tests:
           path: spec
           value:
             egress:
+              - ports:
+                  - port: 27017
+                    protocol: TCP
+                to:
+                  - podSelector:
+                      matchLabels:
+                        component: ozgcloud-mongodb
               - ports:
                   - port: 53
                     protocol: UDP
diff --git a/aggregation-manager-server/src/test/helm/service_test.yaml b/aggregation-manager-server/src/test/helm/service_test.yaml
index 4f4733d627851e2458863ea27e75eb91cddf4a91..12e99797e21dec01f7b0be275f22cd4b9373d669 100644
--- a/aggregation-manager-server/src/test/helm/service_test.yaml
+++ b/aggregation-manager-server/src/test/helm/service_test.yaml
@@ -44,7 +44,17 @@ tests:
           path: spec.type
           value: ClusterIP
 
-  - it: has metrics port
+  - it: should have grpc port
+    asserts:
+      - contains:
+          path: spec.ports
+          content:
+            name: grpc-9090
+            port: 9090
+            protocol: TCP
+          count: 1
+          any: true
+  - it: should have metrics port
     asserts:
       - contains:
           path: spec.ports
diff --git a/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/AggregationDataGrpcServiceTest.java b/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/AggregationDataGrpcServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..e4d1d25b04d90f1a8a8417376ddece89a1ad1d4b
--- /dev/null
+++ b/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/AggregationDataGrpcServiceTest.java
@@ -0,0 +1,66 @@
+package de.ozgcloud.aggregation.data;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+import io.grpc.stub.StreamObserver;
+
+class AggregationDataGrpcServiceTest {
+
+	@InjectMocks
+	@Spy
+	private AggregationDataGrpcServiceImpl service;
+	@Mock
+	private static GrpcAggregationDataRequestObserver grpcAggregationDataRequestObserver;
+
+	@Nested
+	class TestSendAggregationData {
+
+		@Mock
+		private StreamObserver<GrpcSendAggregationDataResponse> responseObserver;
+		@Mock
+		private GrpcAggregationDataRequestObserver grpcAggregationDataRequestObserverWithRepsonseObserver;
+
+		@BeforeEach
+		void mock() {
+			when(grpcAggregationDataRequestObserver.withResponseObserver(any())).thenReturn(grpcAggregationDataRequestObserverWithRepsonseObserver);
+		}
+
+		@Test
+		void shouldGetGrpcAggregationDataRequestObserver() {
+			service.sendAggregationData(responseObserver);
+
+			verify(service).getGrpcAggregationDataRequestObserver();
+		}
+
+		@Test
+		void shouldSetResponseObserver() {
+			service.sendAggregationData(responseObserver);
+
+			verify(grpcAggregationDataRequestObserver).withResponseObserver(responseObserver);
+		}
+
+		@Test
+		void shouldReturnRequestObserverWithResponseObserver() {
+			var requestObserver = service.sendAggregationData(responseObserver);
+
+			assertThat(requestObserver).isSameAs(grpcAggregationDataRequestObserverWithRepsonseObserver);
+		}
+	}
+
+	static class AggregationDataGrpcServiceImpl extends AggregationDataGrpcService {
+
+		@Override
+		GrpcAggregationDataRequestObserver getGrpcAggregationDataRequestObserver() {
+			return grpcAggregationDataRequestObserver;
+		}
+	}
+}
diff --git a/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/AggregationDataMapperTest.java b/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/AggregationDataMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..37b80d85b98047022f6e45fc01807b9221690c0a
--- /dev/null
+++ b/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/AggregationDataMapperTest.java
@@ -0,0 +1,49 @@
+package de.ozgcloud.aggregation.data;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mapstruct.factory.Mappers;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+class AggregationDataMapperTest {
+
+	@InjectMocks
+	private final AggregationDataMapper aggregationDataMapper = Mappers.getMapper(AggregationDataMapper.class);
+
+	@Mock
+	private GrpcObjectMapper grpcObjectMapper;
+
+	@Nested
+	class TestFromGrpc {
+
+		@Test
+		void shouldMapHeaderData() {
+			var aggregationData = aggregationDataMapper.fromGrpc(GrpcAggregationDataTestFactory.create());
+
+			assertThat(aggregationData).usingRecursiveComparison()
+					.ignoringFields("payload", "kommune")
+					.isEqualTo(AggregationDataTestFactory.create());
+		}
+
+		@Test
+		void shouldCallGrpcObjectMapper() {
+			aggregationDataMapper.fromGrpc(GrpcAggregationDataTestFactory.create());
+
+			verify(grpcObjectMapper).toMap(GrpcAggregationDataTestFactory.PAYLOAD);
+		}
+
+		@Test
+		void shouldSetPayload() {
+			when(grpcObjectMapper.toMap(any())).thenReturn(AggregationDataTestFactory.PAYLOAD);
+
+			var aggregationData = aggregationDataMapper.fromGrpc(GrpcAggregationDataTestFactory.create());
+
+			assertThat(aggregationData.getPayload()).isEqualTo(AggregationDataTestFactory.PAYLOAD);
+		}
+	}
+}
diff --git a/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/AggregationDataServiceTest.java b/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/AggregationDataServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..30fb641e0b2bef6dd663129e8cac8480284dc5c8
--- /dev/null
+++ b/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/AggregationDataServiceTest.java
@@ -0,0 +1,33 @@
+package de.ozgcloud.aggregation.data;
+
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import com.thedeanda.lorem.LoremIpsum;
+
+class AggregationDataServiceTest {
+
+	@InjectMocks
+	private AggregationDataService service;
+
+	@Mock
+	private AggregationDataRepository repository;
+
+	@Nested
+	class TestSave {
+
+		@Test
+		void shouldSaveInRepository() {
+			var aggregationData = AggregationDataTestFactory.create();
+			var mappingName = LoremIpsum.getInstance().getWords(1);
+
+			service.save(aggregationData, mappingName);
+
+			verify(repository).saveInCollection(aggregationData, mappingName);
+		}
+	}
+}
diff --git a/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/AggregationDataTestFactory.java b/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/AggregationDataTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..2977c2be5f15b965ebe15e9330969addfb88ed97
--- /dev/null
+++ b/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/AggregationDataTestFactory.java
@@ -0,0 +1,34 @@
+package de.ozgcloud.aggregation.data;
+
+import java.time.ZonedDateTime;
+import java.util.List;
+import java.util.Map;
+
+import com.thedeanda.lorem.LoremIpsum;
+
+public class AggregationDataTestFactory {
+
+	public static final String KOMMUNE = LoremIpsum.getInstance().getWords(1);
+	public static final String ID = GrpcAggregationDataTestFactory.ID;
+	public static final String STATUS = GrpcAggregationDataTestFactory.STATUS;
+	public static final ZonedDateTime EIGNANG_DATUM = ZonedDateTime.parse(GrpcAggregationDataTestFactory.EINGANG_DATUM);
+	public static final String VORGANG_NAME = GrpcAggregationDataTestFactory.VORGANG_NAME;
+	public static final Map<String, Object> PAYLOAD = Map.of(
+			GrpcPropertyTestFactory.STRING_KEY, GrpcPropertyTestFactory.STRING_VALUE,
+			GrpcPropertyTestFactory.LIST_KEY, List.of(GrpcPropertyTestFactory.LIST_VALUE),
+			GrpcPropertyTestFactory.MAP_KEY, Map.of(GrpcPropertyTestFactory.NESTED_MAP_KEY, GrpcPropertyTestFactory.MAP_VALUE));
+
+	public static AggregationData create() {
+		return createBuilder().build();
+	}
+
+	public static AggregationData.AggregationDataBuilder createBuilder() {
+		return AggregationData.builder()
+				.id(ID)
+				.kommune(KOMMUNE)
+				.status(STATUS)
+				.eingangDatum(EIGNANG_DATUM)
+				.vorgangName(VORGANG_NAME)
+				.payload(PAYLOAD);
+	}
+}
diff --git a/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/CustomAggregationDataRepositoryImplTest.java b/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/CustomAggregationDataRepositoryImplTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..e3a252235879a2e7dbe0d43abf04b95b18c8a56e
--- /dev/null
+++ b/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/CustomAggregationDataRepositoryImplTest.java
@@ -0,0 +1,48 @@
+package de.ozgcloud.aggregation.data;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.springframework.data.mongodb.core.MongoTemplate;
+
+import com.thedeanda.lorem.LoremIpsum;
+
+class CustomAggregationDataRepositoryImplTest {
+
+	@InjectMocks
+	private CustomAggregationDataRepositoryImpl repository;
+	@Mock
+	private MongoTemplate mongoTemplate;
+
+	@Nested
+	class TestSaveInCollection {
+
+		private final AggregationData aggregationData = AggregationDataTestFactory.create();
+		private final String collectionName = LoremIpsum.getInstance().getWords(1);
+
+		@BeforeEach
+		void mock() {
+			when(mongoTemplate.save(any(), any())).thenReturn(aggregationData);
+		}
+
+		@Test
+		void shouldSaveInCollection() {
+			repository.saveInCollection(aggregationData, collectionName);
+
+			verify(mongoTemplate).save(aggregationData, collectionName);
+		}
+
+		@Test
+		void shouldReturnSavedAggregationData() {
+			var result = repository.saveInCollection(aggregationData, collectionName);
+
+			assertThat(result).isSameAs(aggregationData);
+		}
+	}
+}
diff --git a/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/GrpcAggregationDataRequestObserverTest.java b/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/GrpcAggregationDataRequestObserverTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..245b46bf30587238b13b03e50ac0abc7bd1b1fe4
--- /dev/null
+++ b/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/GrpcAggregationDataRequestObserverTest.java
@@ -0,0 +1,104 @@
+package de.ozgcloud.aggregation.data;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import io.grpc.stub.StreamObserver;
+
+class GrpcAggregationDataRequestObserverTest {
+
+	@InjectMocks
+	private GrpcAggregationDataRequestObserver grpcAggregationDataRequestObserver;
+
+	@Mock
+	private AggregationDataMapper aggregationDataMapper;
+	@Mock
+	private AggregationDataService aggregationDataService;
+	@Mock
+	private StreamObserver<GrpcSendAggregationDataResponse> responseObserver;
+
+	@Nested
+	class TestWithResponseObserver {
+
+		@Test
+		void shouldSetResponseObserver() {
+			var requestObserver = grpcAggregationDataRequestObserver.withResponseObserver(responseObserver);
+
+			assertThat(ReflectionTestUtils.getField(requestObserver, GrpcAggregationDataRequestObserver.class, "responseObserver"))
+					.isEqualTo(responseObserver);
+		}
+	}
+
+	@Nested
+	class TestOnNext {
+
+		@BeforeEach
+		void mock() {
+			when(aggregationDataMapper.fromGrpc(any())).thenReturn(AggregationDataTestFactory.createBuilder().kommune(null).build());
+		}
+
+		@Test
+		void shouldCallAggregationDataMapper() {
+			grpcAggregationDataRequestObserver.onNext(GrpcSendAggregationDataRequestTestFactory.create());
+
+			verify(aggregationDataMapper).fromGrpc(GrpcSendAggregationDataRequestTestFactory.AGGREGATION_DATA);
+		}
+
+		@Test
+		void shouldCallAggregationDataService() {
+			grpcAggregationDataRequestObserver.onNext(GrpcSendAggregationDataRequestTestFactory.create());
+
+			verify(aggregationDataService).save(AggregationDataTestFactory.create(), GrpcSendAggregationDataRequestTestFactory.MAPPING_NAME);
+		}
+	}
+
+	@Nested
+	class TestOnError {
+
+		@BeforeEach
+		void init() {
+			grpcAggregationDataRequestObserver.withResponseObserver(responseObserver);
+		}
+
+		@Test
+		void shouldCallResponseObserverOnError() {
+			var error = new RuntimeException("Test error");
+
+			grpcAggregationDataRequestObserver.onError(error);
+
+			verify(responseObserver).onError(error);
+		}
+	}
+
+	@Nested
+	class TestOnCompleted {
+
+		@BeforeEach
+		void init() {
+			grpcAggregationDataRequestObserver.withResponseObserver(responseObserver);
+		}
+
+		@Test
+		void shouldCallOnNext() {
+			grpcAggregationDataRequestObserver.onCompleted();
+
+			verify(responseObserver).onNext(GrpcSendAggregationDataResponse.getDefaultInstance());
+		}
+
+		@Test
+		void shouldCallResponseObserverOnCompleted() {
+			grpcAggregationDataRequestObserver.onCompleted();
+
+			verify(responseObserver).onCompleted();
+		}
+	}
+
+}
diff --git a/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/GrpcAggregationDataTestFactory.java b/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/GrpcAggregationDataTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..e968ba8ce8181bb6ab21dacebfe6ef337499a189
--- /dev/null
+++ b/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/GrpcAggregationDataTestFactory.java
@@ -0,0 +1,30 @@
+package de.ozgcloud.aggregation.data;
+
+import java.time.ZonedDateTime;
+import java.util.UUID;
+
+import com.thedeanda.lorem.LoremIpsum;
+
+import de.ozgcloud.aggregation.data.GrpcAggregationData.Builder;
+
+public class GrpcAggregationDataTestFactory {
+
+	public static final GrpcObject PAYLOAD = GrpcObjectTestFactory.create();
+	public static final String STATUS = LoremIpsum.getInstance().getWords(1);
+	public static final String ID = UUID.randomUUID().toString();
+	public static final String EINGANG_DATUM = ZonedDateTime.now().toString();
+	public static final String VORGANG_NAME = LoremIpsum.getInstance().getWords(1);
+
+	public static GrpcAggregationData create() {
+		return createBuilder().build();
+	}
+
+	public static Builder createBuilder() {
+		return GrpcAggregationData.newBuilder()
+				.setId(ID)
+				.setStatus(STATUS)
+				.setEingangDatum(EINGANG_DATUM)
+				.setVorgangName(VORGANG_NAME)
+				.setPayload(PAYLOAD);
+	}
+}
diff --git a/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/GrpcObjectMapperTest.java b/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/GrpcObjectMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..2fe9d19b5601bc888683d98bad5341a613e24518
--- /dev/null
+++ b/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/GrpcObjectMapperTest.java
@@ -0,0 +1,23 @@
+package de.ozgcloud.aggregation.data;
+
+import static org.assertj.core.api.Assertions.*;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mapstruct.factory.Mappers;
+
+class GrpcObjectMapperTest {
+
+	private final GrpcObjectMapper grpcObjectMapper = Mappers.getMapper(GrpcObjectMapper.class);
+
+	@Nested
+	class TestToMap {
+
+		@Test
+		void shouldMapGrpcObjectToMap() {
+			var map = grpcObjectMapper.toMap(GrpcObjectTestFactory.create());
+
+			assertThat(map).usingRecursiveComparison().isEqualTo(AggregationDataTestFactory.PAYLOAD);
+		}
+	}
+}
diff --git a/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/GrpcObjectTestFactory.java b/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/GrpcObjectTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..339e9db812d4934c904dfdd243aefc6d545945f2
--- /dev/null
+++ b/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/GrpcObjectTestFactory.java
@@ -0,0 +1,18 @@
+package de.ozgcloud.aggregation.data;
+
+import de.ozgcloud.aggregation.data.GrpcObject.Builder;
+
+public class GrpcObjectTestFactory {
+
+	public static GrpcObject create() {
+		return createBuilder().build();
+	}
+
+	private static Builder createBuilder() {
+		return GrpcObject.newBuilder()
+				.addProperties(GrpcPropertyTestFactory.createStringProperty())
+				.addProperties(GrpcPropertyTestFactory.createListProperty())
+				.addProperties(GrpcPropertyTestFactory.creatMapProperty());
+	}
+
+}
diff --git a/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/GrpcPropertyTestFactory.java b/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/GrpcPropertyTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..0edb24f5f9e717f79e2b2dda59a20f71755036b6
--- /dev/null
+++ b/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/GrpcPropertyTestFactory.java
@@ -0,0 +1,49 @@
+package de.ozgcloud.aggregation.data;
+
+public class GrpcPropertyTestFactory {
+
+    public static final String STRING_VALUE = "stringValue";
+    public static final String STRING_KEY = "stringKey";
+    public static final String LIST_VALUE = "listValue";
+    public static final String LIST_KEY = "listKey";
+    public static final String MAP_VALUE = "mapValue";
+    public static final String MAP_KEY = "mapKey";
+    public static final String NESTED_MAP_KEY = "nestedMapKey";
+
+    public static GrpcProperty createStringProperty() {
+        return GrpcProperty.newBuilder()
+                .setKey(STRING_KEY)
+                .setValue(GrpcElement.newBuilder()
+                        .setStringValue(STRING_VALUE)
+                        .build())
+                .build();
+    }
+
+    public static GrpcProperty createListProperty() {
+        return GrpcProperty.newBuilder()
+                .setKey(LIST_KEY)
+                .setValue(GrpcElement.newBuilder()
+                        .setListValue(GrpcElementList.newBuilder()
+                                .addElements(GrpcElement.newBuilder()
+                                        .setStringValue(LIST_VALUE)
+                                        .build())
+                                .build())
+                        .build())
+                .build();
+    }
+
+    public static GrpcProperty creatMapProperty() {
+        return GrpcProperty.newBuilder()
+                .setKey(MAP_KEY)
+                .setValue(GrpcElement.newBuilder()
+                        .setObjectValue(GrpcObject.newBuilder()
+                                .addProperties(GrpcProperty.newBuilder()
+                                        .setKey(NESTED_MAP_KEY)
+                                        .setValue(GrpcElement.newBuilder().setStringValue(MAP_VALUE).build())
+                                        .build())
+                                .build())
+                        .build())
+                .build();
+    }
+
+}
diff --git a/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/GrpcSendAggregationDataRequestTestFactory.java b/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/GrpcSendAggregationDataRequestTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..cac473b793d2b28c6c796af0be653ef8b8454114
--- /dev/null
+++ b/aggregation-manager-server/src/test/java/de/ozgcloud/aggregation/data/GrpcSendAggregationDataRequestTestFactory.java
@@ -0,0 +1,24 @@
+package de.ozgcloud.aggregation.data;
+
+import com.thedeanda.lorem.LoremIpsum;
+
+import de.ozgcloud.aggregation.data.GrpcSendAggregationDataRequest.Builder;
+
+public class GrpcSendAggregationDataRequestTestFactory {
+
+	public static final GrpcAggregationData AGGREGATION_DATA = GrpcAggregationDataTestFactory.create();
+	public static final String MANDANT = AggregationDataTestFactory.KOMMUNE;
+	public static final String MAPPING_NAME = LoremIpsum.getInstance().getWords(1);
+
+	public static GrpcSendAggregationDataRequest create() {
+		return createBuilder()
+				.build();
+	}
+
+	public static Builder createBuilder() {
+		return GrpcSendAggregationDataRequest.newBuilder()
+				.addAggregationData(AGGREGATION_DATA)
+				.setMandant(MANDANT)
+				.setName(MAPPING_NAME);
+	}
+}
diff --git a/aggregation-manager-server/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension b/aggregation-manager-server/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension
new file mode 100644
index 0000000000000000000000000000000000000000..79b126e6cdb86bec1f4f08c205de8961bde1934a
--- /dev/null
+++ b/aggregation-manager-server/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension
@@ -0,0 +1 @@
+org.mockito.junit.jupiter.MockitoExtension
\ No newline at end of file
diff --git a/aggregation-manager-server/src/test/resources/junit-platform.properties b/aggregation-manager-server/src/test/resources/junit-platform.properties
new file mode 100644
index 0000000000000000000000000000000000000000..1cebb76d5a58ac034b2627d12411d82d1e85821e
--- /dev/null
+++ b/aggregation-manager-server/src/test/resources/junit-platform.properties
@@ -0,0 +1 @@
+junit.jupiter.extensions.autodetection.enabled = true
\ No newline at end of file