diff --git a/emper/Runtime.cpp b/emper/Runtime.cpp
index 31c7b1c232545aeddd141fa6f9348554bf29d6e9..9969fcc03453f7ea3251fd65deda234b6450b507 100644
--- a/emper/Runtime.cpp
+++ b/emper/Runtime.cpp
@@ -87,15 +87,13 @@ Runtime::Runtime(workerid_t workerCount, RuntimeStrategyFactory& strategyFactory
 		currentRuntime = this;
 	}
 
-	// initialize the global and all worker IoContexts
-	if constexpr (emper::IO) {
+	// initialize the global IoContext if a completer is used
+	if constexpr (emper::IO && emper::IO_COMPLETER_BEHAVIOR != emper::IoCompleterBehavior::none) {
 		// The global io_uring needs at least workerCount entries in its SQ because
 		// for each worker's IoContext one eventfd read is prepared before the
 		// globalCompleter is started and submits all previously prepared sqes.
 		globalIo = new GlobalIoContext(*this, workerCount);
-		if constexpr (emper::IO_COMPLETER_BEHAVIOR != emper::IoCompleterBehavior::none) {
-			globalIo->startGlobalCompleter();
-		}
+		globalIo->startGlobalCompleter();
 
 		if constexpr (emper::STATS) {
 			globalIo->stats.workerId = emper::io::Stats::GLOBAL_COMPLETER_ID;
@@ -178,10 +176,12 @@ Runtime::~Runtime() {
 	delete[] threads;
 
 	if constexpr (emper::IO) {
-		// It is safer to destroy the globalIo before the worker IoContexts
-		// because pointer to the worker IoContexts can outlife their objects
-		// in the globalCompleter
-		delete globalIo;
+		if constexpr (emper::IO_COMPLETER_BEHAVIOR != emper::IoCompleterBehavior::none) {
+			// It is safer to destroy the globalIo before the worker IoContexts
+			// because pointer to the worker IoContexts can outlife their objects
+			// in the globalCompleter
+			delete globalIo;
+		}
 
 		for (unsigned int i = 0; i < workerCount; ++i) {
 			delete ioContexts[i];
@@ -286,7 +286,7 @@ void Runtime::initiateTermination() {
 
 	wakeupSem.notify_many(workerCount);
 
-	if constexpr (emper::IO) {
+	if constexpr (emper::IO && emper::IO_COMPLETER_BEHAVIOR != emper::IoCompleterBehavior::none) {
 		globalIo->initiateTermination();
 	}
 }
@@ -299,7 +299,7 @@ void Runtime::waitUntilFinished() {
 		}
 	}
 
-	if constexpr (emper::IO) {
+	if constexpr (emper::IO && emper::IO_COMPLETER_BEHAVIOR != emper::IoCompleterBehavior::none) {
 		globalIo->waitUntilFinished();
 	}
 
diff --git a/emper/io/Future.hpp b/emper/io/Future.hpp
index b9c073232ab28cd091191b031b67cb7b916f06bb..d0978de740cc9c636b812765ef2cb6d3fa76d723 100644
--- a/emper/io/Future.hpp
+++ b/emper/io/Future.hpp
@@ -18,8 +18,9 @@
 #include "BinaryPrivateSemaphore.hpp"	 // for BPS
 #include "CallerEnvironment.hpp"			 // for CallerEnvironment, ANYWHERE
 #include "Common.hpp"
-#include "Debug.hpp"				 // for LOGD, LogSubsystem, LogSubsyst...
-#include "Emper.hpp"				 // for DEBUG
+#include "Debug.hpp"	// for LOGD, LogSubsystem, LogSubsyst...
+#include "Emper.hpp"	// for DEBUG
+#include "Runtime.hpp"
 #include "io/Operation.hpp"	 // for Operation, operator<<, Operati...
 
 struct io_uring_sqe;
@@ -387,7 +388,15 @@ class PartialCompletableFuture : public Future {
 	}
 
 	auto completeAndGetContinuation(int32_t res) -> Fiber* override {
-		CompletionType completion = tryComplete<CallerEnvironment::ANYWHERE>(res);
+		CompletionType completion;
+
+		// If there is no completer we must be in a emper worker
+		// Otherwise decide at runtime where the possible partialCompletion should be resubmitted
+		if (emper::IO_COMPLETER_BEHAVIOR == emper::IoCompleterBehavior::none || Runtime::inRuntime()) {
+			completion = tryComplete<CallerEnvironment::EMPER>(res);
+		} else {
+			completion = tryComplete<CallerEnvironment::ANYWHERE>(res);
+		}
 
 		switch (completion) {
 			case CompletionType::Resubmission: