Index: iknow-api/Services/Implementations/EnrollmentService.cs
===================================================================
--- iknow-api/Services/Implementations/EnrollmentService.cs	(revision 1b20b226a74790f84dc06dc488f4f761b510a3f2)
+++ iknow-api/Services/Implementations/EnrollmentService.cs	(revision 2853f2ebbc643ed265db27aa0af19878c14db48c)
@@ -3,4 +3,5 @@
 using iknow_api.Models;
 using Microsoft.EntityFrameworkCore;
+using Npgsql;
 
 namespace iknow_api.Services
@@ -220,4 +221,14 @@
                 };
             }
+            catch (DbUpdateException ex) when (IsUniqueViolation(ex))
+            {
+                // Two enrolments for the same semester sent at the same time both
+                // pass the check above, because each transaction reads the state
+                // from before the other one wrote. UNIQUE (user_id, semester_id)
+                // is what actually settles it, so the loser gets the same
+                // sentence as if the check had caught it.
+                await transaction.RollbackAsync();
+                return Fail("You are already enrolled in that semester.");
+            }
             catch
             {
@@ -226,4 +237,8 @@
             }
         }
+
+        /// <summary>23505 is unique_violation.</summary>
+        private static bool IsUniqueViolation(DbUpdateException ex) =>
+            ex.InnerException is PostgresException { SqlState: "23505" };
 
         private static EnrollSemesterResultDto Fail(string message) =>
