diff --git a/api-lib-core/src/main/java/de/ozgcloud/apilib/common/command/grpc/GrpcOzgCloudCommandService.java b/api-lib-core/src/main/java/de/ozgcloud/apilib/common/command/grpc/GrpcOzgCloudCommandService.java
index 2506c223cc17f257ada388b6772728011b1ce830..37eed86704a675810bc035248ce4d6db12b6f529 100644
--- a/api-lib-core/src/main/java/de/ozgcloud/apilib/common/command/grpc/GrpcOzgCloudCommandService.java
+++ b/api-lib-core/src/main/java/de/ozgcloud/apilib/common/command/grpc/GrpcOzgCloudCommandService.java
@@ -14,6 +14,7 @@ import net.devh.boot.grpc.client.inject.GrpcClient;
 public class GrpcOzgCloudCommandService implements OzgCloudCommandService {
 
 	private static final int WAIT_TIME_MS = 500;
+	public static final int DEFAULT_COMMAND_REQUEST_THRESHOLD_MILLIS = 10000;
 
 	@GrpcClient("command-manager")
 	private final CommandServiceBlockingStub commandServiceStub;
@@ -22,6 +23,8 @@ public class GrpcOzgCloudCommandService implements OzgCloudCommandService {
 
 	private final OzgCloudCallContextProvider contextProvider;
 
+	private final int commandRequestThresholdMillis;
+
 	@Override
 	public OzgCloudCommand createAndWaitUntilDone(OzgCloudCommand commandToCreate) {
 		return waitUntilDone(create(commandToCreate));
@@ -34,8 +37,8 @@ public class GrpcOzgCloudCommandService implements OzgCloudCommandService {
 
 	OzgCloudCommand waitUntilDone(OzgCloudCommand commandToWaitFor) {
 		var command = commandToWaitFor;
-//		TODO timeout
-		while (!command.getStatus().isFinalState()) {
+		var timeout = System.currentTimeMillis() + commandRequestThresholdMillis;
+		while (!command.getStatus().isFinalState() && System.currentTimeMillis() < timeout) {
 			synchronized (this) {
 				try {
 					wait(WAIT_TIME_MS);
@@ -48,7 +51,7 @@ public class GrpcOzgCloudCommandService implements OzgCloudCommandService {
 		return command;
 	}
 
-	private OzgCloudCommand reloadCommand(OzgCloudCommandId commandId) {
+	OzgCloudCommand reloadCommand(OzgCloudCommandId commandId) {
 		GrpcGetCommandRequest request = GrpcGetCommandRequest.newBuilder().setId(commandId.toString()).build();
 		return mapper.fromGrpc(getCommandServiceStub().getCommand(request));
 	}
diff --git a/api-lib-core/src/test/java/de/ozgcloud/apilib/common/command/grpc/GrpcOzgCloudCommandServiceTest.java b/api-lib-core/src/test/java/de/ozgcloud/apilib/common/command/grpc/GrpcOzgCloudCommandServiceTest.java
index 8cdc3f055d216c2859f07ed4b5d29b3169dcf094..5b8713e61258819b251af5f3851e61b304a13107 100644
--- a/api-lib-core/src/test/java/de/ozgcloud/apilib/common/command/grpc/GrpcOzgCloudCommandServiceTest.java
+++ b/api-lib-core/src/test/java/de/ozgcloud/apilib/common/command/grpc/GrpcOzgCloudCommandServiceTest.java
@@ -7,23 +7,29 @@ import static org.mockito.Mockito.*;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
-import org.mockito.InjectMocks;
 import org.mockito.Mock;
-import org.mockito.Spy;
+import org.mockito.Mockito;
 
 import de.itvsh.ozg.pluto.grpc.command.CommandServiceGrpc.CommandServiceBlockingStub;
+import de.ozgcloud.apilib.common.callcontext.OzgCloudCallContextProvider;
 import de.ozgcloud.apilib.common.command.OzgCloudCommand;
+import de.ozgcloud.apilib.common.command.OzgCloudCommandStatus;
 
 class GrpcOzgCloudCommandServiceTest {
 
-	@Spy
-	@InjectMocks
 	private GrpcOzgCloudCommandService service;
 
 	@Mock
 	private CommandServiceBlockingStub serviceStub;
 	@Mock
 	private CommandMapper mapper;
+	@Mock
+	private OzgCloudCallContextProvider contextProvider;
+
+	@BeforeEach
+	void init() {
+		service = spy(new GrpcOzgCloudCommandService(serviceStub, mapper, contextProvider, 600));
+	}
 
 	@Nested
 	class TestCreateAndWaitUntilDone {
@@ -94,4 +100,14 @@ class GrpcOzgCloudCommandServiceTest {
 		}
 	}
 
+	@Test
+	void shouldTerminateByTimeout() {
+		var command = OzgCloudCommandTestFactory.createBuilder().status(OzgCloudCommandStatus.PENDING).build();
+		doReturn(command).when(service).reloadCommand(any());
+
+		service.waitUntilDone(command);
+
+		Mockito.verify(service, Mockito.times(2)).reloadCommand(command.getId());
+	}
+
 }
diff --git a/ozg-cloud-spring-boot-starter/src/main/java/de/ozgcloud/client/autoconfigure/OzgCloudClientAutoConfiguration.java b/ozg-cloud-spring-boot-starter/src/main/java/de/ozgcloud/client/autoconfigure/OzgCloudClientAutoConfiguration.java
index 61cc836003338e2e5dec2076f4c115abab6c8f8f..0fada0b00719ab624172d3dad90f7f33f27e2dbb 100644
--- a/ozg-cloud-spring-boot-starter/src/main/java/de/ozgcloud/client/autoconfigure/OzgCloudClientAutoConfiguration.java
+++ b/ozg-cloud-spring-boot-starter/src/main/java/de/ozgcloud/client/autoconfigure/OzgCloudClientAutoConfiguration.java
@@ -104,8 +104,9 @@ public class OzgCloudClientAutoConfiguration {
 	@Bean
 	@ConditionalOnProperty("ozgcloud.command-manager.address")
 	OzgCloudCommandService grpcCommandService(@GrpcClient("command-manager") CommandServiceBlockingStub commandServiceStub,
-		CommandMapper commandMapper,  OzgCloudCallContextProvider contextProvider) {
-		return new GrpcOzgCloudCommandService(commandServiceStub, commandMapper, contextProvider);
+		CommandMapper commandMapper, OzgCloudCallContextProvider contextProvider) {
+		return new GrpcOzgCloudCommandService(commandServiceStub, commandMapper, contextProvider,
+			GrpcOzgCloudCommandService.DEFAULT_COMMAND_REQUEST_THRESHOLD_MILLIS);
 	}
 
 	@Bean