diff --git a/aggregation-manager-job/lombok.config b/aggregation-manager-job/lombok.config
index a06fa130e8af26b659f2d3a0cb1114cd966a9b0e..650d169bcafc87be10f9129d54c24008ee7bc933 100644
--- a/aggregation-manager-job/lombok.config
+++ b/aggregation-manager-job/lombok.config
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/aggregation-manager-job/pom.xml b/aggregation-manager-job/pom.xml
index 4b941623da3c5bfe1e9f4c41044652e02308add8..7546f1e416d558c42c14239e1f451f1282f3f64b 100644
--- a/aggregation-manager-job/pom.xml
+++ b/aggregation-manager-job/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+    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
diff --git a/aggregation-manager-job/src/main/helm/Chart.yaml b/aggregation-manager-job/src/main/helm/Chart.yaml
index 4dbc8eeeed2c13ae5f30f63eb8b93d7ad714b318..0fd6c5a925c7196f4f7c68909117b8911a450bb3 100644
--- a/aggregation-manager-job/src/main/helm/Chart.yaml
+++ b/aggregation-manager-job/src/main/helm/Chart.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/aggregation-manager-job/src/main/helm/templates/_helpers.tpl b/aggregation-manager-job/src/main/helm/templates/_helpers.tpl
index 88c452bde33a48f2aad132a1f829b420d9626a9a..8b01f744812950ccee2c4b3744329ca047b6be3e 100644
--- a/aggregation-manager-job/src/main/helm/templates/_helpers.tpl
+++ b/aggregation-manager-job/src/main/helm/templates/_helpers.tpl
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
@@ -22,7 +22,6 @@
 # unter der Lizenz sind dem Lizenztext zu entnehmen.
 #
 
-
 {{/* error check 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec) */}}
 {{/* Namespace */}}
 {{- define "app.namespace" -}}
diff --git a/aggregation-manager-job/src/main/helm/templates/configmap_bindings_type.yaml b/aggregation-manager-job/src/main/helm/templates/configmap_bindings_type.yaml
index 620446357f78f2c7648cb9de093133a50e52bacd..0656aa0e8d17ac77666e6fc9f35fdd67987f15bc 100644
--- a/aggregation-manager-job/src/main/helm/templates/configmap_bindings_type.yaml
+++ b/aggregation-manager-job/src/main/helm/templates/configmap_bindings_type.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
@@ -26,7 +26,7 @@
 apiVersion: v1
 kind: ConfigMap
 metadata:
-  name: aggregation-manager-bindings-type
+  name: aggregation-manager-job-bindings-type
   namespace: {{ include "app.namespace" . }}
 data:
   type: |
diff --git a/aggregation-manager-job/src/main/helm/templates/cronjob.yaml b/aggregation-manager-job/src/main/helm/templates/cronjob.yaml
index c320cf7a4a0ab8150e72dafdd1b490489c87954a..f241604c10a1e8d29284042a51dad9dac8980f5f 100644
--- a/aggregation-manager-job/src/main/helm/templates/cronjob.yaml
+++ b/aggregation-manager-job/src/main/helm/templates/cronjob.yaml
@@ -153,7 +153,7 @@ spec:
             {{- if ((.Values.database).tls).enabled }}
             - name: bindings
               configMap:
-                name: aggregation-manager-bindings-type
+                name: aggregation-manager-job-bindings-type
             - name: mongodb-root-ca
               secret:
                 secretName: {{ ((.Values.database).tls).secretName }}
diff --git a/aggregation-manager-job/src/main/helm/templates/network_policy.yaml b/aggregation-manager-job/src/main/helm/templates/network_policy.yaml
index 03efd104d87196bfa00589c986d265445531fd50..0a4c36b94f93b77f71247adab486983c9bc13211 100644
--- a/aggregation-manager-job/src/main/helm/templates/network_policy.yaml
+++ b/aggregation-manager-job/src/main/helm/templates/network_policy.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/aggregation-manager-job/src/main/helm/templates/service.yaml b/aggregation-manager-job/src/main/helm/templates/service.yaml
index d8f6db48969f5ab3d182808bd3315c1dd414e737..7021bc6081893b9d4bf0ae35f5bde9572aea7a33 100644
--- a/aggregation-manager-job/src/main/helm/templates/service.yaml
+++ b/aggregation-manager-job/src/main/helm/templates/service.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/aggregation-manager-job/src/main/helm/templates/service_account.yaml b/aggregation-manager-job/src/main/helm/templates/service_account.yaml
index 02ff46e312df7ecaba152d3626e4e3affd778f34..664e8acec9fabb26df2325ab4bc336e628151144 100644
--- a/aggregation-manager-job/src/main/helm/templates/service_account.yaml
+++ b/aggregation-manager-job/src/main/helm/templates/service_account.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/aggregation-manager-job/src/main/helm/templates/service_monitor.yaml b/aggregation-manager-job/src/main/helm/templates/service_monitor.yaml
index 5274cc482a298371af3b0fb05301b3bb1acb0c5b..20c0fee105500e4444f26baa4a6d1d22066c9cba 100644
--- a/aggregation-manager-job/src/main/helm/templates/service_monitor.yaml
+++ b/aggregation-manager-job/src/main/helm/templates/service_monitor.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/aggregation-manager-job/src/main/helm/values.yaml b/aggregation-manager-job/src/main/helm/values.yaml
index 366ab528a084541f719b998c41778cac4d55bfe6..e619c25c4f0b53888af78724f990ae368aa49569 100644
--- a/aggregation-manager-job/src/main/helm/values.yaml
+++ b/aggregation-manager-job/src/main/helm/values.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
@@ -32,8 +32,8 @@ ozgcloud:
 
 database:
   useExternal: false
-  databaseName: aggregation-manager-database
-  secretName: ozg-mongodb-admin-aggregation-manager-user
+  databaseName: aggregation-manager-job-database
+  secretName: ozg-mongodb-admin-aggregation-manager-job-user
   tls:
     enabled: false
     secretName: ozg-mongodb-tls-cert
diff --git a/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationCallContext.java b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationCallContext.java
index 5971fb14a41d03278d2812e822c790600e35d757..035d0f0e2bf90e5ac6c436f9c752fc15cfc9b6fd 100644
--- a/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationCallContext.java
+++ b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationCallContext.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * 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
diff --git a/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationManagerApplication.java b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationManagerApplication.java
index 9d5496307a55997824bf8c7723890dae6a78af68..22ee8742bada8d265601e0ba33d621240a065c9d 100644
--- a/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationManagerApplication.java
+++ b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationManagerApplication.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * 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
diff --git a/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationManagerConfiguration.java b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationManagerConfiguration.java
index d4ac274520b0f76db83fa5f9841cb8aa9a4d35ce..00541877a3dbf271f7e375b6abf291d861e785cc 100644
--- a/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationManagerConfiguration.java
+++ b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationManagerConfiguration.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * 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
diff --git a/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationManagerGrpcConfiguration.java b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationManagerGrpcConfiguration.java
index 0d13fd94f46a80050b2ba3cc4f0adae1f7f232c0..eec32d5d22db5bb94650f73344808f20fc3e5931 100644
--- a/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationManagerGrpcConfiguration.java
+++ b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationManagerGrpcConfiguration.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * 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
diff --git a/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationManagerRunner.java b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationManagerRunner.java
index ccfe40139c90b6f80ff097426b707ad7515f42ce..3d5596e8748fbdd4c3cf9ebcc884faa7d40fa79b 100644
--- a/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationManagerRunner.java
+++ b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationManagerRunner.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * 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
@@ -23,37 +23,19 @@
  */
 package de.ozgcloud.aggregation;
 
-import java.util.List;
 import java.util.Objects;
-import java.util.Optional;
 import java.util.UUID;
-import java.util.function.Function;
-import java.util.function.IntFunction;
-import java.util.function.IntPredicate;
-import java.util.function.Predicate;
-import java.util.function.UnaryOperator;
-import java.util.stream.IntStream;
-import java.util.stream.Stream;
 
-import org.apache.logging.log4j.CloseableThreadContext;
 import org.apache.logging.log4j.ThreadContext;
+import org.springframework.beans.factory.annotation.Lookup;
 import org.springframework.boot.CommandLineRunner;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.stereotype.Component;
 
-import de.ozgcloud.aggregation.transformation.AggregationMapping.FormIdentifier;
+import de.ozgcloud.aggregation.transformation.AggregationMapping;
 import de.ozgcloud.aggregation.transformation.Transformation;
 import de.ozgcloud.aggregation.transformation.TransformationException;
 import de.ozgcloud.aggregation.transformation.TransformationService;
-import de.ozgcloud.aggregation.transformation.VorgangMapper;
-import de.ozgcloud.aggregation.warehouse.DocumentEntry;
-import de.ozgcloud.aggregation.warehouse.WarehouseRepository;
-import de.ozgcloud.apilib.vorgang.OzgCloudVorgang;
-import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery;
-import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery.FormIdentification;
-import de.ozgcloud.apilib.vorgang.OzgCloudVorgangService;
-import de.ozgcloud.apilib.vorgang.OzgCloudVorgangStub;
-import de.ozgcloud.apilib.vorgang.Page;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.log4j.Log4j2;
@@ -62,133 +44,54 @@ import lombok.extern.log4j.Log4j2;
 @RequiredArgsConstructor
 @Log4j2
 @ConditionalOnProperty(prefix = "ozgcloud.command.line.runner", value = "enabled", havingValue = "true", matchIfMissing = true)
-public class AggregationManagerRunner implements CommandLineRunner {
+public abstract class AggregationManagerRunner implements CommandLineRunner {
 
 	private static final String MDC_EXECUTION = "execution";
-	private static final String MDC_VORGANG = "vorgang";
 
-	private static final Predicate<Batch> HAS_NEXT_BATCH = x -> !x.items.isEmpty();
-
-	private final OzgCloudVorgangService vorgangService;
 	private final AggregationManagerConfiguration config;
-
 	private final TransformationProperties transformationProperties;
-
 	private final TransformationService transformationService;
-	private final WarehouseRepository repository;
-	private final VorgangMapper vorgangMapper;
 
 	@Override
 	public void run(String... args) throws TransformationException {
 		var identifier = transformationProperties.getIdentifier();
 		var aggregationMappings = transformationProperties.getAggregationMappings();
 		if (Objects.isNull(aggregationMappings) || aggregationMappings.isEmpty()) {
-			runWithTransformation(transformationService.load(identifier, null), Optional.empty());
+			runWithDefaultTransformation(transformationService.load(identifier, null));
 		} else {
 			aggregationMappings.stream()
 					.forEach(aggregationMapping -> runWithTransformation(transformationService.load(identifier, aggregationMapping),
-							Optional.of(aggregationMapping.getFormIdentifier())));
+							aggregationMapping));
 		}
 	}
 
-	void runWithTransformation(Transformation transformation, Optional<FormIdentifier> formIdentifier) {
+	void runWithDefaultTransformation(Transformation transformation) {
+		runWithTransformation(transformation, null);
+	}
+
+	void runWithTransformation(Transformation transformation, AggregationMapping aggregationMapping) {
 		try (Execution execution = new Execution(transformation)) {
 			ThreadContext.put(MDC_EXECUTION, execution.id.toString());
-			loadVorgaengeIntoRepository(Stream.concat(
-					extractBatchesOfVorgaengeFromDataSource(execution, formIdentifier),
-					extractBatchesOfDeletedVorgaengeFromDataSource(execution, formIdentifier)));
+			prepareAggregator(execution, aggregationMapping).aggregate();
 		} finally {
 			ThreadContext.remove(MDC_EXECUTION);
 		}
 	}
 
-	void loadVorgaengeIntoRepository(Stream<Batch> batches) {
-		repository.deleteAll();
-		batches.map(this::transformBatchToDocumentEntries).forEach(this::loadDocumentEntriesIntoRepository);
-	}
-
-	Stream<Batch> extractBatchesOfVorgaengeFromDataSource(Execution execution, Optional<FormIdentifier> formIdentifier) {
-		return extractBatchesFromDataSource(execution, page -> getVorgaengeFromDataSource(page, formIdentifier));
-	}
-
-	List<OzgCloudVorgang> getVorgaengeFromDataSource(Page page, Optional<FormIdentifier> formIdentifier) {
-		return vorgangService.find(buildFindByFormEngineQuery(formIdentifier), page).stream()
-				.map(vorgangStub -> vorgangService.getById(vorgangStub.getId()))
-				.toList();
-	}
-
-	OzgCloudVorgangQuery buildFindByFormEngineQuery(Optional<FormIdentifier> formIdentifier) {
-		return OzgCloudVorgangQuery.builder()
-				.form(mapToFormIdentification(formIdentifier))
-				.build();
-	}
-
-	private Optional<FormIdentification> mapToFormIdentification(Optional<FormIdentifier> formIdentifier) {
-		return formIdentifier
-				.map(identifier -> FormIdentification.builder()
-						.formId(identifier.getFormId())
-						.formEngineName(identifier.getFormEngineName())
-						.build());
-	}
-
-	Stream<Batch> extractBatchesOfDeletedVorgaengeFromDataSource(Execution execution, Optional<FormIdentifier> formIdentifier) {
-		return formIdentifier.isEmpty() ? extractBatchesFromDataSource(execution, getPagedDeletedVorgaenge(vorgangService.findDeleted()))
-				: Stream.empty();
+	Aggregator prepareAggregator(Execution execution, AggregationMapping aggregationMapping) {
+		return createAggregator()
+				.withExecution(execution)
+				.withAggregationMapping(aggregationMapping)
+				.withBatchSize(config.getFetchingBatchSize());
 	}
 
-	Function<Page, List<OzgCloudVorgang>> getPagedDeletedVorgaenge(Stream<OzgCloudVorgangStub> allDeletedVorgaenge) {
-		var it = allDeletedVorgaenge.iterator();
-		IntPredicate hasNextVorgangStub = ignored -> it.hasNext();
-		IntFunction<OzgCloudVorgangStub> nextVorgangStub = ignored -> it.next();
-		return page -> IntStream.range(page.getOffset(), page.getOffset() + page.getLimit())
-				.takeWhile(hasNextVorgangStub)
-				.mapToObj(nextVorgangStub)
-				.map(vorgangMapper::fromVorgangStub)
-				.toList();
-	}
-
-	Stream<Batch> extractBatchesFromDataSource(Execution execution, Function<Page, List<OzgCloudVorgang>> getFromDataSource) {
-		var fetchSize = config.getFetchingBatchSize();
-		var initialBatch = createBatch(execution, Page.builder().offset(0).limit(fetchSize).build(), getFromDataSource);
-		UnaryOperator<Batch> nextBatch = x -> createBatch(
-				execution,
-				Page.builder().offset(x.page.getOffset() + fetchSize).limit(fetchSize).build(),
-				getFromDataSource);
-		return Stream.iterate(initialBatch, HAS_NEXT_BATCH, nextBatch).filter(x -> !x.items.isEmpty());
-	}
-
-	private Batch createBatch(Execution execution, Page page, Function<Page, List<OzgCloudVorgang>> getFromDataSource) {
-		return new Batch(execution, createBatchUUID(), page, getFromDataSource.apply(page));
-	}
-
-	UUID createBatchUUID() {
-		return UUID.randomUUID();
-	}
-
-	void loadDocumentEntriesIntoRepository(Stream<DocumentEntry> entries) {
-		final List<DocumentEntry> documents = entries.toList();
-		LOG.atDebug().log("store documents: {}", () -> documents.stream().map(DocumentEntry::getId).toList());
-		repository.saveAll(documents);
-	}
-
-	Stream<DocumentEntry> transformBatchToDocumentEntries(Batch batch) {
-		return batch.items.stream().map(vorgang -> transformWithinBatch(batch, vorgang)).filter(Objects::nonNull);
-	}
-
-	DocumentEntry transformWithinBatch(Batch batch, OzgCloudVorgang vorgang) {
-		try (var instance = CloseableThreadContext.put(MDC_VORGANG, vorgang.getId().toString())) {
-			return batch.execution.transformation.apply(vorgang);
-		} catch (TransformationException e) {
-			LOG.atError().withThrowable(e).log("failed to transform vorgang [{}] in batch [{}] of execution [{}]",
-					vorgang::getId, () -> batch.id, () -> batch.execution.id);
-			return null;
-		}
-	}
+	@Lookup
+	protected abstract Aggregator createAggregator();
 
+	@Getter
 	@RequiredArgsConstructor
 	protected static class Execution implements AutoCloseable {
 		private final UUID id = UUID.randomUUID();
-		@Getter
 		private final Transformation transformation;
 
 		@Override
@@ -197,7 +100,4 @@ public class AggregationManagerRunner implements CommandLineRunner {
 		}
 	}
 
-	record Batch(Execution execution, UUID id, Page page, List<OzgCloudVorgang> items) {
-	}
-
 }
diff --git a/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/Aggregator.java b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/Aggregator.java
new file mode 100644
index 0000000000000000000000000000000000000000..79cf481fe8871d780ceec13bb1b7564037d2fb0c
--- /dev/null
+++ b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/Aggregator.java
@@ -0,0 +1,160 @@
+package de.ozgcloud.aggregation;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.function.Function;
+import java.util.function.IntFunction;
+import java.util.function.IntPredicate;
+import java.util.function.Predicate;
+import java.util.function.UnaryOperator;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+import org.apache.logging.log4j.CloseableThreadContext;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+import de.ozgcloud.aggregation.AggregationManagerRunner.Execution;
+import de.ozgcloud.aggregation.transformation.AggregationMapping;
+import de.ozgcloud.aggregation.transformation.AggregationMapping.FormIdentifier;
+import de.ozgcloud.aggregation.transformation.TransformationException;
+import de.ozgcloud.aggregation.transformation.VorgangMapper;
+import de.ozgcloud.aggregation.warehouse.DocumentEntry;
+import de.ozgcloud.aggregation.warehouse.WarehouseRepository;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgang;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery.FormIdentification;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangService;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangStub;
+import de.ozgcloud.apilib.vorgang.Page;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.log4j.Log4j2;
+
+@Component
+@Scope("prototype")
+@RequiredArgsConstructor
+@Log4j2
+class Aggregator {
+
+	private static final String MDC_VORGANG = "vorgang";
+	private static final Predicate<Batch> HAS_NEXT_BATCH = x -> !x.items.isEmpty();
+
+	private final OzgCloudVorgangService vorgangService;
+	private final WarehouseRepository repository;
+	private final VorgangMapper vorgangMapper;
+
+	private Execution execution;
+	private FormIdentifier formIdentifier;
+	private String collectionName = DocumentEntry.COLLECTION;
+	private int batchSize = 100;
+
+	public Aggregator withExecution(Execution execution) {
+		this.execution = execution;
+		return this;
+	}
+
+	public Aggregator withAggregationMapping(AggregationMapping aggregationMapping) {
+		if (Objects.nonNull(aggregationMapping)) {
+			this.formIdentifier = aggregationMapping.getFormIdentifier();
+			this.collectionName = aggregationMapping.getName();
+		}
+		return this;
+	}
+
+	public Aggregator withBatchSize(int batchSize) {
+		this.batchSize = batchSize;
+		return this;
+	}
+
+	public void aggregate() {
+		loadVorgaengeIntoRepository(Stream.concat(extractBatchesOfVorgaengeFromDataSource(), extractBatchesOfDeletedVorgaengeFromDataSource()));
+	}
+
+	Stream<Batch> extractBatchesOfVorgaengeFromDataSource() {
+		return extractBatchesFromDataSource(this::getVorgaengeFromDataSource);
+	}
+
+	List<OzgCloudVorgang> getVorgaengeFromDataSource(Page page) {
+		return vorgangService.find(buildFindByFormEngineQuery(), page).stream()
+				.map(vorgangStub -> vorgangService.getById(vorgangStub.getId()))
+				.toList();
+	}
+
+	OzgCloudVorgangQuery buildFindByFormEngineQuery() {
+		return OzgCloudVorgangQuery.builder()
+				.form(mapToFormIdentification())
+				.build();
+	}
+
+	private Optional<FormIdentification> mapToFormIdentification() {
+		return Optional.ofNullable(formIdentifier)
+				.map(identifier -> FormIdentification.builder()
+						.formId(identifier.getFormId())
+						.formEngineName(identifier.getFormEngineName())
+						.build());
+	}
+
+	Stream<Batch> extractBatchesOfDeletedVorgaengeFromDataSource() {
+		return Objects.isNull(formIdentifier) ? extractBatchesFromDataSource(getPagedDeletedVorgaenge(vorgangService.findDeleted()))
+				: Stream.empty();
+	}
+
+	Function<Page, List<OzgCloudVorgang>> getPagedDeletedVorgaenge(Stream<OzgCloudVorgangStub> allDeletedVorgaenge) {
+		var it = allDeletedVorgaenge.iterator();
+		IntPredicate hasNextVorgangStub = ignored -> it.hasNext();
+		IntFunction<OzgCloudVorgangStub> nextVorgangStub = ignored -> it.next();
+		return page -> IntStream.range(page.getOffset(), page.getOffset() + page.getLimit())
+				.takeWhile(hasNextVorgangStub)
+				.mapToObj(nextVorgangStub)
+				.map(vorgangMapper::fromVorgangStub)
+				.toList();
+	}
+
+	Stream<Batch> extractBatchesFromDataSource(Function<Page, List<OzgCloudVorgang>> getFromDataSource) {
+		var initialBatch = createBatch(execution, Page.builder().offset(0).limit(batchSize).build(), getFromDataSource);
+		UnaryOperator<Batch> nextBatch = x -> createBatch(
+				execution,
+				Page.builder().offset(x.page.getOffset() + batchSize).limit(batchSize).build(),
+				getFromDataSource);
+		return Stream.iterate(initialBatch, HAS_NEXT_BATCH, nextBatch).filter(x -> !x.items.isEmpty());
+	}
+
+	private Batch createBatch(Execution execution, Page page, Function<Page, List<OzgCloudVorgang>> getFromDataSource) {
+		return new Batch(execution, createBatchUUID(), page, getFromDataSource.apply(page));
+	}
+
+	UUID createBatchUUID() {
+		return UUID.randomUUID();
+	}
+
+	void loadVorgaengeIntoRepository(Stream<Batch> batches) {
+		repository.clearCollection(collectionName);
+		batches.map(this::transformBatchToDocumentEntries).forEach(this::loadDocumentEntriesIntoRepository);
+	}
+
+	List<DocumentEntry> transformBatchToDocumentEntries(Batch batch) {
+		return batch.items.stream().map(vorgang -> transformWithinBatch(batch, vorgang)).filter(Objects::nonNull).toList();
+	}
+
+	DocumentEntry transformWithinBatch(Batch batch, OzgCloudVorgang vorgang) {
+		try (var instance = CloseableThreadContext.put(MDC_VORGANG, vorgang.getId().toString())) {
+			return batch.execution.getTransformation().apply(vorgang);
+		} catch (TransformationException e) {
+			LOG.error(
+					"failed to transform vorgang [%s] in batch [%s] of execution [%s]".formatted(vorgang.getId(), batch.id, batch.execution.getId()),
+					e);
+			return null;
+		}
+	}
+
+	void loadDocumentEntriesIntoRepository(List<DocumentEntry> entries) {
+		LOG.atDebug().log("store documents: {}", () -> entries.stream().map(DocumentEntry::getId).toList());
+		repository.saveAllInCollection(entries, collectionName);
+	}
+
+	record Batch(Execution execution, UUID id, Page page, List<OzgCloudVorgang> items) {
+	}
+
+}
diff --git a/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/TransformationProperties.java b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/TransformationProperties.java
index b639b4bd91893f94bef366a4f16122a7a8265103..aadc1cac0a74c6ceec10de99559e7c6862b2a84c 100644
--- a/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/TransformationProperties.java
+++ b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/TransformationProperties.java
@@ -25,8 +25,11 @@ package de.ozgcloud.aggregation;
 
 import java.util.List;
 
+import jakarta.validation.Valid;
+
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.validation.annotation.Validated;
 
 import de.ozgcloud.aggregation.transformation.AggregationMapping;
 import lombok.Getter;
@@ -35,6 +38,7 @@ import lombok.extern.log4j.Log4j2;
 
 @ConfigurationProperties(prefix = "ozgcloud.aggregation")
 @Configuration
+@Validated
 @Getter
 @Setter
 @Log4j2
@@ -44,6 +48,7 @@ public class TransformationProperties {
 	 * List of field mapping definitions with a form specification to which the
 	 * field mappings should be applied
 	 */
+	@Valid
 	private List<AggregationMapping> aggregationMappings;
 
 	/*
diff --git a/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/transformation/AggregationMapping.java b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/transformation/AggregationMapping.java
index d98c2350ef04f3920dc8d30f8ea4100236991d65..f32b019c01de61bd0c2cba4d87b0d2b3e935f3aa 100644
--- a/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/transformation/AggregationMapping.java
+++ b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/transformation/AggregationMapping.java
@@ -25,6 +25,10 @@ package de.ozgcloud.aggregation.transformation;
 
 import java.util.List;
 
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+
 import lombok.Builder;
 import lombok.Getter;
 import lombok.Singular;
@@ -35,22 +39,42 @@ import lombok.ToString;
 @ToString
 public class AggregationMapping {
 
+	@NotBlank
+	private String name;
+	@NotNull
+	@Valid
 	private FormIdentifier formIdentifier;
 
 	@Singular
+	@Valid
 	private List<FieldMapping> fieldMappings;
+	private String parent;
+	private Status status;
+	private Scope scope;
+
+	public enum Status {
+		AUSSTEHEND, FREIGEGEBEN, ZURUECKGEHALTEN;
+	}
+
+	public enum Scope {
+		LAND, MANDANT;
+	}
 
 	@Getter
 	@Builder
 	public static class FormIdentifier {
+		@NotBlank
 		private String formEngineName;
+		@NotBlank
 		private String formId;
 	}
 
 	@Getter
 	@Builder
 	public static class FieldMapping {
+		@NotBlank
 		private String sourcePath;
+		@NotBlank
 		private String targetPath;
 	}
 }
diff --git a/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/warehouse/CustomWarehouseRepository.java b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/warehouse/CustomWarehouseRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..0a312165a18ef10eab5ce9178e3c4ba6f4efc396
--- /dev/null
+++ b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/warehouse/CustomWarehouseRepository.java
@@ -0,0 +1,12 @@
+package de.ozgcloud.aggregation.warehouse;
+
+import java.util.List;
+
+interface CustomWarehouseRepository {
+
+	DocumentEntry saveInCollection(DocumentEntry documentEntry, String collectionName);
+
+	List<DocumentEntry> saveAllInCollection(Iterable<DocumentEntry> documentEntries, String collectionName);
+
+	void clearCollection(String collectionName);
+}
diff --git a/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/warehouse/CustomWarehouseRepositoryImpl.java b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/warehouse/CustomWarehouseRepositoryImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..a5169d606f6a6055943538d8ac02f8a0477716b1
--- /dev/null
+++ b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/warehouse/CustomWarehouseRepositoryImpl.java
@@ -0,0 +1,30 @@
+package de.ozgcloud.aggregation.warehouse;
+
+import java.util.List;
+import java.util.stream.StreamSupport;
+
+import org.springframework.data.mongodb.core.MongoTemplate;
+
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+class CustomWarehouseRepositoryImpl implements CustomWarehouseRepository {
+
+	private final MongoTemplate mongoTemplate;
+
+	@Override
+	public List<DocumentEntry> saveAllInCollection(Iterable<DocumentEntry> documentEntries, String collectionName) {
+		return StreamSupport.stream(documentEntries.spliterator(), false).map(entry -> saveInCollection(entry, collectionName)).toList();
+	}
+
+	@Override
+	public DocumentEntry saveInCollection(DocumentEntry documentEntry, String collectionName) {
+		return mongoTemplate.save(documentEntry, collectionName);
+	}
+
+	@Override
+	public void clearCollection(String collectionName) {
+		mongoTemplate.dropCollection(collectionName);
+	}
+
+}
diff --git a/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/warehouse/DocumentEntry.java b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/warehouse/DocumentEntry.java
index 6fde2052394db0c883d22c20a8d9619d5bec4fdc..5afa5add677eef2732f8103f6d23e4c49c8de802 100644
--- a/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/warehouse/DocumentEntry.java
+++ b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/warehouse/DocumentEntry.java
@@ -40,7 +40,7 @@ import lombok.Getter;
 @TypeAlias("Vorgang")
 public class DocumentEntry {
 
-	static final String COLLECTION = "vorgang";
+	public static final String COLLECTION = "vorgang";
 
 	@Id
 	private String id;
diff --git a/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/warehouse/WarehouseRepository.java b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/warehouse/WarehouseRepository.java
index 06edf8f643448638914e1854810690eb76b6f83e..92632d531ca8c6e2d45cf714ed48f7072ef9ccc5 100644
--- a/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/warehouse/WarehouseRepository.java
+++ b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/warehouse/WarehouseRepository.java
@@ -27,6 +27,6 @@ import org.springframework.data.mongodb.repository.MongoRepository;
 import org.springframework.stereotype.Repository;
 
 @Repository
-public interface WarehouseRepository extends MongoRepository<DocumentEntry, String> {
+public interface WarehouseRepository extends MongoRepository<DocumentEntry, String>, CustomWarehouseRepository {
 
 }
diff --git a/aggregation-manager-job/src/main/resources/application-local.yml b/aggregation-manager-job/src/main/resources/application-local.yml
index 5757dad77b6cf41d257b0604abf036ac0cd2db2e..f971794e9d5962d901fa845a6421360ae558671a 100644
--- a/aggregation-manager-job/src/main/resources/application-local.yml
+++ b/aggregation-manager-job/src/main/resources/application-local.yml
@@ -11,7 +11,7 @@ spring:
     mongodb:
       host: localhost
       port: 27017
-      database: aggregation-manager
+      database: aggregation-manager-job
 
 ozgcloud:
   vorgang-manager:
diff --git a/aggregation-manager-job/src/test/helm-linter-values.yaml b/aggregation-manager-job/src/test/helm-linter-values.yaml
index 5024cc924057218b72df02830cac6d67890d6c54..ca9203d3b2911e7aa350f85a5b62f1264d4bf26e 100644
--- a/aggregation-manager-job/src/test/helm-linter-values.yaml
+++ b/aggregation-manager-job/src/test/helm-linter-values.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/aggregation-manager-job/src/test/helm/configmap_bindings_type_test.yaml b/aggregation-manager-job/src/test/helm/configmap_bindings_type_test.yaml
index 4ad5fad2df2de83511d9ba12123a90312e3c9383..b02634db1d638c1c5a52370c48b638f2a51bf8bd 100644
--- a/aggregation-manager-job/src/test/helm/configmap_bindings_type_test.yaml
+++ b/aggregation-manager-job/src/test/helm/configmap_bindings_type_test.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
@@ -45,7 +45,7 @@ tests:
           of: v1
       - equal:
           path: metadata.name
-          value: aggregation-manager-bindings-type
+          value: aggregation-manager-job-bindings-type
       - equal:
           path: metadata.namespace
           value: sh-helm-test
diff --git a/aggregation-manager-job/src/test/helm/cronjob_database_test.yaml b/aggregation-manager-job/src/test/helm/cronjob_database_test.yaml
index 38ad6f7b0f126f207b87941bc8ed2a7eb4a479b8..e29aca6a4f7fe3f44eb4b75a93e96f38abe1a7ab 100644
--- a/aggregation-manager-job/src/test/helm/cronjob_database_test.yaml
+++ b/aggregation-manager-job/src/test/helm/cronjob_database_test.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
@@ -68,14 +68,14 @@ tests:
             name: spring_data_mongodb_uri
             valueFrom:
               secretKeyRef:
-                name: ozg-mongodb-admin-aggregation-manager-user
+                name: ozg-mongodb-admin-aggregation-manager-job-user
                 key: connectionString.standardSrv
                 optional: false
       - contains:
           path: spec.jobTemplate.spec.template.spec.containers[0].env
           content:
             name: spring_data_mongodb_database
-            value: aggregation-manager-database
+            value: aggregation-manager-job-database
   - it: should configure external mongodb if useExternal
     set:
       database.useExternal: true
@@ -84,7 +84,7 @@ tests:
           path: spec.jobTemplate.spec.template.spec.containers[0].envFrom
           content:
             secretRef:
-              name: ozg-mongodb-admin-aggregation-manager-user
+              name: ozg-mongodb-admin-aggregation-manager-job-user
   - it: should not have a volume for the mongodb certificate if tls is disabled
     set:
       database:
diff --git a/aggregation-manager-job/src/test/helm/cronjob_defaults_labels_test.yaml b/aggregation-manager-job/src/test/helm/cronjob_defaults_labels_test.yaml
index 73dcd9d8c5ceb04c576b9de17a2e88573c5db111..faf075d5cd2ff5765ace191962d0adc91cec7199 100644
--- a/aggregation-manager-job/src/test/helm/cronjob_defaults_labels_test.yaml
+++ b/aggregation-manager-job/src/test/helm/cronjob_defaults_labels_test.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/aggregation-manager-job/src/test/helm/cronjob_env_test.yaml b/aggregation-manager-job/src/test/helm/cronjob_env_test.yaml
index 0964a3526aea3d15e15096043c5ee4e86a0bcc60..14aad4dd395c276f8554bbf53b2acce46e02be3f 100644
--- a/aggregation-manager-job/src/test/helm/cronjob_env_test.yaml
+++ b/aggregation-manager-job/src/test/helm/cronjob_env_test.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/aggregation-manager-job/src/test/helm/cronjob_image_pull_secret_test.yaml b/aggregation-manager-job/src/test/helm/cronjob_image_pull_secret_test.yaml
index d20bffe4aae3d5fbe916855fad80f0663b279f99..c8138c28f1a946e9885c3bc2cbd4a32bbb870791 100644
--- a/aggregation-manager-job/src/test/helm/cronjob_image_pull_secret_test.yaml
+++ b/aggregation-manager-job/src/test/helm/cronjob_image_pull_secret_test.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/aggregation-manager-job/src/test/helm/cronjob_resources_test.yaml b/aggregation-manager-job/src/test/helm/cronjob_resources_test.yaml
index 5f244b3b4a85e532c67b0d1ed0481f29ef74c730..09be4bc145d470acb07bfa37cc06288273e073c2 100644
--- a/aggregation-manager-job/src/test/helm/cronjob_resources_test.yaml
+++ b/aggregation-manager-job/src/test/helm/cronjob_resources_test.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/aggregation-manager-job/src/test/helm/cronjob_service_account_test.yaml b/aggregation-manager-job/src/test/helm/cronjob_service_account_test.yaml
index 332566087ce7f807da1498f491f82ba8b4fafc8b..588230c574e77c0e8962f2b24490e0ae951a589b 100644
--- a/aggregation-manager-job/src/test/helm/cronjob_service_account_test.yaml
+++ b/aggregation-manager-job/src/test/helm/cronjob_service_account_test.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/aggregation-manager-job/src/test/helm/cronjob_spring_profile_test.yaml b/aggregation-manager-job/src/test/helm/cronjob_spring_profile_test.yaml
index 4a52ee5a0e5c33f80397ba62c140753e76d8ce3c..633e3513c7963674606ea6f62440aa918cfde4db 100644
--- a/aggregation-manager-job/src/test/helm/cronjob_spring_profile_test.yaml
+++ b/aggregation-manager-job/src/test/helm/cronjob_spring_profile_test.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/aggregation-manager-job/src/test/helm/cronjob_test.yaml b/aggregation-manager-job/src/test/helm/cronjob_test.yaml
index b0540adeca68d8816d0debb67f272ec0ee51e9ed..119c1a1904ed7fb296c0a12791e084a21547555a 100644
--- a/aggregation-manager-job/src/test/helm/cronjob_test.yaml
+++ b/aggregation-manager-job/src/test/helm/cronjob_test.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/aggregation-manager-job/src/test/helm/cronjob_volume_test.yaml b/aggregation-manager-job/src/test/helm/cronjob_volume_test.yaml
index e80b13548745b47f37aeef1ab5085cfcb6924011..ba68ac06939502e39060c8896ed71770b9ac233d 100644
--- a/aggregation-manager-job/src/test/helm/cronjob_volume_test.yaml
+++ b/aggregation-manager-job/src/test/helm/cronjob_volume_test.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
@@ -80,7 +80,7 @@ tests:
           value: "bindings"
       - equal:
           path: spec.jobTemplate.spec.template.spec.volumes[0].configMap.name
-          value: "aggregation-manager-bindings-type"
+          value: "aggregation-manager-job-bindings-type"
       - equal:
           path: spec.jobTemplate.spec.template.spec.volumes[1].name
           value: "mongodb-root-ca"
diff --git a/aggregation-manager-job/src/test/helm/network_policy_test.yaml b/aggregation-manager-job/src/test/helm/network_policy_test.yaml
index 726b2d325b6ef1ec78279de9475ccc041e0d1278..f680b3e541d58d4a3e1db1aae30e5f821152dcc7 100644
--- a/aggregation-manager-job/src/test/helm/network_policy_test.yaml
+++ b/aggregation-manager-job/src/test/helm/network_policy_test.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/aggregation-manager-job/src/test/helm/service_account_test.yaml b/aggregation-manager-job/src/test/helm/service_account_test.yaml
index 7cd967ba28fca4e359d0ed4eff8536fe9fbabf99..532d556ef4480f0ece2decd8ad3b6350bb2cd2de 100644
--- a/aggregation-manager-job/src/test/helm/service_account_test.yaml
+++ b/aggregation-manager-job/src/test/helm/service_account_test.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/aggregation-manager-job/src/test/helm/service_monitor_test.yaml b/aggregation-manager-job/src/test/helm/service_monitor_test.yaml
index de007a9880e9b8de50b4af3127ad49192e15b761..de7e81b9383c35803f6677bd781b6a7cd96e0c7c 100644
--- a/aggregation-manager-job/src/test/helm/service_monitor_test.yaml
+++ b/aggregation-manager-job/src/test/helm/service_monitor_test.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/aggregation-manager-job/src/test/helm/service_test.yaml b/aggregation-manager-job/src/test/helm/service_test.yaml
index 59659253452be9688c98d1e032754ce05da81cf5..99060f8e11ade7f6ffcabc7c90db318e48dd9d8a 100644
--- a/aggregation-manager-job/src/test/helm/service_test.yaml
+++ b/aggregation-manager-job/src/test/helm/service_test.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/AggregationManagerApplicationTest.java b/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/AggregationManagerApplicationTest.java
index 2a71c5380dce4dcf86d7eab02d44e6fa16842cac..a4435962dfe31959a66dd33a574de6290a0a6597 100644
--- a/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/AggregationManagerApplicationTest.java
+++ b/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/AggregationManagerApplicationTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * 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
diff --git a/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/AggregationManagerRunnerITCase.java b/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/AggregationManagerRunnerITCase.java
index c7ebb19305b6318b97af1787a0acb02456d4c084..7be8d55ab3d28d778ca582d07176f4d6082fe650 100644
--- a/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/AggregationManagerRunnerITCase.java
+++ b/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/AggregationManagerRunnerITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * 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
diff --git a/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/AggregationManagerRunnerTest.java b/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/AggregationManagerRunnerTest.java
index 1e578c804c4a8caa7022cce046ec08f37c059fcc..ef2a1f26bb2fdfbcdf47a5dcd7d2f6292f63b661 100644
--- a/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/AggregationManagerRunnerTest.java
+++ b/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/AggregationManagerRunnerTest.java
@@ -29,42 +29,26 @@ import static org.mockito.Mockito.*;
 
 import java.util.Collections;
 import java.util.List;
-import java.util.Optional;
-import java.util.UUID;
-import java.util.function.Function;
-import java.util.stream.Stream;
 
+import org.apache.commons.lang3.RandomUtils;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
-import org.mockito.ArgumentCaptor;
 import org.mockito.ArgumentMatcher;
-import org.mockito.Captor;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
 
 import com.thedeanda.lorem.LoremIpsum;
 
-import de.ozgcloud.aggregation.AggregationManagerRunner.Batch;
 import de.ozgcloud.aggregation.AggregationManagerRunner.Execution;
 import de.ozgcloud.aggregation.transformation.AggregationMapping;
-import de.ozgcloud.aggregation.transformation.AggregationMapping.FormIdentifier;
 import de.ozgcloud.aggregation.transformation.AggregationMappingTestFactory;
-import de.ozgcloud.aggregation.transformation.FormIdentifierTestFactory;
 import de.ozgcloud.aggregation.transformation.Transformation;
 import de.ozgcloud.aggregation.transformation.TransformationService;
 import de.ozgcloud.aggregation.transformation.VorgangMapper;
-import de.ozgcloud.aggregation.warehouse.DocumentEntry;
-import de.ozgcloud.aggregation.warehouse.DocumentEntryTestFactory;
 import de.ozgcloud.aggregation.warehouse.WarehouseRepository;
-import de.ozgcloud.apilib.vorgang.OzgCloudVorgang;
-import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery;
 import de.ozgcloud.apilib.vorgang.OzgCloudVorgangService;
-import de.ozgcloud.apilib.vorgang.OzgCloudVorgangStub;
-import de.ozgcloud.apilib.vorgang.OzgCloudVorgangStubTestFactory;
-import de.ozgcloud.apilib.vorgang.OzgCloudVorgangTestFactory;
-import de.ozgcloud.apilib.vorgang.Page;
 
 class AggregationManagerRunnerTest {
 
@@ -80,9 +64,11 @@ class AggregationManagerRunnerTest {
 	private WarehouseRepository repository;
 	@Mock
 	private VorgangMapper vorgangMapper;
+	@Mock
+	private static Aggregator aggregator;
 	@Spy
 	@InjectMocks
-	private AggregationManagerRunner runner;
+	private AggregationManagerRunnerImpl runner;
 
 	@Nested
 	class TestRun {
@@ -135,8 +121,8 @@ class AggregationManagerRunnerTest {
 			void shouldRunWithTransformationForEachTransformation() {
 				runner.run();
 
-				verify(runner).runWithTransformation(firstTransformation, Optional.of(AggregationMappingTestFactory.FORM_IDENTIFIER));
-				verify(runner).runWithTransformation(secondTransformation, Optional.of(AggregationMappingTestFactory.FORM_IDENTIFIER));
+				verify(runner).runWithTransformation(firstTransformation, aggregationMappings.get(0));
+				verify(runner).runWithTransformation(secondTransformation, aggregationMappings.get(1));
 			}
 		}
 
@@ -159,10 +145,10 @@ class AggregationManagerRunnerTest {
 			}
 
 			@Test
-			void shouldCallRunWithTransformation() {
+			void shouldCallRunWithDefaultTransformation() {
 				runner.run();
 
-				verify(runner).runWithTransformation(transformation, Optional.empty());
+				verify(runner).runWithDefaultTransformation(transformation);
 			}
 		}
 
@@ -185,386 +171,124 @@ class AggregationManagerRunnerTest {
 			}
 
 			@Test
-			void shouldCallRunWithTransformation() {
+			void shouldCallRunWithDefaultTransformation() {
 				runner.run();
 
-				verify(runner).runWithTransformation(transformation, Optional.empty());
+				verify(runner).runWithDefaultTransformation(transformation);
 			}
 		}
 	}
 
 	@Nested
-	class TestRunWithTransformation {
+	class TestRunWithDefaultTransformation {
 
 		@Mock
 		private Transformation transformation;
-		private final ArgumentMatcher<Execution> hasTransformation = execution -> execution.getTransformation().equals(transformation);
-		private final Optional<FormIdentifier> formIdentifier = Optional.of(FormIdentifierTestFactory.create());
-		@Mock
-		private Batch batchOfVorgaenge;
-		@Mock
-		private Batch batchOfDeletedVorgaenge;
-		@Captor
-		private ArgumentCaptor<Stream<Batch>> batchStreamCaptor;
-
-		@BeforeEach
-		void init() {
-			doReturn(Stream.of(batchOfVorgaenge)).when(runner).extractBatchesOfVorgaengeFromDataSource(any(), any());
-			doReturn(Stream.of(batchOfDeletedVorgaenge)).when(runner).extractBatchesOfDeletedVorgaengeFromDataSource(any(), any());
-			doNothing().when(runner).loadVorgaengeIntoRepository(any());
-		}
 
 		@Test
-		void shouldExtractBatchesOfVorgaengeFromDataSource() {
-			runner.runWithTransformation(transformation, formIdentifier);
-
-			verify(runner).extractBatchesOfVorgaengeFromDataSource(argThat(hasTransformation), eq(formIdentifier));
-		}
+		void shouldCallRunWithTransformation() {
+			doNothing().when(runner).runWithTransformation(any(), any());
 
-		@Test
-		void shouldExtractBatchesOfDeletedVorgaengeFromDataSource() {
-			runner.runWithTransformation(transformation, formIdentifier);
+			runner.runWithDefaultTransformation(transformation);
 
-			verify(runner).extractBatchesOfDeletedVorgaengeFromDataSource(argThat(hasTransformation), eq(formIdentifier));
-		}
-
-		@Test
-		void shouldLoadVorgaengeIntoRepository() {
-			runner.runWithTransformation(transformation, formIdentifier);
-
-			verify(runner).loadVorgaengeIntoRepository(batchStreamCaptor.capture());
-			assertThat(batchStreamCaptor.getValue()).containsExactly(batchOfVorgaenge, batchOfDeletedVorgaenge);
+			verify(runner).runWithTransformation(eq(transformation), isNull());
 		}
 	}
 
 	@Nested
-	class TestLoadVorgaengeIntoRepository {
+	class TestRunWithTransformation {
 
 		@Mock
-		private Execution execution;
-		@Mock
-		private Batch batch;
-		private final DocumentEntry documentEntry = DocumentEntryTestFactory.create();
-		@Captor
-		private ArgumentCaptor<Stream<DocumentEntry>> documentEntriesCaptor;
+		private Transformation transformation;
+		private final AggregationMapping aggregationMapping = AggregationMappingTestFactory.create();
+		private final ArgumentMatcher<Execution> hasTransformation = execution -> execution.getTransformation().equals(transformation);
 
 		@BeforeEach
-		void init() {
-			doReturn(Stream.of(documentEntry)).when(runner).transformBatchToDocumentEntries(any());
-			doNothing().when(runner).loadDocumentEntriesIntoRepository(any());
-		}
-
-		@Test
-		void shouldDropCollection() {
-			loadVorgaengeIntoRepository();
-
-			verify(repository).deleteAll();
+		void mock() {
+			doReturn(aggregator).when(runner).prepareAggregator(any(), any());
 		}
 
 		@Test
-		void shouldTransform() {
-			loadVorgaengeIntoRepository();
+		void shouldCallPrepareAggregator() {
+			runWithTransformation();
 
-			verify(runner).transformBatchToDocumentEntries(batch);
+			verify(runner).prepareAggregator(argThat(hasTransformation), eq(aggregationMapping));
 		}
 
 		@Test
-		void shouldLoadIntoRepository() {
-			loadVorgaengeIntoRepository();
+		void shouldLoadAggregation() {
+			runWithTransformation();
 
-			verify(runner).loadDocumentEntriesIntoRepository(documentEntriesCaptor.capture());
-			assertThat(documentEntriesCaptor.getValue()).containsExactly(documentEntry);
+			verify(aggregator).aggregate();
 		}
 
-		private void loadVorgaengeIntoRepository() {
-			runner.loadVorgaengeIntoRepository(Stream.of(batch));
+		private void runWithTransformation() {
+			runner.runWithTransformation(transformation, aggregationMapping);
 		}
 	}
 
 	@Nested
-	class TestExtractBatchesOfVorgaengeFromDataSource {
+	class TestPrepareAggregator {
 
-		private final Optional<FormIdentifier> formIdentifier = Optional.of(FormIdentifierTestFactory.create());
 		@Mock
 		private Execution execution;
-		@Captor
-		private ArgumentCaptor<Function<Page, List<OzgCloudVorgang>>> functionToRetrieveDataCaptor;
-		@Mock
-		private Batch batch;
-		@Mock
-		private Page page;
+		private final AggregationMapping aggregationMapping = AggregationMappingTestFactory.create();
+		private final int batchSize = RandomUtils.insecure().randomInt();
 
 		@BeforeEach
-		void init() {
-			doReturn(Stream.of(batch)).when(runner).extractBatchesFromDataSource(any(), any());
-		}
-
-		@Test
-		void shouldExtract() {
-			runner.extractBatchesOfVorgaengeFromDataSource(execution, formIdentifier);
-
-			verify(runner).extractBatchesFromDataSource(eq(execution), any());
-		}
-
-		@Test
-		void shouldExtractWithDataRetrievalFunction() {
-			runner.extractBatchesOfVorgaengeFromDataSource(execution, formIdentifier);
-
-			verify(runner).extractBatchesFromDataSource(eq(execution), functionToRetrieveDataCaptor.capture());
-			functionToRetrieveDataCaptor.getValue().apply(page);
-			verify(runner).getVorgaengeFromDataSource(page, formIdentifier);
-		}
-
-		@Test
-		void shouldReturnExtractedBatches() {
-			var extracted = runner.extractBatchesOfVorgaengeFromDataSource(execution, formIdentifier);
-
-			assertThat(extracted).containsExactly(batch);
-		}
-	}
-
-	@Nested
-	class TestGetVorgaengeFromDataSource {
-
-		private final Page page = Page.builder().offset(10).limit(2).build();
-		private final Optional<FormIdentifier> formIdentifier = Optional.of(FormIdentifierTestFactory.create());
-		private final OzgCloudVorgangQuery query = OzgCloudVorgangQuery.builder().build();
-
-		@BeforeEach
-		void init() {
-			doReturn(query).when(runner).buildFindByFormEngineQuery(any());
-			when(vorgangService.find(any(), any())).thenReturn(List.of(OzgCloudVorgangStubTestFactory.create()));
-			when(vorgangService.getById(any())).thenReturn(OzgCloudVorgangTestFactory.create());
-		}
-
-		@Test
-		void shouldCallBuildFindByFormEngineQuery() {
-			getVorgaengeFromDataSource();
-
-			verify(runner).buildFindByFormEngineQuery(formIdentifier);
+		void mock() {
+			when(config.getFetchingBatchSize()).thenReturn(batchSize);
+			when(aggregator.withExecution(any())).thenReturn(aggregator);
+			when(aggregator.withAggregationMapping(any())).thenReturn(aggregator);
+			when(aggregator.withBatchSize(anyInt())).thenReturn(aggregator);
 		}
 
 		@Test
-		void shouldCallVorgangService() {
-			getVorgaengeFromDataSource();
+		void shouldGetBatchSize() {
+			runner.prepareAggregator(execution, aggregationMapping);
 
-			verify(vorgangService).find(query, page);
+			verify(config).getFetchingBatchSize();
 		}
 
 		@Test
-		void shouldGetVorgangDetails() {
-			getVorgaengeFromDataSource();
+		void shouldSetExecution() {
+			runner.prepareAggregator(execution, aggregationMapping);
 
-			verify(vorgangService).getById(OzgCloudVorgangTestFactory.ID);
+			verify(aggregator).withExecution(execution);
 		}
 
 		@Test
-		void shouldReturnVorgangDetails() {
-			var vorgaenge = getVorgaengeFromDataSource();
-
-			assertThat(vorgaenge).usingRecursiveFieldByFieldElementComparator().containsExactly(OzgCloudVorgangTestFactory.create());
-		}
-
-		private List<OzgCloudVorgang> getVorgaengeFromDataSource() {
-			return runner.getVorgaengeFromDataSource(page, formIdentifier);
-		}
-	}
-
-	@Nested
-	class TestBuildFindByFormEngineQuery {
-
-		@Nested
-		class TestOnEmptyFormIdentifier {
-
-			@Test
-			void shouldReturnFindAllQueryOnEmptyFormIdentifier() {
-				var query = runner.buildFindByFormEngineQuery(Optional.empty());
-
-				assertThat(query).usingRecursiveComparison().isEqualTo(OzgCloudVorgangQuery.builder().build());
-			}
-		}
-
-		@Nested
-		class TestOnFormIdentifierNotEmpty {
-
-			private final Optional<FormIdentifier> formIdentifier = Optional.of(FormIdentifierTestFactory.create());
-
-			@Test
-			void shouldSetFormIdInQuery() {
-				var query = runner.buildFindByFormEngineQuery(formIdentifier);
-
-				assertThat(query.getForm()).get().extracting("formId").isEqualTo(FormIdentifierTestFactory.FORM_ID);
-			}
-
-			@Test
-			void shouldSetFormEngineNameInQuery() {
-				var query = runner.buildFindByFormEngineQuery(formIdentifier);
+		void shouldSetAggregationMapping() {
+			runner.prepareAggregator(execution, aggregationMapping);
 
-				assertThat(query.getForm()).get().extracting("formEngineName").isEqualTo(FormIdentifierTestFactory.FORM_ENGINE_NAME);
-			}
-		}
-	}
-
-	@Nested
-	class TestExtractBatchesOfDeletedVorgaengeFromDataSource {
-
-		@Mock
-		private Execution execution;
-		@Mock
-		private Function<Page, List<OzgCloudVorgang>> functionToRetrieveData;
-		private final List<OzgCloudVorgangStub> deletedVorgaenge = List.of(OzgCloudVorgangStubTestFactory.create());
-		@Captor
-		private ArgumentCaptor<Stream<OzgCloudVorgangStub>> deletedVorgaengeCaptor;
-		@Mock
-		private Batch batch;
-
-		@Nested
-		class TestOnEmptyFormIdentifier {
-
-			@BeforeEach
-			void init() {
-				when(vorgangService.findDeleted()).thenReturn(deletedVorgaenge.stream());
-				doReturn(functionToRetrieveData).when(runner).getPagedDeletedVorgaenge(any());
-				doReturn(Stream.of(batch)).when(runner).extractBatchesFromDataSource(any(), any());
-			}
-
-			@Test
-			void shouldFindDeleted() {
-				runner.extractBatchesOfDeletedVorgaengeFromDataSource(execution, Optional.empty());
-
-				verify(vorgangService).findDeleted();
-			}
-
-			@Test
-			void shouldGetPagedDeletedVorgaenge() {
-				runner.extractBatchesOfDeletedVorgaengeFromDataSource(execution, Optional.empty());
-
-				verify(runner).getPagedDeletedVorgaenge(deletedVorgaengeCaptor.capture());
-				assertThat(deletedVorgaengeCaptor.getValue()).usingRecursiveFieldByFieldElementComparator()
-						.containsExactlyElementsOf(deletedVorgaenge);
-			}
-
-			@Test
-			void shouldExtractWithDataRetrievalFunction() {
-				runner.extractBatchesOfDeletedVorgaengeFromDataSource(execution, Optional.empty());
-
-				verify(runner).extractBatchesFromDataSource(execution, functionToRetrieveData);
-			}
-
-			@Test
-			void shouldReturnExtractedBatches() {
-				var extracted = runner.extractBatchesOfDeletedVorgaengeFromDataSource(execution, Optional.empty());
-
-				assertThat(extracted).containsExactly(batch);
-			}
+			verify(aggregator).withAggregationMapping(aggregationMapping);
 		}
 
-		@Nested
-		class TestOnFormIdentifierNotEmpty {
-
-			private final Optional<FormIdentifier> formIdentifier = Optional.of(FormIdentifierTestFactory.create());
-
-			@Test
-			void shouldReturnEmptyStream() {
-				var extracted = runner.extractBatchesOfDeletedVorgaengeFromDataSource(execution, formIdentifier);
-
-				assertThat(extracted).isEmpty();
-			}
-		}
-	}
-
-	@Nested
-	class TestGetPagedDeletedVorgaenge {
-
-		private static final int PAGE_SIZE = 2;
-
-		private final Stream<OzgCloudVorgangStub> vorgangStubs = Stream.generate(OzgCloudVorgangStubTestFactory::create).limit(PAGE_SIZE + 1);
-
 		@Test
-		void shouldReturnFirstFullPage() {
-			var pagingFunction = runner.getPagedDeletedVorgaenge(vorgangStubs);
-
-			var vorgaenge = getFirstPage(pagingFunction);
+		void shouldSetBatchSize() {
+			runner.prepareAggregator(execution, aggregationMapping);
 
-			assertThat(vorgaenge).hasSize(PAGE_SIZE);
+			verify(aggregator).withBatchSize(batchSize);
 		}
 
 		@Test
-		void shouldReturnSecondPageWithOneElement() {
-			var pagingFunction = runner.getPagedDeletedVorgaenge(vorgangStubs);
-			getFirstPage(pagingFunction);
-
-			var vorgaenge = getSecondPage(pagingFunction);
-
-			assertThat(vorgaenge).hasSize(1);
-		}
+		void shouldReturnAggregator() {
+			var result = runner.prepareAggregator(execution, aggregationMapping);
 
-		private List<OzgCloudVorgang> getFirstPage(Function<Page, List<OzgCloudVorgang>> pagingFunction) {
-			return pagingFunction.apply(Page.builder().offset(0).limit(PAGE_SIZE).build());
-		}
-
-		private List<OzgCloudVorgang> getSecondPage(Function<Page, List<OzgCloudVorgang>> pagingFunction) {
-			return pagingFunction.apply(Page.builder().offset(PAGE_SIZE).limit(PAGE_SIZE).build());
+			assertThat(result).isEqualTo(aggregator);
 		}
 	}
 
-	@Nested
-	class TestExtractBatchesFromDataSource {
-
-		private static final int BATCH_SIZE = 2;
-		private static final List<OzgCloudVorgang> VORGAENGE_1 = List.of(OzgCloudVorgangTestFactory.create(), OzgCloudVorgangTestFactory.create());
-		private static final List<OzgCloudVorgang> VORGAENGE_2 = List.of(OzgCloudVorgangTestFactory.create());
-		private static final UUID BATCH_1_UUID = UUID.randomUUID();
-		private static final UUID BATCH_2_UUID = UUID.randomUUID();
-
-		@Mock
-		private Execution execution;
-		@Mock
-		private Function<Page, List<OzgCloudVorgang>> functionToRetrieveData;
-
-		@BeforeEach
-		void init() {
-			when(config.getFetchingBatchSize()).thenReturn(BATCH_SIZE);
-			when(functionToRetrieveData.apply(any())).thenReturn(VORGAENGE_1, VORGAENGE_2, List.of());
-			when(runner.createBatchUUID()).thenReturn(BATCH_1_UUID, BATCH_2_UUID);
-		}
-
-		@Test
-		void shouldCallFunctionToRetrieveDataForFirstPage() {
-			extractBatchesFromDataSource();
-
-			verify(functionToRetrieveData).apply(argThat(hasExpectedOffsetAndConfiguredLimit(0)));
-		}
-
-		@Test
-		void shouldCallFunctionToRetrieveDataForSecondPage() {
-			extractBatchesFromDataSource().toList();
-
-			verify(functionToRetrieveData).apply(argThat(hasExpectedOffsetAndConfiguredLimit(BATCH_SIZE)));
-		}
-
-		@Test
-		void shouldCallFunctionToRetrieveDataForThirdPage() {
-			extractBatchesFromDataSource().toList();
-
-			verify(functionToRetrieveData).apply(argThat(hasExpectedOffsetAndConfiguredLimit(BATCH_SIZE * 2)));
-		}
-
-		@Test
-		void shouldReturnBatches() {
-			var batches = extractBatchesFromDataSource().toList();
-
-			assertThat(batches).hasSize(2).usingRecursiveFieldByFieldElementComparator().containsExactly(
-					new Batch(execution, BATCH_1_UUID, Page.builder().offset(0).limit(BATCH_SIZE).build(), VORGAENGE_1),
-					new Batch(execution, BATCH_2_UUID, Page.builder().offset(BATCH_SIZE).limit(BATCH_SIZE).build(), VORGAENGE_2));
-		}
+	static class AggregationManagerRunnerImpl extends AggregationManagerRunner {
 
-		private ArgumentMatcher<Page> hasExpectedOffsetAndConfiguredLimit(int expectedOffset) {
-			return page -> page.getOffset() == expectedOffset && page.getLimit() == BATCH_SIZE;
+		public AggregationManagerRunnerImpl(AggregationManagerConfiguration config, TransformationProperties transformationProperties,
+				TransformationService transformationService) {
+			super(config, transformationProperties, transformationService);
 		}
 
-		private Stream<Batch> extractBatchesFromDataSource() {
-			return runner.extractBatchesFromDataSource(execution, functionToRetrieveData);
+		@Override
+		protected Aggregator createAggregator() {
+			return aggregator;
 		}
 	}
 }
diff --git a/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/AggregatorTest.java b/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/AggregatorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..2d66f74b8f51b0eb4abbd382b62aa780b98dce54
--- /dev/null
+++ b/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/AggregatorTest.java
@@ -0,0 +1,551 @@
+package de.ozgcloud.aggregation;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import org.apache.commons.lang3.RandomUtils;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Captor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import de.ozgcloud.aggregation.AggregationManagerRunner.Execution;
+import de.ozgcloud.aggregation.Aggregator.Batch;
+import de.ozgcloud.aggregation.transformation.AggregationMapping;
+import de.ozgcloud.aggregation.transformation.AggregationMapping.FormIdentifier;
+import de.ozgcloud.aggregation.transformation.AggregationMappingTestFactory;
+import de.ozgcloud.aggregation.transformation.FormIdentifierTestFactory;
+import de.ozgcloud.aggregation.transformation.Transformation;
+import de.ozgcloud.aggregation.transformation.VorgangMapper;
+import de.ozgcloud.aggregation.warehouse.DocumentEntry;
+import de.ozgcloud.aggregation.warehouse.DocumentEntryTestFactory;
+import de.ozgcloud.aggregation.warehouse.WarehouseRepository;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgang;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangService;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangStub;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangStubTestFactory;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangTestFactory;
+import de.ozgcloud.apilib.vorgang.Page;
+
+class AggregatorTest {
+
+	@InjectMocks
+	@Spy
+	private Aggregator aggregator;
+	@Mock
+	private Transformation transformation;
+	private final Execution execution = new Execution(transformation);
+	@Mock
+	private WarehouseRepository repository;
+	@Mock
+	private VorgangMapper vorgangMapper;
+	@Mock
+	private OzgCloudVorgangService vorgangService;
+
+	@Nested
+	class TestWithExecution {
+
+		@Test
+		void shouldReturnSelf() {
+			var result = aggregator.withExecution(execution);
+
+			assertThat(result).isSameAs(aggregator);
+		}
+
+		@Test
+		void shouldSetExecution() {
+			var result = aggregator.withExecution(execution);
+
+			assertThat(ReflectionTestUtils.getField(result, "execution")).isEqualTo(execution);
+		}
+	}
+
+	@Nested
+	class TestWithAggregationMapping {
+
+		@Nested
+		class TestOnNonNullAggregationMapping {
+
+			private final AggregationMapping aggregationMapping = AggregationMappingTestFactory.create();
+			private final FormIdentifier formIdentifier = AggregationMappingTestFactory.FORM_IDENTIFIER;
+			private final String collectionName = AggregationMappingTestFactory.NAME;
+
+			@Test
+			void shouldReturnSelf() {
+				var result = aggregator.withAggregationMapping(aggregationMapping);
+
+				assertThat(result).isSameAs(aggregator);
+			}
+
+			@Test
+			void shouldSetFormIdentifier() {
+				var result = aggregator.withAggregationMapping(aggregationMapping);
+
+				assertThat(ReflectionTestUtils.getField(result, "formIdentifier")).isEqualTo(formIdentifier);
+			}
+
+			@Test
+			void shouldSetCollectionName() {
+				var result = aggregator.withAggregationMapping(aggregationMapping);
+
+				assertThat(ReflectionTestUtils.getField(result, "collectionName")).isEqualTo(collectionName);
+			}
+		}
+
+		@Nested
+		class TestOnNullAggregationMapping {
+
+			@Test
+			void shouldReturnSelf() {
+				var result = aggregator.withAggregationMapping(null);
+
+				assertThat(result).isSameAs(aggregator);
+			}
+
+			@Test
+			void shouldNotSetFormIdentifier() {
+				var result = aggregator.withAggregationMapping(null);
+
+				assertThat(ReflectionTestUtils.getField(result, "formIdentifier")).isNull();
+			}
+
+			@Test
+			void shouldNotSetCollectionName() {
+				var result = aggregator.withAggregationMapping(null);
+
+				assertThat(ReflectionTestUtils.getField(result, "collectionName")).isEqualTo(DocumentEntry.COLLECTION);
+			}
+		}
+	}
+
+	@Nested
+	class TestWithBatchSize {
+
+		private final int batchSize = RandomUtils.insecure().randomInt();
+
+		@Test
+		void shouldReturnSelf() {
+			var result = aggregator.withBatchSize(batchSize);
+
+			assertThat(result).isSameAs(aggregator);
+		}
+
+		@Test
+		void shouldSetBatchSize() {
+			var result = aggregator.withBatchSize(batchSize);
+
+			assertThat(ReflectionTestUtils.getField(result, "batchSize")).isEqualTo(batchSize);
+		}
+	}
+
+	@Nested
+	class TestAggregate {
+		@Mock
+		private Batch batchOfVorgaenge;
+		@Mock
+		private Batch batchOfDeletedVorgaenge;
+		@Captor
+		private ArgumentCaptor<Stream<Batch>> batchStreamCaptor;
+
+		@BeforeEach
+		void setUp() {
+			doReturn(Stream.of(batchOfVorgaenge)).when(aggregator).extractBatchesOfVorgaengeFromDataSource();
+			doReturn(Stream.of(batchOfDeletedVorgaenge)).when(aggregator).extractBatchesOfDeletedVorgaengeFromDataSource();
+			doNothing().when(aggregator).loadVorgaengeIntoRepository(any());
+		}
+
+		@Test
+		void shouldExtractBatchesOfVorgaengeFromDataSource() {
+			aggregator.aggregate();
+
+			verify(aggregator).extractBatchesOfVorgaengeFromDataSource();
+		}
+
+		@Test
+		void shouldExtractBatchesOfDeletedVorgaengeFromDataSource() {
+			aggregator.aggregate();
+
+			verify(aggregator).extractBatchesOfDeletedVorgaengeFromDataSource();
+		}
+
+		@Test
+		void shouldLoadVorgaengeIntoRepository() {
+			aggregator.aggregate();
+
+			verify(aggregator).loadVorgaengeIntoRepository(batchStreamCaptor.capture());
+			assertThat(batchStreamCaptor.getValue()).containsExactly(batchOfVorgaenge, batchOfDeletedVorgaenge);
+		}
+	}
+
+	@Nested
+	class TestExtractBatchesOfVorgaengeFromDataSource {
+		@Captor
+		private ArgumentCaptor<Function<Page, List<OzgCloudVorgang>>> functionToRetrieveDataCaptor;
+		@Mock
+		private Batch batch;
+		@Mock
+		private Page page;
+
+		@BeforeEach
+		void init() {
+			doReturn(Stream.of(batch)).when(aggregator).extractBatchesFromDataSource(any());
+		}
+
+		@Test
+		void shouldExtractWithDataRetrievalFunction() {
+			doReturn(Collections.emptyList()).when(aggregator).getVorgaengeFromDataSource(any());
+
+			aggregator.extractBatchesOfVorgaengeFromDataSource();
+
+			verify(aggregator).extractBatchesFromDataSource(functionToRetrieveDataCaptor.capture());
+			functionToRetrieveDataCaptor.getValue().apply(page);
+			verify(aggregator).getVorgaengeFromDataSource(page);
+		}
+
+		@Test
+		void shouldReturnExtractedBatches() {
+			var extracted = aggregator.extractBatchesOfVorgaengeFromDataSource();
+
+			assertThat(extracted).containsExactly(batch);
+		}
+	}
+
+	@Nested
+	class TestGetVorgaengeFromDataSource {
+
+		private final Page page = Page.builder().offset(10).limit(2).build();
+		private final OzgCloudVorgangQuery query = OzgCloudVorgangQuery.builder().build();
+
+		@BeforeEach
+		void init() {
+			doReturn(query).when(aggregator).buildFindByFormEngineQuery();
+			when(vorgangService.find(any(), any())).thenReturn(List.of(OzgCloudVorgangStubTestFactory.create()));
+			when(vorgangService.getById(any())).thenReturn(OzgCloudVorgangTestFactory.create());
+		}
+
+		@Test
+		void shouldCallBuildFindByFormEngineQuery() {
+			getVorgaengeFromDataSource();
+
+			verify(aggregator).buildFindByFormEngineQuery();
+		}
+
+		@Test
+		void shouldCallVorgangService() {
+			getVorgaengeFromDataSource();
+
+			verify(vorgangService).find(query, page);
+		}
+
+		@Test
+		void shouldGetVorgangDetails() {
+			getVorgaengeFromDataSource();
+
+			verify(vorgangService).getById(OzgCloudVorgangTestFactory.ID);
+		}
+
+		@Test
+		void shouldReturnVorgangDetails() {
+			var vorgaenge = getVorgaengeFromDataSource();
+
+			assertThat(vorgaenge).usingRecursiveFieldByFieldElementComparator().containsExactly(OzgCloudVorgangTestFactory.create());
+		}
+
+		private List<OzgCloudVorgang> getVorgaengeFromDataSource() {
+			return aggregator.getVorgaengeFromDataSource(page);
+		}
+	}
+
+	@Nested
+	class TestBuildFindByFormEngineQuery {
+
+		@Nested
+		class TestOnFormIdentifierNull {
+
+			@Test
+			void shouldReturnFindAllQueryOnNullFormIdentifier() {
+				var query = aggregator.buildFindByFormEngineQuery();
+
+				assertThat(query).usingRecursiveComparison().isEqualTo(OzgCloudVorgangQuery.builder().build());
+			}
+		}
+
+		@Nested
+		class TestOnFormIdentifierNotNull {
+
+			private final AggregationMapping aggregationMapping = AggregationMappingTestFactory.create();
+
+			@BeforeEach
+			void init() {
+				aggregator = aggregator.withAggregationMapping(aggregationMapping);
+			}
+
+			@Test
+			void shouldSetFormIdInQuery() {
+				var query = aggregator.buildFindByFormEngineQuery();
+
+				assertThat(query.getForm()).get().extracting("formId").isEqualTo(FormIdentifierTestFactory.FORM_ID);
+			}
+
+			@Test
+			void shouldSetFormEngineNameInQuery() {
+				var query = aggregator.buildFindByFormEngineQuery();
+
+				assertThat(query.getForm()).get().extracting("formEngineName").isEqualTo(FormIdentifierTestFactory.FORM_ENGINE_NAME);
+			}
+		}
+	}
+
+	@Nested
+	class TestExtractBatchesOfDeletedVorgaengeFromDataSource {
+
+		@Mock
+		private Execution execution;
+		@Mock
+		private Function<Page, List<OzgCloudVorgang>> functionToRetrieveData;
+		private final List<OzgCloudVorgangStub> deletedVorgaenge = List.of(OzgCloudVorgangStubTestFactory.create());
+		@Captor
+		private ArgumentCaptor<Stream<OzgCloudVorgangStub>> deletedVorgaengeCaptor;
+		@Mock
+		private Batch batch;
+
+		@Nested
+		class TestOnFormIdentifierNull {
+
+			@BeforeEach
+			void init() {
+				when(vorgangService.findDeleted()).thenReturn(deletedVorgaenge.stream());
+				doReturn(functionToRetrieveData).when(aggregator).getPagedDeletedVorgaenge(any());
+				doReturn(Stream.of(batch)).when(aggregator).extractBatchesFromDataSource(any());
+			}
+
+			@Test
+			void shouldFindDeleted() {
+				aggregator.extractBatchesOfDeletedVorgaengeFromDataSource();
+
+				verify(vorgangService).findDeleted();
+			}
+
+			@Test
+			void shouldGetPagedDeletedVorgaenge() {
+				aggregator.extractBatchesOfDeletedVorgaengeFromDataSource();
+
+				verify(aggregator).getPagedDeletedVorgaenge(deletedVorgaengeCaptor.capture());
+				assertThat(deletedVorgaengeCaptor.getValue()).usingRecursiveFieldByFieldElementComparator()
+						.containsExactlyElementsOf(deletedVorgaenge);
+			}
+
+			@Test
+			void shouldExtractWithDataRetrievalFunction() {
+				aggregator.extractBatchesOfDeletedVorgaengeFromDataSource();
+
+				verify(aggregator).extractBatchesFromDataSource(functionToRetrieveData);
+			}
+
+			@Test
+			void shouldReturnExtractedBatches() {
+				var extracted = aggregator.extractBatchesOfDeletedVorgaengeFromDataSource();
+
+				assertThat(extracted).containsExactly(batch);
+			}
+		}
+
+		@Nested
+		class TestOnFormIdentifierNotNull {
+
+			private final AggregationMapping aggregationMapping = AggregationMappingTestFactory.create();
+
+			@BeforeEach
+			void init() {
+				aggregator = aggregator.withAggregationMapping(aggregationMapping);
+			}
+
+			@Test
+			void shouldNotFindDeleted() {
+				aggregator.extractBatchesOfDeletedVorgaengeFromDataSource();
+
+				verify(vorgangService, never()).findDeleted();
+			}
+
+			@Test
+			void shouldReturnEmptyStream() {
+				var extracted = aggregator.extractBatchesOfDeletedVorgaengeFromDataSource();
+
+				assertThat(extracted).isEmpty();
+			}
+		}
+	}
+
+	@Nested
+	class TestGetPagedDeletedVorgaenge {
+
+		private static final int PAGE_SIZE = 2;
+
+		private final Stream<OzgCloudVorgangStub> vorgangStubs = Stream.generate(OzgCloudVorgangStubTestFactory::create).limit(PAGE_SIZE + 1);
+
+		@Test
+		void shouldReturnFirstFullPage() {
+			var pagingFunction = aggregator.getPagedDeletedVorgaenge(vorgangStubs);
+
+			var vorgaenge = getFirstPage(pagingFunction);
+
+			assertThat(vorgaenge).hasSize(PAGE_SIZE);
+		}
+
+		@Test
+		void shouldReturnSecondPageWithOneElement() {
+			var pagingFunction = aggregator.getPagedDeletedVorgaenge(vorgangStubs);
+			getFirstPage(pagingFunction);
+
+			var vorgaenge = getSecondPage(pagingFunction);
+
+			assertThat(vorgaenge).hasSize(1);
+		}
+
+		private List<OzgCloudVorgang> getFirstPage(Function<Page, List<OzgCloudVorgang>> pagingFunction) {
+			return pagingFunction.apply(Page.builder().offset(0).limit(PAGE_SIZE).build());
+		}
+
+		private List<OzgCloudVorgang> getSecondPage(Function<Page, List<OzgCloudVorgang>> pagingFunction) {
+			return pagingFunction.apply(Page.builder().offset(PAGE_SIZE).limit(PAGE_SIZE).build());
+		}
+	}
+
+	@Nested
+	class TestExtractBatchesFromDataSource {
+
+		private static final int BATCH_SIZE = 2;
+		private static final List<OzgCloudVorgang> VORGAENGE_1 = List.of(OzgCloudVorgangTestFactory.create(), OzgCloudVorgangTestFactory.create());
+		private static final List<OzgCloudVorgang> VORGAENGE_2 = List.of(OzgCloudVorgangTestFactory.create());
+		private static final UUID BATCH_1_UUID = UUID.randomUUID();
+		private static final UUID BATCH_2_UUID = UUID.randomUUID();
+
+		@Mock
+		private Function<Page, List<OzgCloudVorgang>> functionToRetrieveData;
+
+		@SuppressWarnings("unchecked")
+		@BeforeEach
+		void init() {
+			aggregator = aggregator.withBatchSize(BATCH_SIZE).withExecution(execution);
+			when(functionToRetrieveData.apply(any())).thenReturn(VORGAENGE_1, VORGAENGE_2, Collections.emptyList());
+			when(aggregator.createBatchUUID()).thenReturn(BATCH_1_UUID, BATCH_2_UUID);
+		}
+
+		@Test
+		void shouldCallFunctionToRetrieveDataForFirstPage() {
+			extractBatchesFromDataSource();
+
+			verify(functionToRetrieveData).apply(argThat(hasExpectedOffsetAndConfiguredLimit(0)));
+		}
+
+		@Test
+		void shouldCallFunctionToRetrieveDataForSecondPage() {
+			extractBatchesFromDataSource().toList();
+
+			verify(functionToRetrieveData).apply(argThat(hasExpectedOffsetAndConfiguredLimit(BATCH_SIZE)));
+		}
+
+		@Test
+		void shouldCallFunctionToRetrieveDataForThirdPage() {
+			extractBatchesFromDataSource().toList();
+
+			verify(functionToRetrieveData).apply(argThat(hasExpectedOffsetAndConfiguredLimit(BATCH_SIZE * 2)));
+		}
+
+		@Test
+		void shouldReturnBatches() {
+			var batches = extractBatchesFromDataSource().toList();
+
+			assertThat(batches).hasSize(2).usingRecursiveFieldByFieldElementComparator().containsExactly(
+					new Batch(execution, BATCH_1_UUID, Page.builder().offset(0).limit(BATCH_SIZE).build(), VORGAENGE_1),
+					new Batch(execution, BATCH_2_UUID, Page.builder().offset(BATCH_SIZE).limit(BATCH_SIZE).build(), VORGAENGE_2));
+		}
+
+		private ArgumentMatcher<Page> hasExpectedOffsetAndConfiguredLimit(int expectedOffset) {
+			return page -> page.getOffset() == expectedOffset && page.getLimit() == BATCH_SIZE;
+		}
+
+		private Stream<Batch> extractBatchesFromDataSource() {
+			return aggregator.extractBatchesFromDataSource(functionToRetrieveData);
+		}
+	}
+
+	@Nested
+	class TestLoadVorgaengeIntoRepository {
+
+		@Mock
+		private Execution execution;
+		@Mock
+		private Batch batch;
+		private final DocumentEntry documentEntry = DocumentEntryTestFactory.create();
+		private final AggregationMapping aggregationMapping = AggregationMappingTestFactory.create();
+		@Captor
+		private ArgumentCaptor<List<DocumentEntry>> documentEntriesCaptor;
+
+		@BeforeEach
+		void init() {
+			aggregator = aggregator.withAggregationMapping(aggregationMapping);
+			doReturn(List.of(documentEntry)).when(aggregator).transformBatchToDocumentEntries(any());
+			doNothing().when(aggregator).loadDocumentEntriesIntoRepository(any());
+		}
+
+		@Test
+		void shouldDropCollection() {
+			loadVorgaengeIntoRepository();
+
+			verify(repository).clearCollection(AggregationMappingTestFactory.NAME);
+		}
+
+		@Test
+		void shouldTransform() {
+			loadVorgaengeIntoRepository();
+
+			verify(aggregator).transformBatchToDocumentEntries(batch);
+		}
+
+		@Test
+		void shouldLoadIntoRepository() {
+			loadVorgaengeIntoRepository();
+
+			verify(aggregator).loadDocumentEntriesIntoRepository(documentEntriesCaptor.capture());
+			assertThat(documentEntriesCaptor.getValue()).containsExactly(documentEntry);
+		}
+
+		private void loadVorgaengeIntoRepository() {
+			aggregator.loadVorgaengeIntoRepository(Stream.of(batch));
+		}
+	}
+
+	@Nested
+	class TestLoadDocumentEntriesIntoRepository {
+
+		private final List<DocumentEntry> documentEntries = List.of(DocumentEntryTestFactory.create());
+		private final AggregationMapping aggregationMapping = AggregationMappingTestFactory.create();
+
+		@BeforeEach
+		void init() {
+			aggregator = aggregator.withAggregationMapping(aggregationMapping);
+		}
+
+		@Test
+		void shouldSaveDocumentEntriesInCollection() {
+			aggregator.loadDocumentEntriesIntoRepository(documentEntries);
+
+			verify(repository).saveAllInCollection(documentEntries, AggregationMappingTestFactory.NAME);
+		}
+	}
+}
diff --git a/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/transformation/AggregationMappingTestFactory.java b/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/transformation/AggregationMappingTestFactory.java
index 4be105f1284cafaef138f184ae54625242ad50e5..44a5c25ce128edf4625a5b95ab27d772bb621c46 100644
--- a/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/transformation/AggregationMappingTestFactory.java
+++ b/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/transformation/AggregationMappingTestFactory.java
@@ -23,6 +23,8 @@
  */
 package de.ozgcloud.aggregation.transformation;
 
+import com.thedeanda.lorem.LoremIpsum;
+
 import de.ozgcloud.aggregation.transformation.AggregationMapping.AggregationMappingBuilder;
 import de.ozgcloud.aggregation.transformation.AggregationMapping.FieldMapping;
 import de.ozgcloud.aggregation.transformation.AggregationMapping.FormIdentifier;
@@ -31,6 +33,7 @@ public class AggregationMappingTestFactory {
 
 	public static final FormIdentifier FORM_IDENTIFIER = FormIdentifierTestFactory.create();
 	public static final FieldMapping MAPPING = FieldMappingTestFactory.create();
+	public static final String NAME = LoremIpsum.getInstance().getWords(1);
 
 	public static AggregationMapping create() {
 		return createBuilder().build();
@@ -39,6 +42,7 @@ public class AggregationMappingTestFactory {
 	public static AggregationMappingBuilder createBuilder() {
 		return AggregationMapping.builder()
 				.formIdentifier(FORM_IDENTIFIER)
-				.fieldMapping(MAPPING);
+				.fieldMapping(MAPPING)
+				.name(NAME);
 	}
 }
diff --git a/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/warehouse/CustomWarehouseRepositoryImplTest.java b/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/warehouse/CustomWarehouseRepositoryImplTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..194a372bc2330c39c339baab737c0bf879fba26e
--- /dev/null
+++ b/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/warehouse/CustomWarehouseRepositoryImplTest.java
@@ -0,0 +1,88 @@
+package de.ozgcloud.aggregation.warehouse;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.List;
+
+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 org.springframework.data.mongodb.core.MongoTemplate;
+
+import com.thedeanda.lorem.LoremIpsum;
+
+class CustomWarehouseRepositoryImplTest {
+
+	@Spy
+	@InjectMocks
+	private CustomWarehouseRepositoryImpl repository;
+
+	@Mock
+	private MongoTemplate mongoTemplate;
+
+	@Nested
+	class TestSaveAllInCollection {
+
+		private final DocumentEntry documentEntry = DocumentEntryTestFactory.create();
+		private final List<DocumentEntry> documentEntries = List.of(documentEntry);
+		private final String collectionName = LoremIpsum.getInstance().getWords(1);
+
+		@Test
+		void shouldCallSaveInCollection() {
+			repository.saveAllInCollection(documentEntries, collectionName);
+
+			verify(repository).saveInCollection(documentEntry, collectionName);
+		}
+
+		@Test
+		void shouldReturnSavedDocumentEntry() {
+			var savedDocumentEntry = DocumentEntryTestFactory.create();
+			doReturn(savedDocumentEntry).when(repository).saveInCollection(any(), any());
+
+			var returnedDocumentEntries = repository.saveAllInCollection(documentEntries, collectionName);
+
+			assertThat(returnedDocumentEntries).containsExactly(savedDocumentEntry);
+		}
+	}
+
+	@Nested
+	class TestSaveInCollection {
+
+		private final DocumentEntry documentEntry = DocumentEntryTestFactory.create();
+		private final String collectionName = LoremIpsum.getInstance().getWords(1);
+
+		@Test
+		void testSaveInCollection() {
+			repository.saveInCollection(documentEntry, collectionName);
+
+			verify(mongoTemplate).save(documentEntry, collectionName);
+		}
+
+		@Test
+		void shouldReturnSavedDocumentEntry() {
+			var savedDocumentEntry = DocumentEntryTestFactory.create();
+			when(mongoTemplate.save(documentEntry, collectionName)).thenReturn(savedDocumentEntry);
+
+			var returnedDocumentEntry = repository.saveInCollection(documentEntry, collectionName);
+
+			assertThat(returnedDocumentEntry).isEqualTo(savedDocumentEntry);
+		}
+	}
+
+	@Nested
+	class TestDeleteCollection {
+
+		private final String collectionName = LoremIpsum.getInstance().getWords(1);
+
+		@Test
+		void shouldDropCollection() {
+			repository.clearCollection(collectionName);
+
+			verify(mongoTemplate).dropCollection(collectionName);
+		}
+	}
+}
diff --git a/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/warehouse/WarehouseRepositoryITCase.java b/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/warehouse/WarehouseRepositoryITCase.java
index 18a3ab40118388b784fee2bfe17873ae5ec811d7..ad1c860d0f6006f1c13a5ca3cf5c349863bf136d 100644
--- a/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/warehouse/WarehouseRepositoryITCase.java
+++ b/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/warehouse/WarehouseRepositoryITCase.java
@@ -32,6 +32,8 @@ import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.mongodb.core.MongoOperations;
 
+import com.thedeanda.lorem.LoremIpsum;
+
 import de.ozgcloud.common.test.DataITCase;
 
 @DataITCase
@@ -57,7 +59,33 @@ class WarehouseRepositoryITCase {
 			var foundDocument = mongoOperations.findById(savedDocument.getId(), Document.class, DocumentEntry.COLLECTION);
 			assertThat(foundDocument.getString("_class")).isEqualTo("Vorgang");
 		}
+	}
+
+	@Nested
+	class TestSaveInCollection {
 
+		private final String collectionName = LoremIpsum.getInstance().getWords(1);
+
+		@Test
+		void shouldSaveInCollection() {
+			repository.saveInCollection(DocumentEntryTestFactory.create(), collectionName);
+
+			assertThat(mongoOperations.getCollection(collectionName).countDocuments()).isOne();
+		}
 	}
 
+	@Nested
+	class TestClearCollection {
+
+		private final String collectionName = LoremIpsum.getInstance().getWords(1);
+
+		@Test
+		void shouldClearCollection() {
+			mongoOperations.save(DocumentEntryTestFactory.create(), collectionName);
+
+			repository.clearCollection(collectionName);
+
+			assertThat(mongoOperations.getCollection(collectionName).countDocuments()).isZero();
+		}
+	}
 }
diff --git a/aggregation-manager-server/lombok.config b/aggregation-manager-server/lombok.config
new file mode 100644
index 0000000000000000000000000000000000000000..f8d3b76385742905b4dac9085c349034013f2b97
--- /dev/null
+++ b/aggregation-manager-server/lombok.config
@@ -0,0 +1,32 @@
+#
+# 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.
+#
+
+lombok.log.fieldName=LOG
+lombok.log.slf4j.flagUsage = ERROR
+lombok.log.log4j.flagUsage = ERROR
+lombok.data.flagUsage = ERROR
+lombok.nonNull.exceptionType = IllegalArgumentException
+lombok.addLombokGeneratedAnnotation = true
+lombok.copyableAnnotations += org.springframework.beans.factory.annotation.Qualifier
+lombok.copyableAnnotations += net.devh.boot.grpc.client.inject.GrpcClient
\ No newline at end of file
diff --git a/aggregation-manager-server/pom.xml b/aggregation-manager-server/pom.xml
index b8ab821717693bdd2e3db592d80cc3644e5acd22..f72df101935087b497fda650bd741251e80a62fc 100644
--- a/aggregation-manager-server/pom.xml
+++ b/aggregation-manager-server/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+    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
diff --git a/aggregation-manager-server/src/main/helm/Chart.yaml b/aggregation-manager-server/src/main/helm/Chart.yaml
index a4ac9f3a43b648896d9bd440117f37228c9f01f2..4c3c0f25a70c0969fc179e41e3ca25f354ba9a8b 100644
--- a/aggregation-manager-server/src/main/helm/Chart.yaml
+++ b/aggregation-manager-server/src/main/helm/Chart.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/aggregation-manager-server/src/main/helm/templates/_helpers.tpl b/aggregation-manager-server/src/main/helm/templates/_helpers.tpl
index 9f2c1fc28a0df6ab40790fb3202c2257ac5ea362..282313ebc33dd0695c821d2991c9001edba0f929 100644
--- a/aggregation-manager-server/src/main/helm/templates/_helpers.tpl
+++ b/aggregation-manager-server/src/main/helm/templates/_helpers.tpl
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
@@ -22,7 +22,6 @@
 # unter der Lizenz sind dem Lizenztext zu entnehmen.
 #
 
-
 {{/* error check 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec) */}}
 {{/* Namespace */}}
 {{- define "app.namespace" -}}
@@ -79,14 +78,6 @@ app.kubernetes.io/namespace: {{ include "app.namespace" . }}
 {{- required "Environment muss angegeben sein" (.Values.ozgcloud).environment -}}
 {{- end -}}
 
-{{- define "app.grpcClientVorgangManagerAddress" -}}
-{{- if (.Values.env).grpcClientVorgangManagerAddress -}}
-{{ printf "%s" (.Values.env).grpcClientVorgangManagerAddress }}
-{{- else -}}
-{{ printf "dns:///%s.%s:9090" ( coalesce .Values.vorgangManagerName "vorgang-manager" ) (include "app.namespace" . ) }}
-{{- end -}}
-{{- end -}}
-
 {{- define "app.getCustomList" -}}
 {{- with (.Values.env).customList -}}
 {{- if kindIs "map" . -}}
diff --git a/aggregation-manager-server/src/main/helm/templates/configmap_bindings_type.yaml b/aggregation-manager-server/src/main/helm/templates/configmap_bindings_type.yaml
index 6acf2ceb743eea597fa9a804d98fee220882bcbe..63711189ff34aed1493c5506e1b5023b279becbe 100644
--- a/aggregation-manager-server/src/main/helm/templates/configmap_bindings_type.yaml
+++ b/aggregation-manager-server/src/main/helm/templates/configmap_bindings_type.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
+# 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
@@ -22,11 +22,13 @@
 # unter der Lizenz sind dem Lizenztext zu entnehmen.
 #
 
+{{- if ((.Values.database).tls).enabled }}
 apiVersion: v1
 kind: ConfigMap
 metadata:
-  name: bindings-type
+  name: aggregation-manager-server-bindings-type
   namespace: {{ include "app.namespace" . }}
 data:
   type: |
-    ca-certificates
\ No newline at end of file
+        ca-certificates
+{{- end }}
\ No newline at end of file
diff --git a/aggregation-manager-server/src/main/helm/templates/deployment.yaml b/aggregation-manager-server/src/main/helm/templates/deployment.yaml
index f8e7c6b924ccaa659d6cd448d5ca3d886f0c2a25..1fac9cbcc4c4d51d0e1ef96085c1ba91158dcc24 100644
--- a/aggregation-manager-server/src/main/helm/templates/deployment.yaml
+++ b/aggregation-manager-server/src/main/helm/templates/deployment.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
+# 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
@@ -54,6 +54,9 @@ spec:
           labelSelector:
             matchLabels:
               app.kubernetes.io/name: {{ .Release.Name }}
+      {{- if (.Values.serviceAccount).create }}
+      serviceAccountName: {{ .Values.serviceAccount.name }}
+      {{- end }}
       containers:
       - name: aggregation-manager-server
         image: "{{ .Values.image.repo }}/{{ .Values.image.name }}:{{ coalesce (.Values.image).tag "latest" }}"
@@ -63,6 +66,11 @@ spec:
           value: "/bindings"
         - name: spring_profiles_active
           value: {{ include "app.envSpringProfiles" . }}
+        - name: ozgcloud_administration_address
+          value: {{ include "app.getOzgcloudAdministrationAddress" . }}
+        {{- with include "app.getCustomList" . }}
+{{ . | indent 8 }}
+        {{- end }}
         ports:
           - containerPort: 8081
             name: metrics
@@ -100,16 +108,30 @@ spec:
         terminationMessagePolicy: File
         tty: true
         volumeMounts:
-          - name: bindings
-            mountPath: "/bindings/ca-certificates/type"
-            subPath: type
-            readOnly: true
-      volumes:
+        {{- if ((.Values.database).tls).enabled }}
         - name: bindings
-          configMap:
-            name: bindings-type
+          mountPath: "/bindings/ca-certificates/type"
+          subPath: type
+          readOnly: true
+        - name: mongodb-root-ca
+          mountPath: "/bindings/ca-certificates/mongodb-root-ca.pem"
+          subPath: ca.crt
+          readOnly: true
+        {{- end }}
+      volumes:
+        {{- if ((.Values.database).tls).enabled }}
+      - name: bindings
+        configMap:
+          name: aggregation-manager-server-bindings-type
+      - name: mongodb-root-ca
+        secret:
+          secretName: {{ ((.Values.database).tls).secretName }}
+          optional: true
+      {{- end }}
       dnsConfig: { }
       dnsPolicy: ClusterFirst
+      imagePullSecrets:
+      - name: {{ required "imagePullSecret must be set" .Values.imagePullSecret }}
       restartPolicy: Always
       schedulerName: default-scheduler
       securityContext: { }
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 66f7b05c6f2207aa9d5a842bfa26073c92dee760..74138a34bca3f686944dd08abe10287689f7625e 100644
--- a/aggregation-manager-server/src/main/helm/templates/network_policy.yaml
+++ b/aggregation-manager-server/src/main/helm/templates/network_policy.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/aggregation-manager-server/src/main/helm/templates/service.yaml b/aggregation-manager-server/src/main/helm/templates/service.yaml
index 55d72c490b4df05a3b136fbff6ad9ddf5a07e2fb..4af595e657094aac4bfd1b1e7d7386812f8577ae 100644
--- a/aggregation-manager-server/src/main/helm/templates/service.yaml
+++ b/aggregation-manager-server/src/main/helm/templates/service.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/aggregation-manager-server/src/main/helm/templates/service_account.yaml b/aggregation-manager-server/src/main/helm/templates/service_account.yaml
index 02ff46e312df7ecaba152d3626e4e3affd778f34..664e8acec9fabb26df2325ab4bc336e628151144 100644
--- a/aggregation-manager-server/src/main/helm/templates/service_account.yaml
+++ b/aggregation-manager-server/src/main/helm/templates/service_account.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/aggregation-manager-server/src/main/helm/templates/service_monitor.yaml b/aggregation-manager-server/src/main/helm/templates/service_monitor.yaml
index 102cf41061848962736cdf1136c66e69bcf4688d..35f52b7999d37996d6d41d6023f1f7ca4ea68900 100644
--- a/aggregation-manager-server/src/main/helm/templates/service_monitor.yaml
+++ b/aggregation-manager-server/src/main/helm/templates/service_monitor.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/aggregation-manager-server/src/main/helm/values.yaml b/aggregation-manager-server/src/main/helm/values.yaml
index f4eb0eb6cdc2aabda8ac44f53cab0a0eace353a9..f00bd23b53fa51a45533aba042fcae8ed877c9be 100644
--- a/aggregation-manager-server/src/main/helm/values.yaml
+++ b/aggregation-manager-server/src/main/helm/values.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
@@ -32,8 +32,8 @@ ozgcloud:
 
 database:
   useExternal: false
-  databaseName: aggregation-manager-database
-  secretName: ozg-mongodb-admin-aggregation-manager-user
+  databaseName: aggregation-manager-server-database
+  secretName: ozg-mongodb-admin-aggregation-manager-server-user
   tls:
     enabled: false
     secretName: ozg-mongodb-tls-cert
@@ -42,6 +42,6 @@ serviceAccount:
   create: true
   name: aggregation-manager-server-service-account
 
-imagePullSecret: ""
-
 replicaCount: 1
+
+administrationName: administration
diff --git a/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/AggregationManagerApplication.java b/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/AggregationManagerApplication.java
index 882c75f04d7b389b58fc16aeb145c47a470ec14d..09a4dab58b64714b9bdd109b6df084c9a4b0ab2b 100644
--- a/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/AggregationManagerApplication.java
+++ b/aggregation-manager-server/src/main/java/de/ozgcloud/aggregation/AggregationManagerApplication.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * 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
diff --git a/aggregation-manager-server/src/main/resources/application-local.yml b/aggregation-manager-server/src/main/resources/application-local.yml
index fe32e63285fa1a8832749caf1afffdb3e4be0e60..6b1a35c08da53eb3a7f0a9d58054f1937fc6abb3 100644
--- a/aggregation-manager-server/src/main/resources/application-local.yml
+++ b/aggregation-manager-server/src/main/resources/application-local.yml
@@ -9,5 +9,5 @@ spring:
     mongodb:
       host: localhost
       port: 27017
-      database: aggregation-manager-land
+      database: aggregation-manager-server
 
diff --git a/aggregation-manager-server/src/test/helm-linter-values.yaml b/aggregation-manager-server/src/test/helm-linter-values.yaml
index 5024cc924057218b72df02830cac6d67890d6c54..be6b1860d5c6417dac89f2d16ba8ccd15d0a3257 100644
--- a/aggregation-manager-server/src/test/helm-linter-values.yaml
+++ b/aggregation-manager-server/src/test/helm-linter-values.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
@@ -27,3 +27,5 @@ ozgcloud:
 
 networkPolicy:
   dnsServerNamespace: dummy-dns
+
+imagePullSecret: image-pull-secret
diff --git a/aggregation-manager-server/src/test/helm/configmap_bindings_type_test.yaml b/aggregation-manager-server/src/test/helm/configmap_bindings_type_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..78c9c13265a35a814898e2d2389c5072680fc34b
--- /dev/null
+++ b/aggregation-manager-server/src/test/helm/configmap_bindings_type_test.yaml
@@ -0,0 +1,54 @@
+#
+# 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: configmap_bindings_type
+release:
+  name: aggregation-manager-server
+  namespace: sh-helm-test
+templates:
+  - templates/configmap_bindings_type.yaml
+tests:
+  - it: configMap should not exists
+    asserts:
+      - hasDocuments:
+          count: 0
+  - it: should have configmap if database tls is enabled
+    set:
+      database:
+        tls:
+          enabled: true
+    asserts:
+      - isKind:
+          of: ConfigMap
+      - isAPIVersion:
+          of: v1
+      - equal:
+          path: metadata.name
+          value: aggregation-manager-server-bindings-type
+      - equal:
+          path: metadata.namespace
+          value: sh-helm-test
+      - equal:
+          path: data.type
+          value: "ca-certificates"
diff --git a/aggregation-manager-server/src/test/helm/deployment_63_char_test.yaml b/aggregation-manager-server/src/test/helm/deployment_63_char_test.yaml
index 39f12c1363e440bb7033555a2bd89b4b0fe08067..f6a55a65431e0c6b6aff0fe5a20d5d508e1664c9 100644
--- a/aggregation-manager-server/src/test/helm/deployment_63_char_test.yaml
+++ b/aggregation-manager-server/src/test/helm/deployment_63_char_test.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/aggregation-manager-server/src/test/helm/deployment_env_administration_test.yaml b/aggregation-manager-server/src/test/helm/deployment_env_administration_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..347382800f52d97ea5c10ba4833b8f717c4a2afd
--- /dev/null
+++ b/aggregation-manager-server/src/test/helm/deployment_env_administration_test.yaml
@@ -0,0 +1,60 @@
+#
+# 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 deployment container environments
+templates:
+  - templates/deployment.yaml
+release:
+  namespace: sh-helm-test
+set:
+  imagePullSecret: image-pull-secret
+tests:
+  - it: should have ozgcloud_administration_address
+    set:
+      ozgcloud:
+        environment: dev
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_administration_address
+            value: http://administration.sh-helm-test:8080
+
+  - it: should set ozgcloud_administration_address
+    set:
+      administrationAddress: http://test-administration:8080
+      ozgcloud:
+        environment: dev
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_administration_address
+            value: http://test-administration:8080
+
+  - it: should fail template when env not set
+    set:
+    asserts:
+      - failedTemplate:
+          errormessage: Environment muss angegeben sein
diff --git a/aggregation-manager-server/src/test/helm/deployment_env_customList_test.yaml b/aggregation-manager-server/src/test/helm/deployment_env_customList_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..c12bb7be1d3e56b3f5800b9a17e46b43d13167db
--- /dev/null
+++ b/aggregation-manager-server/src/test/helm/deployment_env_customList_test.yaml
@@ -0,0 +1,72 @@
+#
+# 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 environments customList
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud.environment: test
+  imagePullSecret: image-pull-secret
+tests:
+  - it: check customList as list
+    set:
+      env.customList:
+        - name: my_test_environment_name
+          value: "A test value"
+        - name: test_environment
+          value: "B test value"
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: my_test_environment_name
+            value: "A test value"
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: test_environment
+            value: "B test value"
+  - it: check customList as dict
+    set:
+      env.customList:
+        my_test_environment_name: "A test value"
+        test_environment: "B test value"
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: my_test_environment_name
+            value: "A test value"
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: test_environment
+            value: "B test value"
+  - it: check customList test value is not set by default
+    asserts:
+      - notContains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: my_test_environment_name
+            value: "A test value"
diff --git a/aggregation-manager-server/src/test/helm/deployment_image_pull_secret_test.yaml b/aggregation-manager-server/src/test/helm/deployment_image_pull_secret_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..f4e580823991d87cb8b6e3b0a0c81b2fae1c1c5a
--- /dev/null
+++ b/aggregation-manager-server/src/test/helm/deployment_image_pull_secret_test.yaml
@@ -0,0 +1,44 @@
+#
+# 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 deployment imagepullsecret
+release:
+  name: eingang-adapter
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud.environment: test
+tests:
+  - it: should set the imagePull secret
+    set:
+      imagePullSecret: image-pull-secret
+    asserts:
+      - equal:
+          path: spec.template.spec.imagePullSecrets[0].name
+          value: image-pull-secret
+  - it: should fail tempalte when not set
+    asserts:
+      - failedTemplate:
+          errorMessage: imagePullSecret must be set
diff --git a/aggregation-manager-server/src/test/helm/deployment_resources_test.yaml b/aggregation-manager-server/src/test/helm/deployment_resources_test.yaml
index 90f47f157290668343c7d66f75353fb52c8d6ada..4706c9929a7029e274c81f958ca4b60b2cd3d934 100644
--- a/aggregation-manager-server/src/test/helm/deployment_resources_test.yaml
+++ b/aggregation-manager-server/src/test/helm/deployment_resources_test.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/aggregation-manager-server/src/test/helm/deployment_service_account_test.yaml b/aggregation-manager-server/src/test/helm/deployment_service_account_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..eb1f736d744b9baac4940d39dee42b7427f0e8f2
--- /dev/null
+++ b/aggregation-manager-server/src/test/helm/deployment_service_account_test.yaml
@@ -0,0 +1,55 @@
+#
+# 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: deployment service account
+release:
+  name: aggregation-manager-server
+  namespace: by-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+  imagePullSecret: image-pull-secret
+tests:
+  - it: should use aggregation-manager-server service account
+    asserts:
+      - equal:
+          path: spec.template.spec.serviceAccountName
+          value: aggregation-manager-server-service-account
+  - it: should set service account name
+    set:
+      serviceAccount:
+        name: helm-service-account
+    asserts:
+      - equal:
+          path: spec.template.spec.serviceAccountName
+          value: helm-service-account
+  - it: should use default service account
+    set:
+      serviceAccount:
+        create: false
+    asserts:
+      - isNull:
+          path: spec.template.spec.serviceAccountName
diff --git a/aggregation-manager-server/src/test/helm/deployment_spring_profile_test.yaml b/aggregation-manager-server/src/test/helm/deployment_spring_profile_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..c7eea6926b708158ca05fefe3f6cb3e8c567c157
--- /dev/null
+++ b/aggregation-manager-server/src/test/helm/deployment_spring_profile_test.yaml
@@ -0,0 +1,50 @@
+#
+# 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: deployment springProfile tests
+release:
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+  imagePullSecret: image-pull-secret
+tests:
+  - it: should override the spring profiles
+    set:
+      env.overrideSpringProfiles: oc,dev,ea
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: spring_profiles_active
+            value: oc,dev,ea
+  - it: should generate the spring profiles
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: spring_profiles_active
+            value: oc, dev
diff --git a/aggregation-manager-server/src/test/helm/deployment_test.yaml b/aggregation-manager-server/src/test/helm/deployment_test.yaml
index 6b70a109f3de1afc27b84e7fe19a7a0b81784a16..37a00d0a32c5b8ab4620068ae0d6248b275b040a 100644
--- a/aggregation-manager-server/src/test/helm/deployment_test.yaml
+++ b/aggregation-manager-server/src/test/helm/deployment_test.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
+# 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
@@ -233,28 +233,6 @@ tests:
       - equal:
           path: spec.template.spec.containers[0].securityContext.runAsNonRoot
           value: false
-  - it: validate container volume mounts
-    asserts:
-      - equal:
-          path: spec.template.spec.containers[0].volumeMounts[0].name
-          value: bindings
-      - equal:
-          path: spec.template.spec.containers[0].volumeMounts[0].mountPath
-          value: "/bindings/ca-certificates/type"
-      - equal:
-          path: spec.template.spec.containers[0].volumeMounts[0].subPath
-          value: type
-      - equal:
-          path: spec.template.spec.containers[0].volumeMounts[0].readOnly
-          value: true
-  - it: validate volumes
-    asserts:
-      - equal:
-          path: spec.template.spec.volumes[0].name
-          value: bindings
-      - equal:
-          path: spec.template.spec.volumes[0].configMap.name
-          value: bindings-type
   - it: validate container root config
     asserts:
       - equal:
diff --git a/aggregation-manager-server/src/test/helm/deployment_volume_test.yaml b/aggregation-manager-server/src/test/helm/deployment_volume_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..7f2efa110938e630db731358bf306172a4081a44
--- /dev/null
+++ b/aggregation-manager-server/src/test/helm/deployment_volume_test.yaml
@@ -0,0 +1,93 @@
+#
+# 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: deployment volumes tests
+release:
+  name: aggregation-manager-server
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: "default"
+  imagePullSecret: image-pull-secret
+tests:
+  - it: should not have volumeMounts
+    asserts:
+      - isEmpty:
+          path: spec.template.spec.containers[0].volumeMounts
+  - it: should not have volumes
+    asserts:
+      - isEmpty:
+          path: spec.template.spec.volumes
+  - it: should have volumeMounts if database tls is enabled
+    set:
+      database:
+        tls:
+          enabled: true
+    asserts:
+      - equal:
+          path: spec.template.spec.containers[0].volumeMounts[0].name
+          value: "bindings"
+      - equal:
+          path: spec.template.spec.containers[0].volumeMounts[0].mountPath
+          value: "/bindings/ca-certificates/type"
+      - equal:
+          path: spec.template.spec.containers[0].volumeMounts[0].subPath
+          value: "type"
+      - equal:
+          path: spec.template.spec.containers[0].volumeMounts[0].readOnly
+          value: true
+      - equal:
+          path: spec.template.spec.containers[0].volumeMounts[1].name
+          value: "mongodb-root-ca"
+      - equal:
+          path: spec.template.spec.containers[0].volumeMounts[1].mountPath
+          value: "/bindings/ca-certificates/mongodb-root-ca.pem"
+      - equal:
+          path: spec.template.spec.containers[0].volumeMounts[1].subPath
+          value: "ca.crt"
+      - equal:
+          path: spec.template.spec.containers[0].volumeMounts[1].readOnly
+          value: true
+  - it: should have volumes on it's spec if database tls is enabled
+    set:
+      database:
+        tls:
+          enabled: true
+    asserts:
+      - equal:
+          path: spec.template.spec.volumes[0].name
+          value: "bindings"
+      - equal:
+          path: spec.template.spec.volumes[0].configMap.name
+          value: "aggregation-manager-server-bindings-type"
+      - equal:
+          path: spec.template.spec.volumes[1].name
+          value: "mongodb-root-ca"
+      - equal:
+          path: spec.template.spec.volumes[1].secret.secretName
+          value: "ozg-mongodb-tls-cert"
+      - equal:
+          path: spec.template.spec.volumes[1].secret.optional
+          value: true
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 ac8acb00525cf98f3c5227613d76bd12b27b9e86..54308f5b7b065dc7cd9d7f2748ca2ab028d50f9a 100644
--- a/aggregation-manager-server/src/test/helm/network_policy_test.yaml
+++ b/aggregation-manager-server/src/test/helm/network_policy_test.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/aggregation-manager-server/src/test/helm/service_account_test.yaml b/aggregation-manager-server/src/test/helm/service_account_test.yaml
index 865a883479afd8cfca9aac844bfaa3286d90bb24..be94f3e7d171612a51c6ecea268180149e557543 100644
--- a/aggregation-manager-server/src/test/helm/service_account_test.yaml
+++ b/aggregation-manager-server/src/test/helm/service_account_test.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/aggregation-manager-server/src/test/helm/service_monitor_test.yaml b/aggregation-manager-server/src/test/helm/service_monitor_test.yaml
index cc66c4aff2dc1f65875a98f5ee06fe389f5c8975..a65fb777ea572771b0a740b6c7dfa36160000a50 100644
--- a/aggregation-manager-server/src/test/helm/service_monitor_test.yaml
+++ b/aggregation-manager-server/src/test/helm/service_monitor_test.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/aggregation-manager-server/src/test/helm/service_test.yaml b/aggregation-manager-server/src/test/helm/service_test.yaml
index 95cc6af8a58d62f044e34c0dde0ce41eaf1b0c1e..4f4733d627851e2458863ea27e75eb91cddf4a91 100644
--- a/aggregation-manager-server/src/test/helm/service_test.yaml
+++ b/aggregation-manager-server/src/test/helm/service_test.yaml
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/metabase/run_helm_test.sh b/metabase/run_helm_test.sh
index aafe0e7dd324a8e4764fad72362bc2d2039ae197..ac380340699509b5eea686fe129c97b4995198c4 100755
--- a/metabase/run_helm_test.sh
+++ b/metabase/run_helm_test.sh
@@ -1,4 +1,28 @@
 #!/bin/sh
+#
+# Copyright (C) 2024 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.
+#
+
 
 set -e
 
diff --git a/metabase/src/main/helm/templates/_helpers.tpl b/metabase/src/main/helm/templates/_helpers.tpl
index f7ff4b68574e99a987f2551cd32dffe60b150d59..12f9deca73585fa40db31a9f2f024f6a6b8cf4ac 100644
--- a/metabase/src/main/helm/templates/_helpers.tpl
+++ b/metabase/src/main/helm/templates/_helpers.tpl
@@ -1,3 +1,27 @@
+#
+# Copyright (C) 2024 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.
+#
+
 
 {{/* error check 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec) */}}
 {{/* Namespace */}}
diff --git a/metabase/src/main/helm/templates/metabase_pvc.yaml b/metabase/src/main/helm/templates/metabase_pvc.yaml
index db07c01c2d972a1a3ea3316f0e1f79797631cdf6..a32883623d7cce4ab81979213ceb1d40ad187864 100644
--- a/metabase/src/main/helm/templates/metabase_pvc.yaml
+++ b/metabase/src/main/helm/templates/metabase_pvc.yaml
@@ -1,3 +1,27 @@
+#
+# Copyright (C) 2024 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.
+#
+
 apiVersion: v1
 kind: PersistentVolumeClaim
 metadata:
diff --git a/metabase/src/main/helm/templates/network_policy.yaml b/metabase/src/main/helm/templates/network_policy.yaml
index d14c0d10efcf0c709cc5d99fb66d0f09c7312b2b..87a29ecd28be88242f65ca5e2ebfe091d97c5251 100644
--- a/metabase/src/main/helm/templates/network_policy.yaml
+++ b/metabase/src/main/helm/templates/network_policy.yaml
@@ -1,3 +1,27 @@
+#
+# Copyright (C) 2024 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.
+#
+
 {{- if not (.Values.networkPolicy).disabled }}
 apiVersion: networking.k8s.io/v1
 kind: NetworkPolicy
diff --git a/metabase/src/main/helm/templates/service.yaml b/metabase/src/main/helm/templates/service.yaml
index a3668f9d5ba070e1f79d8f767fb75fabe33b1b49..4824e596d436539c19f9be9e60d7b32c8718b732 100644
--- a/metabase/src/main/helm/templates/service.yaml
+++ b/metabase/src/main/helm/templates/service.yaml
@@ -21,6 +21,7 @@
 # Die sprachspezifischen Genehmigungen und Beschränkungen
 # unter der Lizenz sind dem Lizenztext zu entnehmen.
 #
+
 apiVersion: v1
 kind: Service
 metadata:
diff --git a/metabase/src/test/helm-linter-values.yaml b/metabase/src/test/helm-linter-values.yaml
index 7accba8aca81ac697e89ae763523a8fc69b7b79f..2b963ba672abc992eea924d3b80c5478eee91bec 100644
--- a/metabase/src/test/helm-linter-values.yaml
+++ b/metabase/src/test/helm-linter-values.yaml
@@ -1,7 +1,8 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch das
-# Ministerium für Energiewende, Klimaschutz, Umwelt und Natur
-# Zentrales IT-Management
+# Copyright (C) 2024 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 -
@@ -19,7 +20,7 @@
 # ausdrücklich oder stillschweigend - verbreitet.
 # Die sprachspezifischen Genehmigungen und Beschränkungen
 # unter der Lizenz sind dem Lizenztext zu entnehmen.
-
+#
 
 ozgcloud:
   bezeichner: helm
diff --git a/metabase/src/test/helm/deployment_image_pull_secret_test.yaml b/metabase/src/test/helm/deployment_image_pull_secret_test.yaml
index 7db271604026bfa921751ef481f047791b624b2f..bc6140b90e93f114abe37581a2fa50b176fcb6ac 100644
--- a/metabase/src/test/helm/deployment_image_pull_secret_test.yaml
+++ b/metabase/src/test/helm/deployment_image_pull_secret_test.yaml
@@ -1,7 +1,8 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch das
-# Ministerium für Energiewende, Klimaschutz, Umwelt und Natur
-# Zentrales IT-Management
+# Copyright (C) 2024 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 -
@@ -19,6 +20,7 @@
 # ausdrücklich oder stillschweigend - verbreitet.
 # Die sprachspezifischen Genehmigungen und Beschränkungen
 # unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
 
 suite: deployment image pull secret
 
diff --git a/metabase/src/test/helm/deployment_resources_test.yaml b/metabase/src/test/helm/deployment_resources_test.yaml
index ecfc4eda7e1fa9bc9e45f5f24aeed6bb5a688f75..7c6dcc51cedec7ba35dbeef8b38dbcb3ff41657e 100644
--- a/metabase/src/test/helm/deployment_resources_test.yaml
+++ b/metabase/src/test/helm/deployment_resources_test.yaml
@@ -1,7 +1,8 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch das
-# Ministerium für Energiewende, Klimaschutz, Umwelt und Natur
-# Zentrales IT-Management
+# Copyright (C) 2024 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 -
@@ -19,6 +20,7 @@
 # ausdrücklich oder stillschweigend - verbreitet.
 # Die sprachspezifischen Genehmigungen und Beschränkungen
 # unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
 
 suite: deployment resources
 
diff --git a/metabase/src/test/helm/metabase_pvc_test.yaml b/metabase/src/test/helm/metabase_pvc_test.yaml
index 9b148478b90bda3a567c607ae44564ad05c9f07a..7017f0555660ee95af1259b100ae74e250fdbe7c 100644
--- a/metabase/src/test/helm/metabase_pvc_test.yaml
+++ b/metabase/src/test/helm/metabase_pvc_test.yaml
@@ -1,3 +1,27 @@
+#
+# Copyright (C) 2024 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 pvc
 release:
   name: metabase
diff --git a/metabase/src/test/helm/service_test.yaml b/metabase/src/test/helm/service_test.yaml
index 3cc31ee3350f0c7c205846a6b7cb5e2b4d8646d1..cf6839785d2d0f459cb73806fe46caed12fd9ff0 100644
--- a/metabase/src/test/helm/service_test.yaml
+++ b/metabase/src/test/helm/service_test.yaml
@@ -1,7 +1,8 @@
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch das
-# Ministerium für Energiewende, Klimaschutz, Umwelt und Natur
-# Zentrales IT-Management
+# Copyright (C) 2024 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 -
@@ -19,6 +20,7 @@
 # ausdrücklich oder stillschweigend - verbreitet.
 # Die sprachspezifischen Genehmigungen und Beschränkungen
 # unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
 
 suite: service
 
diff --git a/run_helm_test_aggregation_job.sh b/run_helm_test_aggregation_job.sh
index ef1448f8a76fc7b7b6e5cb6d885c68e434f38454..122f5b90875cbbdec5b4e31edc17b497cde7f132 100755
--- a/run_helm_test_aggregation_job.sh
+++ b/run_helm_test_aggregation_job.sh
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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
diff --git a/run_helm_test_aggregation_server.sh b/run_helm_test_aggregation_server.sh
index e0130ad25b38ab308db870ce6c23631141abc2e8..b150de21ce9dd25ba55bff7441480fffdaf8ec6d 100755
--- a/run_helm_test_aggregation_server.sh
+++ b/run_helm_test_aggregation_server.sh
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# 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