diff --git a/mo/users.py b/mo/users.py
index 96bc328b51bfbe0b9957584f88458e7d537f6c00..b57c6e0557861c16c31f7ac9afb63089d2d94aeb 100644
--- a/mo/users.py
+++ b/mo/users.py
@@ -7,6 +7,7 @@ import email.errors
 import email.headerregistry
 import re
 import secrets
+from sqlalchemy.dialects.postgresql import insert as pgsql_insert
 from typing import Optional, Tuple
 
 import mo
@@ -96,40 +97,57 @@ def change_user_to_org(user, reason: str):
 
 def find_or_create_user(email: str, krestni: Optional[str], prijmeni: Optional[str], is_org: bool, reason: str, allow_change_user_to_org=False) -> Tuple[db.User, bool, bool]:
     sess = db.get_session()
-    user = sess.query(db.User).with_for_update().filter_by(email=email).one_or_none()
-    is_new = user is None
+    user = sess.query(db.User).filter_by(email=email).one_or_none()
+    is_new = False
     is_change_user_to_org = False
+
     if user is None:  # HACK: Podmínku je nutné zapsat znovu místo užití is_new, jinak si s tím mypy neporadí
         if not krestni or not prijmeni:
             raise mo.CheckError('Osoba s daným e-mailem zatím neexistuje, je nutné uvést její jméno.')
-        user = db.User(email=email, first_name=krestni, last_name=prijmeni, is_org=is_org)
-        sess.add(user)
-        sess.flush()    # Aby uživatel dostal user_id
-        logger.info(f'{reason.title()}: Založen uživatel user=#{user.user_id} email=<{user.email}>')
-        mo.util.log(
-            type=db.LogType.user,
-            what=user.user_id,
-            details={'action': 'create-user', 'reason': reason, 'new': db.row2dict(user)},
+
+        res = sess.connection().execute(
+            pgsql_insert(db.User.__table__)
+            .values(
+                email=email,
+                first_name=krestni,
+                last_name=prijmeni,
+                is_org=is_org,
+            )
+            .on_conflict_do_nothing()
+            .returning(db.User.user_id)
         )
-    else:
-        if (krestni and user.first_name != krestni) or (prijmeni and user.last_name != prijmeni):
-            raise mo.CheckError(f'Osoba již registrována s odlišným jménem {user.full_name()}')
-        if (user.is_admin or user.is_org) != is_org:
-            if is_org:
-                if allow_change_user_to_org:
-                    change_user_to_org(user, reason)
-                    is_change_user_to_org = True
-                else:
-                    raise CheckErrorOrgIsUser('Nelze předefinovat účastníka na organizátora.')
+
+        user = sess.query(db.User).filter_by(email=email).one()
+
+        if res.fetchall():
+            is_new = True
+            logger.info(f'{reason.title()}: Založen uživatel user=#{user.user_id} email=<{user.email}>')
+            mo.util.log(
+                type=db.LogType.user,
+                what=user.user_id,
+                details={'action': 'create-user', 'reason': reason, 'new': db.row2dict(user)},
+            )
+
+    if (krestni and user.first_name != krestni) or (prijmeni and user.last_name != prijmeni):
+        raise mo.CheckError(f'Osoba již registrována s odlišným jménem {user.full_name()}')
+    if (user.is_admin or user.is_org) != is_org:
+        if is_org:
+            if allow_change_user_to_org:
+                change_user_to_org(user, reason)
+                is_change_user_to_org = True
             else:
-                raise mo.CheckError('Nelze předefinovat organizátora na účastníka.')
+                raise CheckErrorOrgIsUser('Nelze předefinovat účastníka na organizátora.')
+        else:
+            raise mo.CheckError('Nelze předefinovat organizátora na účastníka.')
+
     return user, is_new, is_change_user_to_org
 
 
 def find_or_create_participant(user: db.User, year: int, school_id: Optional[int], birth_year: Optional[int], grade: Optional[str], reason: str) -> Tuple[db.Participant, bool]:
     sess = db.get_session()
     part = sess.query(db.Participant).get((user.user_id, year))
-    is_new = part is None
+    is_new = False
+
     if part is None:
         prev_part = sess.query(db.Participant).filter_by(user_id=user.user_id).order_by(db.Participant.year.desc()).limit(1).one_or_none()
         if not school_id:
@@ -144,19 +162,37 @@ def find_or_create_participant(user: db.User, year: int, school_id: Optional[int
                 raise mo.CheckError('Osoba s daným e-mailem zatím není zaregistrovaná do ročníku, je nutné uvést rok narození.')
         if not grade:
             raise mo.CheckError('Osoba s daným e-mailem zatím není zaregistrovaná do ročníku, je nutné uvést ročník.')
-        part = db.Participant(user=user, year=year, school=school_id, birth_year=birth_year, grade=grade)
-        sess.add(part)
-        logger.info(f'{reason.title()}: Založen účastník #{user.user_id}')
-        mo.util.log(
-            type=db.LogType.participant,
-            what=user.user_id,
-            details={'action': 'create-participant', 'reason': reason, 'new': db.row2dict(part)},
+
+        res = sess.connection().execute(
+            pgsql_insert(db.Participant.__table__)
+            .values(
+                user_id=user.user_id,
+                year=year,
+                school=school_id,
+                birth_year=birth_year,
+                grade=grade,
+            )
+            .on_conflict_do_nothing()
+            .returning(db.Participant.user_id)
         )
-    else:
-        if ((school_id and part.school != school_id)
-                or (grade and part.grade != grade)
-                or (birth_year and part.birth_year != birth_year)):
-            raise mo.CheckError('Účastník již zaregistrován s odlišnou školou/ročníkem/rokem narození')
+
+        part = sess.query(db.Participant).get((user.user_id, year))
+        assert part is not None
+
+        if res.fetchall():
+            is_new = True
+            logger.info(f'{reason.title()}: Založen účastník #{user.user_id}')
+            mo.util.log(
+                type=db.LogType.participant,
+                what=user.user_id,
+                details={'action': 'create-participant', 'reason': reason, 'new': db.row2dict(part)},
+            )
+
+    if ((school_id and part.school != school_id)
+            or (grade and part.grade != grade)
+            or (birth_year and part.birth_year != birth_year)):
+        raise mo.CheckError('Účastník již zaregistrován s odlišnou školou/ročníkem/rokem narození')
+
     return part, is_new
 
 
@@ -165,27 +201,47 @@ def find_or_create_participation(user: db.User, contest: db.Contest, place: Opti
         place = contest.place
 
     sess = db.get_session()
-    pions = (sess.query(db.Participation)
-             .filter_by(user=user)
-             .filter(db.Participation.contest.has(db.Contest.round == contest.round))
-             .all())
+    pion = None
+    is_new = False
+    retry = False
+
+    while pion is None:
+        pions = (sess.query(db.Participation)
+                 .filter_by(user=user)
+                 .filter(db.Participation.contest.has(db.Contest.round == contest.round))
+                 .all())
+
+        if len(pions) == 0:
+            assert not retry
+            retry = True
+            res = sess.connection().execute(
+                pgsql_insert(db.Participation.__table__)
+                .values(
+                    user_id=user.user_id,
+                    contest_id=contest.contest_id,
+                    place_id=place.place_id,
+                    state=db.PartState.active,
+                )
+                .on_conflict_do_nothing()
+                .returning(db.Participation.user_id)
+            )
+            if res.fetchall():
+                is_new = True
+        elif len(pions) == 1:
+            pion = pions[0]
+        else:
+            raise mo.CheckError('Již se tohoto kola účastní ve více oblastech, což by nemělo být možné')
+
+    if pion.place != place:
+        raise mo.CheckError(f'Již se tohoto kola účastní v {contest.round.get_level().name_locative("jiném", "jiné", "jiném")} ({pion.place.get_code()})')
 
-    is_new = pions == []
     if is_new:
-        pion = db.Participation(user=user, contest=contest, place_id=place.place_id, state=db.PartState.active)
-        sess.add(pion)
         logger.info(f'{reason.title()}: Založena účast user=#{user.user_id} contest=#{contest.contest_id} place=#{place.place_id}')
         mo.util.log(
             type=db.LogType.participant,
             what=user.user_id,
             details={'action': 'add-to-contest', 'reason': reason, 'new': db.row2dict(pion)},
         )
-    elif len(pions) == 1:
-        pion = pions[0]
-        if pion.place != place:
-            raise mo.CheckError(f'Již se tohoto kola účastní v {contest.round.get_level().name_locative("jiném", "jiné", "jiném")} ({pion.place.get_code()})')
-    else:
-        raise mo.CheckError('Již se tohoto kola účastní ve více oblastech, což by nemělo být možné')
 
     return pion, is_new