diff --git a/pluto-server/pom.xml b/pluto-server/pom.xml
index 472a9ccd57fa97f6155baf01fcffa0ceb24ec2e0..d9f7b12ec1baaf19ab3e0742ee73b480a16a5e8a 100644
--- a/pluto-server/pom.xml
+++ b/pluto-server/pom.xml
@@ -29,6 +29,7 @@
 
 		<mongodb.testcontainer.version>1.15.3</mongodb.testcontainer.version>
 		<solr.testcontainer.version>1.16.2</solr.testcontainer.version>
+		<elasticsearch.testcontainer.version>1.17.3</elasticsearch.testcontainer.version>
 	</properties>
 
 	<dependencies>
@@ -89,6 +90,11 @@
 			<groupId>org.springframework.security</groupId>
 			<artifactId>spring-security-core</artifactId>
 		</dependency>
+		
+		<dependency>
+    		<groupId>org.springframework.data</groupId>
+    		<artifactId>spring-data-elasticsearch</artifactId>
+		</dependency>
 
 		<!-- aspectJ -->
 		<dependency>
@@ -219,6 +225,12 @@
 			<version>${solr.testcontainer.version}</version>
 			<scope>test</scope>
 		</dependency>
+		<dependency>
+		    <groupId>org.testcontainers</groupId>
+		    <artifactId>elasticsearch</artifactId>
+		    <version>${elasticsearch.testcontainer.version}</version>
+		    <scope>test</scope>
+		</dependency>
 
 		<!-- mongock -->
 		<dependency>
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchEventListener.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchEventListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..ff485e5bae34338e2bf5361751aa86cc208c2d11
--- /dev/null
+++ b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchEventListener.java
@@ -0,0 +1,56 @@
+package de.itvsh.ozg.pluto.common.elastic;
+
+import java.text.MessageFormat;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Component;
+
+import co.elastic.clients.elasticsearch.ElasticsearchClient;
+import de.itvsh.ozg.pluto.command.Command;
+import de.itvsh.ozg.pluto.command.CommandService;
+import de.itvsh.ozg.pluto.command.VorgangCreatedEvent;
+import de.itvsh.ozg.pluto.vorgang.StatusChangedEvent;
+import de.itvsh.ozg.pluto.vorgang.VorgangAssignedEvent;
+import de.itvsh.ozg.pluto.vorgang.VorgangService;
+
+@Component
+@ConditionalOnBean(ElasticsearchClient.class)
+public class ElasticsearchEventListener {
+	@Autowired
+	private ElasticsearchService elasticsearchService;
+
+	@Autowired
+	private CommandService commandService;
+
+	@Autowired
+	private VorgangService vorgangService;
+
+	@EventListener
+	public void onNewVorgang(VorgangCreatedEvent vorgangCreatedEvent) {
+		elasticsearchService.addVorgang(vorgangService.getById(vorgangCreatedEvent.getSource()));
+
+	}
+
+	@EventListener
+	public void onVorgangAssigned(VorgangAssignedEvent vorgangAssignedEvent) {
+		updateVorgang(vorgangAssignedEvent.getCommand());
+	}
+
+	@EventListener
+	public void onVorgangStatusChanged(StatusChangedEvent event) {
+		updateVorgangById(event.getSource());
+	}
+
+	private void updateVorgangById(String commandId) {
+		commandService.findCommand(commandId).ifPresentOrElse(this::updateVorgang, () -> {
+			throw new IllegalStateException(MessageFormat.format("Kein Command mit der ID {0} gefunden", commandId));
+		});
+	}
+
+	void updateVorgang(Command command) {
+		elasticsearchService.updateVorgang(vorgangService.getById(command.getVorgangId()));
+	}
+
+}
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchService.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchService.java
new file mode 100644
index 0000000000000000000000000000000000000000..9c77e47fa2fda768ab775cc5e0293e415d19286b
--- /dev/null
+++ b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchService.java
@@ -0,0 +1,21 @@
+package de.itvsh.ozg.pluto.common.elastic;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import de.itvsh.ozg.pluto.vorgang.Vorgang;
+
+@Service
+public class ElasticsearchService {
+	@Autowired
+	private ElasticsearchVorgangRepostitory vorgangRepostitory;
+
+	public void addVorgang(Vorgang vorgang) {
+		vorgangRepostitory.save(vorgang);
+	}
+
+	public void updateVorgang(Vorgang vorgang) {
+		vorgangRepostitory.save(vorgang);
+	}
+
+}
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchVorgangRepostitory.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchVorgangRepostitory.java
new file mode 100644
index 0000000000000000000000000000000000000000..4b1bf2d96004196187280f4dc32a866c1059dae2
--- /dev/null
+++ b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchVorgangRepostitory.java
@@ -0,0 +1,11 @@
+package de.itvsh.ozg.pluto.common.elastic;
+
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
+
+import de.itvsh.ozg.pluto.vorgang.Vorgang;
+
+interface ElasticsearchVorgangRepostitory extends ElasticsearchRepository<Vorgang, String> {
+	Page<Vorgang> findByAktenzeichen(String aktenzeichen, Pageable pageable);
+}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchEventListenerTest.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchEventListenerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..8dd93df468bae6c75839b5c8d00f5d4a5e18fd87
--- /dev/null
+++ b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchEventListenerTest.java
@@ -0,0 +1,103 @@
+package de.itvsh.ozg.pluto.common.elastic;
+
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.Optional;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import de.itvsh.ozg.pluto.command.Command;
+import de.itvsh.ozg.pluto.command.CommandService;
+import de.itvsh.ozg.pluto.command.CommandTestFactory;
+import de.itvsh.ozg.pluto.command.VorgangCreatedEvent;
+import de.itvsh.ozg.pluto.vorgang.StatusChangedEvent;
+import de.itvsh.ozg.pluto.vorgang.Vorgang;
+import de.itvsh.ozg.pluto.vorgang.VorgangAssignedEvent;
+import de.itvsh.ozg.pluto.vorgang.VorgangService;
+import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+
+class ElasticsearchEventListenerTest {
+
+	@InjectMocks
+	private ElasticsearchEventListener eventListener;
+
+	@Mock
+	private ElasticsearchService elasticsearchService;
+
+	@Mock
+	private CommandService commandService;
+
+	@Mock
+	private VorgangService vorgangService;
+
+	private Vorgang vorgang;
+
+	@BeforeEach
+	void init() {
+		vorgang = VorgangTestFactory.create();
+	}
+
+	@Nested
+	class TestOnNewVorgang {
+		@Mock
+		private VorgangCreatedEvent vorgangCreatedEvent;
+
+		@Test
+		void onNewVorgangTest() {
+			when(vorgangCreatedEvent.getSource()).thenReturn(VorgangTestFactory.ID);
+			when(vorgangService.getById(anyString())).thenReturn(vorgang);
+
+			eventListener.onNewVorgang(vorgangCreatedEvent);
+
+			verify(elasticsearchService).addVorgang(any());
+		}
+	}
+
+	@Nested
+	class TestOnVorgangAssigned {
+		@Mock
+		private VorgangAssignedEvent vorgangAssignedEvent;
+
+		@BeforeEach
+		void init() {
+			Command command = CommandTestFactory.create();
+			when(vorgangAssignedEvent.getCommand()).thenReturn(command);
+
+			when(vorgangService.getById(anyString())).thenReturn(vorgang);
+		}
+
+		@Test
+		void shouldUpdateVorgang() {
+			eventListener.onVorgangAssigned(vorgangAssignedEvent);
+
+			verify(elasticsearchService).updateVorgang(any());
+		}
+	}
+
+	@Nested
+	class TestOnUpdatedVorgang {
+		@Mock
+		private StatusChangedEvent vorgangUpdatedEvent;
+
+		@BeforeEach
+		void init() {
+			when(vorgangUpdatedEvent.getSource()).thenReturn("commandId");
+			Command command = CommandTestFactory.create();
+			when(commandService.findCommand(anyString())).thenReturn(Optional.of(command));
+
+			when(vorgangService.getById(anyString())).thenReturn(vorgang);
+		}
+
+		@Test
+		void shouldUpdateVorgangInSolr() {
+			eventListener.onVorgangStatusChanged(vorgangUpdatedEvent);
+
+			verify(elasticsearchService).updateVorgang(any());
+		}
+	}
+}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchIndexerEnabledInitializer.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchIndexerEnabledInitializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..a8024d2e5cd6f395b19758c019423d7f7614aa2a
--- /dev/null
+++ b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchIndexerEnabledInitializer.java
@@ -0,0 +1,14 @@
+package de.itvsh.ozg.pluto.common.elastic;
+
+import org.springframework.boot.test.util.TestPropertyValues;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.testcontainers.elasticsearch.ElasticsearchContainer;
+
+public class ElasticsearchIndexerEnabledInitializer extends ElasticsearchInitializer {
+	@Override
+	protected void setProperties(ElasticsearchContainer container, ConfigurableApplicationContext applicationContext) {
+		super.setProperties(container, applicationContext);
+
+		TestPropertyValues.of("kop.elasticsearch.initEnabled=true");
+	}
+}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchInitializer.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchInitializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..b8ed48af0743c0bbe9fdef40b657842350dd13bb
--- /dev/null
+++ b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchInitializer.java
@@ -0,0 +1,31 @@
+package de.itvsh.ozg.pluto.common.elastic;
+
+import org.springframework.boot.test.util.TestPropertyValues;
+import org.springframework.context.ApplicationContextInitializer;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.testcontainers.elasticsearch.ElasticsearchContainer;
+
+import lombok.AccessLevel;
+import lombok.Getter;
+
+public class ElasticsearchInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
+	private static final String ELASTICSEARCH_VERSIION = "docker.elastic.co/elasticsearch/elasticsearch:8.3.2";
+	@Getter(value = AccessLevel.PROTECTED)
+	private ElasticsearchContainer elasticsearchContainer;
+
+	@Override
+	public void initialize(ConfigurableApplicationContext applicationContext) {
+		elasticsearchContainer = new ElasticsearchContainer(ELASTICSEARCH_VERSIION);
+		elasticsearchContainer.start();
+
+		setProperties(elasticsearchContainer, applicationContext);
+	}
+
+	protected void setProperties(ElasticsearchContainer container, ConfigurableApplicationContext applicationContext) {
+		TestPropertyValues.of(
+				"kop.elasticsearch.host=" + container.getHttpHostAddress(),
+				"kop.elasticsearch.initEnabled=false",
+				"kop.elasticsearch.collectionName=test");
+	}
+
+}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchServiceTest.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..20973280e421d09ef644bbd7b2796fa421a8de88
--- /dev/null
+++ b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchServiceTest.java
@@ -0,0 +1,43 @@
+package de.itvsh.ozg.pluto.common.elastic;
+
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+
+class ElasticsearchServiceTest {
+
+	@InjectMocks
+	private ElasticsearchService elasticsearchService;
+
+	@Mock
+	private ElasticsearchVorgangRepostitory repostitory;
+
+	@Nested
+	class TestAddVorgang {
+
+		@Test
+		void shouldCallRepository() {
+			elasticsearchService.addVorgang(VorgangTestFactory.create());
+
+			verify(repostitory).save(any());
+		}
+	}
+
+	@Nested
+	class TestUpdateVorgang {
+
+		@Test
+		void shouldCallRepository() {
+			elasticsearchService.updateVorgang(VorgangTestFactory.create());
+
+			verify(repostitory).save(any());
+		}
+	}
+
+}