diff --git a/authentik/tenants/db.py b/authentik/tenants/db.py index e6735a01def5..2a7563f58cfd 100644 --- a/authentik/tenants/db.py +++ b/authentik/tenants/db.py @@ -1,6 +1,7 @@ from random import choice from django.conf import settings +from django.db import DEFAULT_DB_ALIAS, connections class FailoverRouter: @@ -10,16 +11,22 @@ class FailoverRouter: def __init__(self) -> None: super().__init__() self.database_aliases = set(settings.DATABASES.keys()) - self.read_replica_aliases = list(self.database_aliases - {"default"}) + self.read_replica_aliases = list(self.database_aliases - {DEFAULT_DB_ALIAS}) self.replica_enabled = len(self.read_replica_aliases) > 0 def db_for_read(self, model, **hints): if not self.replica_enabled: - return "default" + return DEFAULT_DB_ALIAS + # Stay on primary for the entire transaction to maintain consistency. + # Reading from a replica mid-transaction would give a different snapshot, + # breaking transactional semantics (not just read-your-writes, but the + # entire consistent point-in-time view that a transaction provides). + if connections[DEFAULT_DB_ALIAS].in_atomic_block: + return DEFAULT_DB_ALIAS return choice(self.read_replica_aliases) # nosec def db_for_write(self, model, **hints): - return "default" + return DEFAULT_DB_ALIAS def allow_relation(self, obj1, obj2, **hints): """Relations between objects are allowed if both objects are