diff --git a/CHANGELOG.md b/CHANGELOG.md
index e7716a4141b69299010bf893bb8fe9544d81a1c7..28de2a961793a3296438424764a6ebeb1871c7ee 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 ### Changed
 
 ### Fixed
+ - Students can no longer enqueue twice. [@rwbackx](https://gitlab.ewi.tudelft.nl/rwbackx)
 
 ### Deprecated
 
diff --git a/src/main/java/nl/tudelft/queue/service/RequestService.java b/src/main/java/nl/tudelft/queue/service/RequestService.java
index f6c047af11a8f187ddbeef997b5a7cd9daff8bdb..f787e95afc0c5c9aaef5a7168ca62919430f68a6 100644
--- a/src/main/java/nl/tudelft/queue/service/RequestService.java
+++ b/src/main/java/nl/tudelft/queue/service/RequestService.java
@@ -19,6 +19,7 @@ package nl.tudelft.queue.service;
 
 import java.time.LocalDateTime;
 import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.stream.Collectors;
 
@@ -57,6 +58,7 @@ import reactor.core.publisher.Mono;
 
 @Service
 public class RequestService {
+
 	@Autowired
 	private RequestRepository rr;
 
@@ -109,7 +111,8 @@ public class RequestService {
 	@Autowired
 	private PermissionService permissionService;
 
-	private static final ReentrantLock lock = new ReentrantLock();
+	private static final ReentrantLock requestTakingLock = new ReentrantLock();
+	private static final Set<Long> currentlyEnqueuing = ConcurrentHashMap.newKeySet();
 
 	/**
 	 * Creates a request in the request database based on the person that posted the request and the
@@ -132,39 +135,44 @@ public class RequestService {
 			throw new AccessDeniedException("Request not allowed");
 		}
 
-		if (request instanceof LabRequest) {
-			var labRequest = (LabRequest) request;
-			/*
-			 * TODO in the future, delegate to another service layer component,
-			 *  and let it generate a link for the respective online mode.
-			 * This is for the far future, when more online modes need to be supported.
-			 */
-
-			if (labRequest.getTimeSlot() != null && !labRequest.getTimeSlot().canTakeSlot()) {
-				throw new AccessDeniedException("Time slot is not available");
-			}
-
-			if (((LabRequest) request).getOnlineMode() == OnlineMode.JITSI) {
-				labRequest.setJitsiRoom(js.createJitsiRoomName(labRequest));
-			}
-			if (((LabRequest) request).getSession().getEnableExperimental()) {
-				((LabRequest) request).setQuestionId(qApi.addQuestion(new QuestionCreateDTO()
-						.edition(new EditionIdDTO()
-								.id(mCache.getOrThrow(dto.getModule()).getEdition().getId()))
-						.question(((LabRequest) request).getQuestion())).block());
+		try {
+			if (!currentlyEnqueuing.add(personId))
+				return;
+			if (request instanceof LabRequest labRequest) {
+				/*
+				 * TODO in the future, delegate to another service layer component,
+				 *  and let it generate a link for the respective online mode.
+				 * This is for the far future, when more online modes need to be supported.
+				 */
+
+				if (labRequest.getTimeSlot() != null && !labRequest.getTimeSlot().canTakeSlot()) {
+					throw new AccessDeniedException("Time slot is not available");
+				}
+
+				if (((LabRequest) request).getOnlineMode() == OnlineMode.JITSI) {
+					labRequest.setJitsiRoom(js.createJitsiRoomName(labRequest));
+				}
+				if (((LabRequest) request).getSession().getEnableExperimental()) {
+					((LabRequest) request).setQuestionId(qApi.addQuestion(new QuestionCreateDTO()
+							.edition(new EditionIdDTO()
+									.id(mCache.getOrThrow(dto.getModule()).getEdition().getId()))
+							.question(((LabRequest) request).getQuestion())).block());
+				}
 			}
-		}
 
-		request = rr.save(request);
-		var event = rer.applyAndSave(new RequestCreatedEvent(request));
+			request = rr.save(request);
+			var event = rer.applyAndSave(new RequestCreatedEvent(request));
 
-		if (request instanceof SelectionRequest) {
-			((SelectionRequest) request).getSession().getRequests().add((SelectionRequest) request);
-			checkFcfsSelection((SelectionRequest) request);
-		}
+			if (request instanceof SelectionRequest) {
+				((SelectionRequest) request).getSession().getRequests().add((SelectionRequest) request);
+				checkFcfsSelection((SelectionRequest) request);
+			}
 
-		if (sendEvent) {
-			wss.sendRequestCreated(event);
+			if (sendEvent) {
+				wss.sendRequestCreated(event);
+			}
+		} finally {
+			currentlyEnqueuing.remove(personId);
 		}
 	}
 
@@ -343,7 +351,7 @@ public class RequestService {
 	@Transactional(Transactional.TxType.REQUIRES_NEW)
 	public Optional<LabRequest> takeNextRequestFromTimeSlot(Person assistant,
 			ClosableTimeSlot timeSlot) {
-		lock.lock();
+		requestTakingLock.lock();
 		try {
 
 			// If the person is already working on a request, no new event should be created.
@@ -362,7 +370,7 @@ public class RequestService {
 
 			return request;
 		} finally {
-			lock.unlock();
+			requestTakingLock.unlock();
 		}
 	}
 
@@ -379,11 +387,11 @@ public class RequestService {
 	 */
 	public Optional<LabRequest> takeNextRequest(Person assistant, Lab lab,
 			RequestTableFilterDTO filter) {
-		lock.lock();
+		requestTakingLock.lock();
 		try {
 			return getNextRequest(assistant, lab, filter);
 		} finally {
-			lock.unlock();
+			requestTakingLock.unlock();
 		}
 	}
 
@@ -415,7 +423,7 @@ public class RequestService {
 	 */
 	@Transactional(Transactional.TxType.REQUIRES_NEW)
 	public LabRequest pickRequest(Person assistant, LabRequest request) {
-		lock.lock();
+		requestTakingLock.lock();
 		try {
 			Optional<LabRequest> oldRequests = lrr.findCurrentlyProcessingRequest(assistant,
 					request.getSession());
@@ -427,7 +435,7 @@ public class RequestService {
 
 			return request;
 		} finally {
-			lock.unlock();
+			requestTakingLock.unlock();
 		}
 	}
 
diff --git a/src/main/resources/templates/lab/enqueue.html b/src/main/resources/templates/lab/enqueue.html
index e60b8c5cd0d95d46652c3e8e84cb075133d66452..47f5575c3339da9f02e5af149abcccd81e8c5f45 100644
--- a/src/main/resources/templates/lab/enqueue.html
+++ b/src/main/resources/templates/lab/enqueue.html
@@ -48,7 +48,7 @@
     </div>
 
     <form th:action="@{/lab/{id}/enqueue/{rType}(id=${qSession.id}, rType=${rType})}" th:object="${request}" method="post"
-          class="form-horizontal">
+          class="form-horizontal" id="enqueue-form">
         <th:block layout:fragment="enqueue-body">
         </th:block>
 
@@ -61,6 +61,13 @@
             </div>
         </div>
     </form>
+    <script>
+        document.addEventListener("DOMContentLoaded", function () {
+            document.getElementById("enqueue-form").addEventListener("submit", function () {
+                document.getElementById("enqueue").setAttribute("disabled", "");
+            });
+        });
+    </script>
 </section>
 </body>
 </html>