diff --git a/emper/io/IoContext.hpp b/emper/io/IoContext.hpp
index 100a11a30f04c3b1332b1723365cf38576bb4e83..f72395cc78779ff05c6277eed89f4dbdaf92d254 100644
--- a/emper/io/IoContext.hpp
+++ b/emper/io/IoContext.hpp
@@ -18,10 +18,28 @@
 #include "emper-config.h"					// for EMPER_IO_WORKER_URING_ENTRIES
 #include "io/Stats.hpp"						// for Stats
 #include "lib/adt/LockedSet.hpp"	// for LockedSet
-#include "lib/sync/CountingTryLock.hpp"
 
 class Fiber;
 
+#ifdef EMPER_IO_CQ_LOCK_COUNTING_TRY_LOCK
+#include "lib/sync/CountingTryLock.hpp"
+using CqLock = emper::lib::sync::CountingTryLock;
+
+#elif defined EMPER_IO_CQ_LOCK_MUTEX
+#include <mutex>
+
+#include "lib/sync/PseudoCountingTryLock.hpp"
+using CqLock = emper::lib::sync::PseudoCountingTryLock<std::mutex>;
+
+#elif defined EMPER_IO_CQ_LOCK_SPIN_LOCK
+#include "lib/sync/PseudoCountingTryLock.hpp"
+#include "lib/sync/SpinLock.hpp"
+using CqLock = emper::lib::sync::PseudoCountingTryLock<emper::lib::sync::SpinLock>;
+
+#else
+#error Uknown cq lock implementation
+#endif
+
 namespace emper::io {
 class Future;
 
@@ -40,7 +58,7 @@ class IoContext : public Logger<LogSubsystem::IO> {
 
 	static thread_local IoContext *workerIo;
 	// TryLock protecting the completion queue of ring.
-	ALIGN_TO_CACHE_LINE lib::sync::CountingTryLock cq_lock;
+	ALIGN_TO_CACHE_LINE CqLock cq_lock;
 	struct io_uring ring;
 
 	// In a worker's IoContext This eventfd is registered with the io_uring to get completion
diff --git a/emper/lib/sync/PseudoCountingTryLock.hpp b/emper/lib/sync/PseudoCountingTryLock.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..2b278bad9d531774d40332666a73affac8d70636
--- /dev/null
+++ b/emper/lib/sync/PseudoCountingTryLock.hpp
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: LGPL-3.0-or-later
+// Copyright © 2021 Florian Fischer
+#pragma once
+
+namespace emper::lib::sync {
+
+template <class Lockable>
+class PseudoCountingTryLock {
+ private:
+	Lockable lock;
+
+ public:
+	[[nodiscard]] auto try_lock() -> bool {
+		lock.lock();
+		return true;
+	}
+
+	[[nodiscard]] auto try_lock_or_increment() -> bool { return try_lock(); }
+
+	auto unlock() -> uint32_t {
+		lock.unlock();
+		return 0;
+	}
+};
+}	 // namespace emper::lib::sync
diff --git a/emper/lib/sync/SpinLock.hpp b/emper/lib/sync/SpinLock.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..a0eef94bffc339a0dab70dfd998dcad83dcd84dc
--- /dev/null
+++ b/emper/lib/sync/SpinLock.hpp
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: LGPL-3.0-or-later
+// Copyright © 2021 Florian Fischer
+#pragma once
+
+#include <atomic>
+
+#include "Common.hpp"
+
+namespace emper::lib::sync {
+
+class SpinLock {
+ private:
+	std::atomic<bool> locked;
+
+ public:
+	SpinLock(bool locked = false) : locked(locked) {}
+
+	inline void lock() {
+		bool isLocked;
+		do {
+			isLocked = false;
+		} while (!locked.compare_exchange_weak(isLocked, true, std::memory_order_acquire,
+																					 std::memory_order_relaxed));
+	}
+
+	inline void unlock() { locked.store(false, std::memory_order_release); }
+};
+}	 // namespace emper::lib::sync
diff --git a/meson.build b/meson.build
index a73194416adeac577574d39bdcce9e66e4e77316..69f961dad178bd8fbc77320afe1058e4d3b64a52 100644
--- a/meson.build
+++ b/meson.build
@@ -93,6 +93,9 @@ foreach option : io_raw_options
 	conf_data.set('EMPER_IO_' + option.to_upper(), get_option('io_' + option))
 endforeach
 
+io_cq_lock_impl = get_option('io_cq_lock_implementation')
+conf_data.set('EMPER_IO_CQ_LOCK_' + io_cq_lock_impl.to_upper(), true)
+
 subdir('emper')
 subdir('tests')
 subdir('apps')
diff --git a/meson_options.txt b/meson_options.txt
index d9fcab82b3091aca6bd853f2826b22cb69a772e8..ac769500be89ab35a157e2a6a7bf662b1f2cb100 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -115,3 +115,10 @@ option(
   value: false,
   description: 'Share a common async backend between all io_urings'
 )
+option(
+  'io_cq_lock_implementation',
+  type: 'combo',
+  description: 'The lock implementation used to protect a worker IoContext CQ',
+  choices: ['spin_lock', 'counting_try_lock', 'mutex'],
+  value: 'counting_try_lock',
+)