Repository: urlaubsverwaltung/urlaubsverwaltung
Pull request #4826 (2024-08-02 19:25:13)

introduce explicit single tenant configuration
<!--

Thanks for contributing to the Urlaubsverwaltung.
Please review the following notes before submitting you pull request.

Please look for other issues or pull requests which already work on this topic. Is somebody already on it? Do you need to synchronize?

# Security Vulnerabilities

🛑 STOP! 🛑 If your contribution fixes a security vulnerability, please do not submit it.
Instead, please open a report of a security vulnerability via
[Report a security vulnerability](https://github.com/urlaubsverwaltung/urlaubsverwaltung/security/advisories/new)


# Describing Your Changes

If, having reviewed the notes above, you're ready to submit your pull request, please
provide a brief description of the proposed changes.

If they:
 🐞 fix a bug, please describe the broken behaviour and how the changes fix it.
    Please label with 'type: bug' and 'status: new'
    
 🎁 make an enhancement, please describe the new functionality and why you believe it's useful.
    Please label with 'type: enhancement' and 'status: new'
 
If your pull request relates to any existing issues,
please reference them by using the issue number prefixed with #.

-->


sonarcloud[bot]: ## [![Quality Gate Failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-failed-20px.png 'Quality Gate Failed')](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826) **Quality Gate failed**  
Failed conditions  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/failed-16px.png '') [74.1% Coverage on New Code](https://sonarcloud.io/component_measures?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826&metric=new_coverage&view=list) (required ≥ 80%)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826)


sonarcloud[bot]: ## [![Quality Gate Failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-failed-20px.png 'Quality Gate Failed')](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826) **Quality Gate failed**  
Failed conditions  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/failed-16px.png '') [78.6% Coverage on New Code](https://sonarcloud.io/component_measures?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826&metric=new_coverage&view=list) (required ≥ 80%)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826)


sonarcloud[bot]: ## [![Quality Gate Failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-failed-20px.png 'Quality Gate Failed')](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826) **Quality Gate failed**  
Failed conditions  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/failed-16px.png '') [78.6% Coverage on New Code](https://sonarcloud.io/component_measures?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826&metric=new_coverage&view=list) (required ≥ 80%)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826)


sonarcloud[bot]: ## [![Quality Gate Failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-failed-20px.png 'Quality Gate Failed')](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826) **Quality Gate failed**  
Failed conditions  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/failed-16px.png '') [78.6% Coverage on New Code](https://sonarcloud.io/component_measures?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826&metric=new_coverage&view=list) (required ≥ 80%)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826)


sonarcloud[bot]: ## [![Quality Gate Failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-failed-20px.png 'Quality Gate Failed')](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826) **Quality Gate failed**  
Failed conditions  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/failed-16px.png '') [70.9% Coverage on New Code](https://sonarcloud.io/component_measures?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826&metric=new_coverage&view=list) (required ≥ 80%)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826)


sonarcloud[bot]: ## [![Quality Gate Failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-failed-20px.png 'Quality Gate Failed')](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826) **Quality Gate failed**  
Failed conditions  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/failed-16px.png '') [70.9% Coverage on New Code](https://sonarcloud.io/component_measures?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826&metric=new_coverage&view=list) (required ≥ 80%)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826)


sonarcloud[bot]: ## [![Quality Gate Failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-failed-20px.png 'Quality Gate Failed')](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826) **Quality Gate failed**  
Failed conditions  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/failed-16px.png '') [69.1% Coverage on New Code](https://sonarcloud.io/component_measures?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826&metric=new_coverage&view=list) (required ≥ 80%)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826)


sonarcloud[bot]: ## [![Quality Gate Failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-failed-20px.png 'Quality Gate Failed')](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826) **Quality Gate failed**  
Failed conditions  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/failed-16px.png '') [68.5% Coverage on New Code](https://sonarcloud.io/component_measures?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826&metric=new_coverage&view=list) (required ≥ 80%)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826)


sonarcloud[bot]: ## [![Quality Gate Failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-failed-20px.png 'Quality Gate Failed')](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826) **Quality Gate failed**  
Failed conditions  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/failed-16px.png '') [70.2% Coverage on New Code](https://sonarcloud.io/component_measures?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826&metric=new_coverage&view=list) (required ≥ 80%)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826)


sonarcloud[bot]: ## [![Quality Gate Failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-failed-20px.png 'Quality Gate Failed')](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826) **Quality Gate failed**  
Failed conditions  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/failed-16px.png '') [70.2% Coverage on New Code](https://sonarcloud.io/component_measures?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826&metric=new_coverage&view=list) (required ≥ 80%)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826)


sonarcloud[bot]: ## [![Quality Gate Failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-failed-20px.png 'Quality Gate Failed')](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826) **Quality Gate failed**  
Failed conditions  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/failed-16px.png '') [70.2% Coverage on New Code](https://sonarcloud.io/component_measures?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826&metric=new_coverage&view=list) (required ≥ 80%)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826)


sonarcloud[bot]: ## [![Quality Gate Failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-failed-20px.png 'Quality Gate Failed')](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826) **Quality Gate failed**  
Failed conditions  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/failed-16px.png '') [70.2% Coverage on New Code](https://sonarcloud.io/component_measures?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826&metric=new_coverage&view=list) (required ≥ 80%)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826)


sonarcloud[bot]: ## [![Quality Gate Failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-failed-20px.png 'Quality Gate Failed')](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826) **Quality Gate failed**  
Failed conditions  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/failed-16px.png '') [70.2% Coverage on New Code](https://sonarcloud.io/component_measures?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826&metric=new_coverage&view=list) (required ≥ 80%)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826)


sonarcloud[bot]: ## [![Quality Gate Failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-failed-20px.png 'Quality Gate Failed')](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826) **Quality Gate failed**  
Failed conditions  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/failed-16px.png '') [72.2% Coverage on New Code](https://sonarcloud.io/component_measures?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826&metric=new_coverage&view=list) (required ≥ 80%)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826)


sonarcloud[bot]: ## [![Quality Gate Failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-failed-20px.png 'Quality Gate Failed')](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826) **Quality Gate failed**  
Failed conditions  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/failed-16px.png '') [71.3% Coverage on New Code](https://sonarcloud.io/component_measures?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826&metric=new_coverage&view=list) (required ≥ 80%)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826)


sonarcloud[bot]: ## [![Quality Gate Failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-failed-20px.png 'Quality Gate Failed')](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826) **Quality Gate failed**  
Failed conditions  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/failed-16px.png '') [71.8% Coverage on New Code](https://sonarcloud.io/component_measures?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826&metric=new_coverage&view=list) (required ≥ 80%)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=4826)



Patch:
diff --git a/pom.xml b/pom.xml
index 0b5a35449..5b1903140 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,7 +19,7 @@
     <maven.compiler.showWarnings>true</maven.compiler.showWarnings>
     <maven.compiler.showDeprecation>true</maven.compiler.showDeprecation>
     <java.version>21</java.version>
-    <uv-extension-api.version>1.2.0</uv-extension-api.version>
+    <uv-extension-api.version>1.3.0</uv-extension-api.version>
     <jollyday.version>1.0.0</jollyday.version>
 
     <!-- Remove commons-compress dependency when testcontainers ships with commons-compress >= 1.27.1, see
@@ -33,6 +33,8 @@
     <docker-publish-registry-path>path/example</docker-publish-registry-path>
     <docker-publish-registry-username>username</docker-publish-registry-username>
     <docker-publish-registry-password>password</docker-publish-registry-password>
+    <docker-image-name>${project.artifactId}</docker-image-name>
+    <docker-image-version>${project.version}</docker-image-version>
   </properties>
 
   <scm>
@@ -314,7 +316,7 @@
           <layout>ZIP</layout>
           <image>
             <name>
-              ${docker-publish-registry}/${docker-publish-registry-path}/${project.artifactId}:${project.version}
+              ${docker-publish-registry}/${docker-publish-registry-path}/${docker-image-name}:${docker-image-version}
             </name>
             <env>
               <BPE_DEFAULT_BPL_JVM_CLASS_ADJUSTMENT>120%</BPE_DEFAULT_BPL_JVM_CLASS_ADJUSTMENT>
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/account/AccountEntity.java b/src/main/java/org/synyx/urlaubsverwaltung/account/AccountEntity.java
index 1fa2cf881..28d87d857 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/account/AccountEntity.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/account/AccountEntity.java
@@ -7,6 +7,7 @@ import jakarta.persistence.Id;
 import jakarta.persistence.ManyToOne;
 import jakarta.persistence.SequenceGenerator;
 import org.synyx.urlaubsverwaltung.person.Person;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.AbstractTenantAwareEntity;
 
 import java.math.BigDecimal;
 import java.time.LocalDate;
@@ -18,7 +19,7 @@ import static jakarta.persistence.GenerationType.SEQUENCE;
  * This class describes how many vacation days and remaining vacation days a person has in which period (validFrom, validTo).
  */
 @Entity(name = "account")
-public class AccountEntity {
+public class AccountEntity extends AbstractTenantAwareEntity {
 
     @Id
     @Column(name = "id", unique = true, nullable = false, updatable = false)
@@ -47,7 +48,7 @@ public class AccountEntity {
     private String comment;
 
     protected AccountEntity() {
-        /* OK */
+        super();
     }
 
     public AccountEntity(Person person, LocalDate validFrom, LocalDate validTo, Boolean doRemainingVacationDaysExpire,
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/account/TurnOfTheYearAccountUpdaterConfiguration.java b/src/main/java/org/synyx/urlaubsverwaltung/account/TurnOfTheYearAccountUpdaterConfiguration.java
index 83a3390cb..8c51f153a 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/account/TurnOfTheYearAccountUpdaterConfiguration.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/account/TurnOfTheYearAccountUpdaterConfiguration.java
@@ -6,8 +6,10 @@ import org.springframework.scheduling.annotation.SchedulingConfigurer;
 import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
 import org.springframework.scheduling.config.ScheduledTaskRegistrar;
 import org.synyx.urlaubsverwaltung.config.ScheduleLocking;
+import org.synyx.urlaubsverwaltung.tenancy.configuration.single.ConditionalOnSingleTenantMode;
 
 @Configuration
+@ConditionalOnSingleTenantMode
 public class TurnOfTheYearAccountUpdaterConfiguration implements SchedulingConfigurer {
 
     private final AccountProperties accountProperties;
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/account/TurnOfTheYearAccountUpdaterService.java b/src/main/java/org/synyx/urlaubsverwaltung/account/TurnOfTheYearAccountUpdaterService.java
index 1b7cf1f78..bf8999648 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/account/TurnOfTheYearAccountUpdaterService.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/account/TurnOfTheYearAccountUpdaterService.java
@@ -39,7 +39,7 @@ public class TurnOfTheYearAccountUpdaterService {
 
     @Autowired
     TurnOfTheYearAccountUpdaterService(PersonService personService, AccountService accountService,
-                                              AccountInteractionService accountInteractionService, VacationDaysReminderService vacationDaysReminderService, MailService mailService, Clock clock) {
+                                       AccountInteractionService accountInteractionService, VacationDaysReminderService vacationDaysReminderService, MailService mailService, Clock clock) {
         this.personService = personService;
         this.accountService = accountService;
         this.accountInteractionService = accountInteractionService;
@@ -48,7 +48,7 @@ public class TurnOfTheYearAccountUpdaterService {
         this.clock = clock;
     }
 
-    void updateAccountsForNextPeriod() {
+    public void updateAccountsForNextPeriod() {
 
         LOG.info("Starting update of holidays accounts to calculate the remaining vacation days.");
 
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/account/VacationDaysReminderConfiguration.java b/src/main/java/org/synyx/urlaubsverwaltung/account/VacationDaysReminderConfiguration.java
index 1f345b9aa..e279cd4c5 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/account/VacationDaysReminderConfiguration.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/account/VacationDaysReminderConfiguration.java
@@ -6,8 +6,10 @@ import org.springframework.scheduling.annotation.SchedulingConfigurer;
 import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
 import org.springframework.scheduling.config.ScheduledTaskRegistrar;
 import org.synyx.urlaubsverwaltung.config.ScheduleLocking;
+import org.synyx.urlaubsverwaltung.tenancy.configuration.single.ConditionalOnSingleTenantMode;
 
 @Configuration
+@ConditionalOnSingleTenantMode
 public class VacationDaysReminderConfiguration implements SchedulingConfigurer {
 
     private final AccountProperties accountProperties;
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/account/VacationDaysReminderService.java b/src/main/java/org/synyx/urlaubsverwaltung/account/VacationDaysReminderService.java
index 277d1749f..9c44c57d4 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/account/VacationDaysReminderService.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/account/VacationDaysReminderService.java
@@ -47,7 +47,7 @@ public class VacationDaysReminderService {
      * Reminds for vacation days left for <b>current year</b>.
      */
     @Async
-    void remindForCurrentlyLeftVacationDays() {
+    public void remindForCurrentlyLeftVacationDays() {
         final int year = Year.now(clock).getValue();
         final List<Person> persons = personService.getActivePersons();
 
@@ -69,7 +69,7 @@ public class VacationDaysReminderService {
      * Should be called after turn of the year logic which calculates the new account for the new year
      */
     @Async
-    void remindForRemainingVacationDays() {
+    public void remindForRemainingVacationDays() {
         final int year = Year.now(clock).getValue();
         final List<Person> persons = personService.getActivePersons();
 
@@ -96,7 +96,7 @@ public class VacationDaysReminderService {
      * Notify about expired remaining vacation days
      */
     @Async
-    void notifyForExpiredRemainingVacationDays() {
+    public void notifyForExpiredRemainingVacationDays() {
         final LocalDate now = LocalDate.now(clock);
         final int year = now.getYear();
 
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/application/application/ApplicationEntity.java b/src/main/java/org/synyx/urlaubsverwaltung/application/application/ApplicationEntity.java
index 5f3f8ee57..e2e6389a4 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/application/application/ApplicationEntity.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/application/application/ApplicationEntity.java
@@ -15,6 +15,7 @@ import org.synyx.urlaubsverwaltung.DurationConverter;
 import org.synyx.urlaubsverwaltung.application.vacationtype.VacationTypeEntity;
 import org.synyx.urlaubsverwaltung.period.DayLength;
 import org.synyx.urlaubsverwaltung.person.Person;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.AbstractTenantAwareEntity;
 
 import java.time.Duration;
 import java.time.LocalDate;
@@ -28,7 +29,7 @@ import static jakarta.persistence.FetchType.EAGER;
 import static jakarta.persistence.GenerationType.SEQUENCE;
 
 @Entity(name = "application")
-class ApplicationEntity {
+public class ApplicationEntity extends AbstractTenantAwareEntity {
 
     @Id
     @Column(name = "id", unique = true, nullable = false, updatable = false)
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/application/application/ApplicationReminderMailConfiguration.java b/src/main/java/org/synyx/urlaubsverwaltung/application/application/ApplicationReminderMailConfiguration.java
index c074910f7..abe097b11 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/application/application/ApplicationReminderMailConfiguration.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/application/application/ApplicationReminderMailConfiguration.java
@@ -7,8 +7,10 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
 import org.springframework.scheduling.config.ScheduledTaskRegistrar;
 import org.synyx.urlaubsverwaltung.application.ApplicationProperties;
 import org.synyx.urlaubsverwaltung.config.ScheduleLocking;
+import org.synyx.urlaubsverwaltung.tenancy.configuration.single.ConditionalOnSingleTenantMode;
 
 @Configuration
+@ConditionalOnSingleTenantMode
 class ApplicationReminderMailConfiguration implements SchedulingConfigurer {
 
     private final ApplicationProperties applicationProperties;
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/application/application/ApplicationReminderMailService.java b/src/main/java/org/synyx/urlaubsverwaltung/application/application/ApplicationReminderMailService.java
index 2c4e184d7..5d350aba3 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/application/application/ApplicationReminderMailService.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/application/application/ApplicationReminderMailService.java
@@ -20,7 +20,7 @@ import static org.synyx.urlaubsverwaltung.application.application.ApplicationSta
 import static org.synyx.urlaubsverwaltung.application.application.ApplicationStatus.WAITING;
 
 @Component
-class ApplicationReminderMailService {
+public class ApplicationReminderMailService {
 
     private static final Logger LOG = getLogger(lookup().lookupClass());
 
@@ -37,7 +37,7 @@ class ApplicationReminderMailService {
         this.clock = clock;
     }
 
-    void sendWaitingApplicationsReminderNotification() {
+    public void sendWaitingApplicationsReminderNotification() {
 
         final boolean isRemindForWaitingApplicationsActive =
             settingsService.getSettings().getApplicationSettings().isRemindForWaitingApplications();
@@ -64,7 +64,7 @@ class ApplicationReminderMailService {
         }
     }
 
-    void sendUpcomingApplicationsReminderNotification() {
+    public void sendUpcomingApplicationsReminderNotification() {
 
         final ApplicationSettings applicationSettings = settingsService.getSettings().getApplicationSettings();
         if (applicationSettings.isRemindForUpcomingApplications()) {
@@ -83,7 +83,7 @@ class ApplicationReminderMailService {
         applicationService.save(application);
     }
 
-    void sendUpcomingHolidayReplacementReminderNotification() {
+    public void sendUpcomingHolidayReplacementReminderNotification() {
 
         final ApplicationSettings applicationSettings = settingsService.getSettings().getApplicationSettings();
         if (applicationSettings.isRemindForUpcomingHolidayReplacement()) {
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/application/comment/ApplicationCommentEntity.java b/src/main/java/org/synyx/urlaubsverwaltung/application/comment/ApplicationCommentEntity.java
index a149272db..36220b62f 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/application/comment/ApplicationCommentEntity.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/application/comment/ApplicationCommentEntity.java
@@ -8,6 +8,7 @@ import jakarta.persistence.Id;
 import jakarta.persistence.ManyToOne;
 import jakarta.persistence.SequenceGenerator;
 import org.synyx.urlaubsverwaltung.person.Person;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.AbstractTenantAwareEntity;
 
 import java.time.Clock;
 import java.time.Instant;
@@ -19,7 +20,7 @@ import static java.time.temporal.ChronoUnit.DAYS;
 import static java.util.Optional.ofNullable;
 
 @Entity(name = "application_comment")
-class ApplicationCommentEntity {
+public class ApplicationCommentEntity extends AbstractTenantAwareEntity {
 
     @Id
     @Column(name = "id", unique = true, nullable = false, updatable = false)
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/application/specialleave/InitialDefaultSpecialLeaveSettingsConfigurerSingleTenant.java b/src/main/java/org/synyx/urlaubsverwaltung/application/specialleave/InitialDefaultSpecialLeaveSettingsConfigurerSingleTenant.java
new file mode 100644
index 000000000..df39ee5aa
--- /dev/null
+++ b/src/main/java/org/synyx/urlaubsverwaltung/application/specialleave/InitialDefaultSpecialLeaveSettingsConfigurerSingleTenant.java
@@ -0,0 +1,24 @@
+package org.synyx.urlaubsverwaltung.application.specialleave;
+
+
+import org.springframework.boot.context.event.ApplicationStartedEvent;
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Component;
+import org.synyx.urlaubsverwaltung.tenancy.configuration.single.ConditionalOnSingleTenantMode;
+
+@Component
+@ConditionalOnSingleTenantMode
+public class InitialDefaultSpecialLeaveSettingsConfigurerSingleTenant {
+
+    private final SpecialLeaveSettingsService specialLeaveSettingsService;
+
+    public InitialDefaultSpecialLeaveSettingsConfigurerSingleTenant(SpecialLeaveSettingsService specialLeaveSettingsService) {
+        this.specialLeaveSettingsService = specialLeaveSettingsService;
+    }
+
+    @EventListener(ApplicationStartedEvent.class)
+    void insertDefaultSpecialLeaveSettings() {
+        this.specialLeaveSettingsService.insertDefaultSpecialLeaveSettings();
+    }
+
+}
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/application/specialleave/SpecialLeaveSettingsEntity.java b/src/main/java/org/synyx/urlaubsverwaltung/application/specialleave/SpecialLeaveSettingsEntity.java
index aff3ff7a5..3e8e37afd 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/application/specialleave/SpecialLeaveSettingsEntity.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/application/specialleave/SpecialLeaveSettingsEntity.java
@@ -6,11 +6,12 @@ import jakarta.persistence.GeneratedValue;
 import jakarta.persistence.Id;
 import jakarta.persistence.SequenceGenerator;
 import jakarta.validation.constraints.NotNull;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.AbstractTenantAwareEntity;
 
 import static jakarta.persistence.GenerationType.SEQUENCE;
 
 @Entity(name = "special_leave_settings")
-class SpecialLeaveSettingsEntity {
+public class SpecialLeaveSettingsEntity extends AbstractTenantAwareEntity {
 
     @Id
     @Column(name = "id", unique = true, nullable = false, updatable = false)
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/application/specialleave/SpecialLeaveSettingsService.java b/src/main/java/org/synyx/urlaubsverwaltung/application/specialleave/SpecialLeaveSettingsService.java
index d60574c4a..3a4efd8fb 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/application/specialleave/SpecialLeaveSettingsService.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/application/specialleave/SpecialLeaveSettingsService.java
@@ -1,8 +1,6 @@
 package org.synyx.urlaubsverwaltung.application.specialleave;
 
 import org.slf4j.Logger;
-import org.springframework.boot.context.event.ApplicationStartedEvent;
-import org.springframework.context.event.EventListener;
 import org.springframework.data.domain.Sort;
 import org.springframework.stereotype.Component;
 
@@ -58,11 +56,9 @@ public class SpecialLeaveSettingsService {
             specialLeaveSettingsEntity.getDays());
     }
 
-    @EventListener(ApplicationStartedEvent.class)
-    void insertDefaultSpecialLeaveSettings() {
+    public void insertDefaultSpecialLeaveSettings() {
         final long count = specialLeaveSettingsRepository.count();
         if (count == 0) {
-
             final SpecialLeaveSettingsEntity ownWedding = createSpecialLeaveEntity(1, true, "application.data.specialleave.own_wedding");
             final SpecialLeaveSettingsEntity birthOfChild = createSpecialLeaveEntity(1, true, "application.data.specialleave.birth_of_child");
             final SpecialLeaveSettingsEntity deathOfChild = createSpecialLeaveEntity(2, true, "application.data.specialleave.death_of_child");
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/application/vacationtype/InitialDefaultVacationTypeConfigurerSingleTenant.java b/src/main/java/org/synyx/urlaubsverwaltung/application/vacationtype/InitialDefaultVacationTypeConfigurerSingleTenant.java
new file mode 100644
index 000000000..eb744b384
--- /dev/null
+++ b/src/main/java/org/synyx/urlaubsverwaltung/application/vacationtype/InitialDefaultVacationTypeConfigurerSingleTenant.java
@@ -0,0 +1,22 @@
+package org.synyx.urlaubsverwaltung.application.vacationtype;
+
+import org.springframework.boot.context.event.ApplicationStartedEvent;
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Component;
+import org.synyx.urlaubsverwaltung.tenancy.configuration.single.ConditionalOnSingleTenantMode;
+
+@Component
+@ConditionalOnSingleTenantMode
+class InitialDefaultVacationTypeConfigurerSingleTenant {
+
+    private final VacationTypeService vacationTypeService;
+
+    InitialDefaultVacationTypeConfigurerSingleTenant(VacationTypeService vacationTypeService) {
+        this.vacationTypeService = vacationTypeService;
+    }
+
+    @EventListener(ApplicationStartedEvent.class)
+    void insertDefaultVacationTypes() {
+        vacationTypeService.insertDefaultVacationTypes();
+    }
+}
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/application/vacationtype/VacationTypeEntity.java b/src/main/java/org/synyx/urlaubsverwaltung/application/vacationtype/VacationTypeEntity.java
index c2eb6841a..a6e808241 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/application/vacationtype/VacationTypeEntity.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/application/vacationtype/VacationTypeEntity.java
@@ -8,6 +8,7 @@ import jakarta.persistence.GeneratedValue;
 import jakarta.persistence.Id;
 import jakarta.persistence.SequenceGenerator;
 import jakarta.validation.constraints.NotNull;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.AbstractTenantAwareEntity;
 
 import java.util.Locale;
 import java.util.Map;
@@ -22,7 +23,7 @@ import static jakarta.persistence.GenerationType.SEQUENCE;
  * @since 2.15.0
  */
 @Entity(name = "vacation_type")
-public class VacationTypeEntity {
+public class VacationTypeEntity extends AbstractTenantAwareEntity {
 
     @Id
     @Column(name = "id", unique = true, nullable = false, updatable = false)
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/application/vacationtype/VacationTypeService.java b/src/main/java/org/synyx/urlaubsverwaltung/application/vacationtype/VacationTypeService.java
index 8b254b17f..9a4fabbf8 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/application/vacationtype/VacationTypeService.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/application/vacationtype/VacationTypeService.java
@@ -43,4 +43,6 @@ public interface VacationTypeService {
      * @param vacationTypes to create
      */
     void createVacationTypes(Collection<VacationType<?>> vacationTypes);
+
+    void insertDefaultVacationTypes();
 }
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/application/vacationtype/VacationTypeServiceImpl.java b/src/main/java/org/synyx/urlaubsverwaltung/application/vacationtype/VacationTypeServiceImpl.java
index 5ed2fa8b0..b46a4d4ad 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/application/vacationtype/VacationTypeServiceImpl.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/application/vacationtype/VacationTypeServiceImpl.java
@@ -2,10 +2,8 @@ package org.synyx.urlaubsverwaltung.application.vacationtype;
 
 import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.context.event.ApplicationStartedEvent;
 import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.context.MessageSource;
-import org.springframework.context.event.EventListener;
 import org.springframework.data.domain.Sort;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -145,44 +143,49 @@ public class VacationTypeServiceImpl implements VacationTypeService {
         }
     }
 
-    @EventListener(ApplicationStartedEvent.class)
-    void insertDefaultVacationTypes() {
+    @Override
+    public void insertDefaultVacationTypes() {
         final long count = vacationTypeRepository.count();
-        if (count == 0) {
 
-            final VacationTypeEntity holiday = createVacationTypeEntity(true, HOLIDAY, "application.data.vacationType.holiday", true, true, YELLOW, false);
-            final VacationTypeEntity specialleave = createVacationTypeEntity(true, SPECIALLEAVE, "application.data.vacationType.specialleave", true, true, YELLOW, false);
-            final VacationTypeEntity unpaidleave = createVacationTypeEntity(true, UNPAIDLEAVE, "application.data.vacationType.unpaidleave", true, true, YELLOW, false);
-            final VacationTypeEntity overtime = createVacationTypeEntity(true, OVERTIME, "application.data.vacationType.overtime", true, true, YELLOW, false);
-            final VacationTypeEntity parentalLeave = createVacationTypeEntity(false, OTHER, "application.data.vacationType.parentalLeave", true, true, YELLOW, false);
-            final VacationTypeEntity maternityProtection = createVacationTypeEntity(false, OTHER, "application.data.vacationType.maternityProtection", true, true, YELLOW, false);
-            final VacationTypeEntity sabbatical = createVacationTypeEntity(false, OTHER, "application.data.vacationType.sabbatical", true, true, YELLOW, false);
-            final VacationTypeEntity paidLeave = createVacationTypeEntity(false, OTHER, "application.data.vacationType.paidLeave", true, true, YELLOW, false);
-            final VacationTypeEntity cure = createVacationTypeEntity(false, OTHER, "application.data.vacationType.cure", true, true, YELLOW, false);
-            final VacationTypeEntity education = createVacationTypeEntity(false, OTHER, "application.data.vacationType.education", true, true, YELLOW, false);
-            final VacationTypeEntity homeOffice = createVacationTypeEntity(false, OTHER, "application.data.vacationType.homeOffice", true, true, YELLOW, false);
-            final VacationTypeEntity outOfOffice = createVacationTypeEntity(false, OTHER, "application.data.vacationType.outOfOffice", true, true, YELLOW, false);
-            final VacationTypeEntity training = createVacationTypeEntity(false, OTHER, "application.data.vacationType.training", true, true, YELLOW, false);
-            final VacationTypeEntity employmentBan = createVacationTypeEntity(false, OTHER, "application.data.vacationType.employmentBan", true, true, YELLOW, false);
-            final VacationTypeEntity educationalLeave = createVacationTypeEntity(false, OTHER, "application.data.vacationType.educationalLeave", true, true, YELLOW, false);
-
-            final List<VacationTypeEntity> vacationTypes = List.of(holiday, holiday, specialleave, unpaidleave, overtime, parentalLeave, maternityProtection, sabbatical, paidLeave, cure, education, homeOffice, outOfOffice, training, employmentBan, educationalLeave);
-            final List<VacationTypeEntity> savesVacationTypes = vacationTypeRepository.saveAll(vacationTypes);
-            LOG.info("Saved initial vacation types {}", savesVacationTypes);
+        if (count == 0) {
+            LOG.info("No initial vacation types exists - going to create them.");
+            final List<VacationType<?>> vacationTypes = getInitialVacationTypes();
+            createVacationTypes(vacationTypes);
+            LOG.info("Saved {} initial vacation types", vacationTypes.size());
         }
     }
 
-    private static VacationTypeEntity createVacationTypeEntity(boolean active, VacationCategory category, String messageKey, boolean requiresApprovalToApply, boolean requiresApprovalToCancel, VacationTypeColor color, boolean visibleToEveryone) {
-        final VacationTypeEntity vacationTypeEntity = new VacationTypeEntity();
-        vacationTypeEntity.setCustom(false);
-        vacationTypeEntity.setActive(active);
-        vacationTypeEntity.setCategory(category);
-        vacationTypeEntity.setMessageKey(messageKey);
-        vacationTypeEntity.setRequiresApprovalToApply(requiresApprovalToApply);
-        vacationTypeEntity.setRequiresApprovalToCancel(requiresApprovalToCancel);
-        vacationTypeEntity.setColor(color);
-        vacationTypeEntity.setVisibleToEveryone(visibleToEveryone);
-        return vacationTypeEntity;
+    private List<VacationType<?>> getInitialVacationTypes() {
+        final ProvidedVacationType holiday = createProvidedVacationType(true, HOLIDAY, "application.data.vacationType.holiday", true, true, YELLOW, false);
+        final ProvidedVacationType specialleave = createProvidedVacationType(true, SPECIALLEAVE, "application.data.vacationType.specialleave", true, true, YELLOW, false);
+        final ProvidedVacationType unpaidleave = createProvidedVacationType(true, UNPAIDLEAVE, "application.data.vacationType.unpaidleave", true, true, YELLOW, false);
+        final ProvidedVacationType overtime = createProvidedVacationType(true, OVERTIME, "application.data.vacationType.overtime", true, true, YELLOW, false);
+        final ProvidedVacationType parentalLeave = createProvidedVacationType(false, OTHER, "application.data.vacationType.parentalLeave", true, true, YELLOW, false);
+        final ProvidedVacationType maternityProtection = createProvidedVacationType(false, OTHER, "application.data.vacationType.maternityProtection", true, true, YELLOW, false);
+        final ProvidedVacationType sabbatical = createProvidedVacationType(false, OTHER, "application.data.vacationType.sabbatical", true, true, YELLOW, false);
+        final ProvidedVacationType paidLeave = createProvidedVacationType(false, OTHER, "application.data.vacationType.paidLeave", true, true, YELLOW, false);
+        final ProvidedVacationType cure = createProvidedVacationType(false, OTHER, "application.data.vacationType.cure", true, true, YELLOW, false);
+        final ProvidedVacationType education = createProvidedVacationType(false, OTHER, "application.data.vacationType.education", true, true, YELLOW, false);
+        final ProvidedVacationType homeOffice = createProvidedVacationType(false, OTHER, "application.data.vacationType.homeOffice", true, true, YELLOW, false);
+        final ProvidedVacationType outOfOffice = createProvidedVacationType(false, OTHER, "application.data.vacationType.outOfOffice", true, true, YELLOW, false);
+        final ProvidedVacationType training = createProvidedVacationType(false, OTHER, "application.data.vacationType.training", true, true, YELLOW, false);
+        final ProvidedVacationType employmentBan = createProvidedVacationType(false, OTHER, "application.data.vacationType.employmentBan", true, true, YELLOW, false);
+        final ProvidedVacationType educationalLeave = createProvidedVacationType(false, OTHER, "application.data.vacationType.educationalLeave", true, true, YELLOW, false);
+
+        return List.of(holiday, specialleave, unpaidleave, overtime, parentalLeave, maternityProtection, sabbatical, paidLeave, cure, education, homeOffice, outOfOffice, training, employmentBan, educationalLeave);
+    }
+
+    private ProvidedVacationType createProvidedVacationType(boolean active, VacationCategory category, String messageKey, boolean requiresApprovalToApply, boolean requiresApprovalToCancel, VacationTypeColor color, boolean visibleToEveryone) {
+        return ProvidedVacationType.builder(messageSource)
+            .id(null)
+            .active(active)
+            .category(category)
+            .messageKey(messageKey)
+            .requiresApprovalToApply(requiresApprovalToApply)
+            .requiresApprovalToCancel(requiresApprovalToCancel)
+            .color(color)
+            .visibleToEveryone(visibleToEveryone)
+            .build();
     }
 
     private static CustomVacationType updateCustomVacationType(CustomVacationType customVacationType, VacationTypeUpdate vacationTypeUpdate) {
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/calendar/CalendarAccessible.java b/src/main/java/org/synyx/urlaubsverwaltung/calendar/CalendarAccessible.java
index 590e28c19..e4fd60975 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/calendar/CalendarAccessible.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/calendar/CalendarAccessible.java
@@ -6,12 +6,13 @@ import jakarta.persistence.GeneratedValue;
 import jakarta.persistence.Id;
 import jakarta.persistence.Inheritance;
 import jakarta.persistence.SequenceGenerator;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.AbstractTenantAwareEntity;
 
 import static jakarta.persistence.GenerationType.SEQUENCE;
 
 @Entity
 @Inheritance
-abstract class CalendarAccessible {
+public abstract class CalendarAccessible extends AbstractTenantAwareEntity {
 
     @Id
     @Column(name = "id", unique = true, nullable = false, updatable = false)
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/calendar/CompanyCalendar.java b/src/main/java/org/synyx/urlaubsverwaltung/calendar/CompanyCalendar.java
index 43bf6c666..643bd5a0d 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/calendar/CompanyCalendar.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/calendar/CompanyCalendar.java
@@ -11,13 +11,14 @@ import jakarta.validation.constraints.NotNull;
 import org.apache.commons.lang3.RandomStringUtils;
 import org.hibernate.validator.constraints.Length;
 import org.synyx.urlaubsverwaltung.person.Person;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.AbstractTenantAwareEntity;
 
 import java.time.Period;
 
 import static jakarta.persistence.GenerationType.SEQUENCE;
 
 @Entity
-class CompanyCalendar {
+public class CompanyCalendar extends AbstractTenantAwareEntity {
 
     private static final int SECRET_LENGTH = 32;
 
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/calendar/CompanyCalendarAccessible.java b/src/main/java/org/synyx/urlaubsverwaltung/calendar/CompanyCalendarAccessible.java
index ed6760b5d..be98efea4 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/calendar/CompanyCalendarAccessible.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/calendar/CompanyCalendarAccessible.java
@@ -3,5 +3,5 @@ package org.synyx.urlaubsverwaltung.calendar;
 import jakarta.persistence.Entity;
 
 @Entity
-class CompanyCalendarAccessible extends CalendarAccessible {
+public class CompanyCalendarAccessible extends CalendarAccessible {
 }
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/calendar/DepartmentCalendar.java b/src/main/java/org/synyx/urlaubsverwaltung/calendar/DepartmentCalendar.java
index 44b7eafed..cd8aba75e 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/calendar/DepartmentCalendar.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/calendar/DepartmentCalendar.java
@@ -12,6 +12,7 @@ import org.apache.commons.lang3.RandomStringUtils;
 import org.hibernate.annotations.OnDelete;
 import org.hibernate.validator.constraints.Length;
 import org.synyx.urlaubsverwaltung.person.Person;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.AbstractTenantAwareEntity;
 
 import java.time.Period;
 
@@ -19,7 +20,7 @@ import static jakarta.persistence.GenerationType.SEQUENCE;
 import static org.hibernate.annotations.OnDeleteAction.CASCADE;
 
 @Entity
-class DepartmentCalendar {
+public class DepartmentCalendar extends AbstractTenantAwareEntity {
 
     private static final int SECRET_LENGTH = 32;
 
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/calendar/PersonCalendar.java b/src/main/java/org/synyx/urlaubsverwaltung/calendar/PersonCalendar.java
index 5463b1aa5..56c5bee62 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/calendar/PersonCalendar.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/calendar/PersonCalendar.java
@@ -11,13 +11,14 @@ import jakarta.validation.constraints.NotNull;
 import org.apache.commons.lang3.RandomStringUtils;
 import org.hibernate.validator.constraints.Length;
 import org.synyx.urlaubsverwaltung.person.Person;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.AbstractTenantAwareEntity;
 
 import java.time.Period;
 
 import static jakarta.persistence.GenerationType.SEQUENCE;
 
 @Entity
-class PersonCalendar {
+public class PersonCalendar extends AbstractTenantAwareEntity {
 
     private static final int SECRET_LENGTH = 32;
 
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/AbsenceMapping.java b/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/AbsenceMapping.java
index 3ac801e98..61788f1f3 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/AbsenceMapping.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/AbsenceMapping.java
@@ -6,6 +6,7 @@ import jakarta.persistence.Enumerated;
 import jakarta.persistence.GeneratedValue;
 import jakarta.persistence.Id;
 import jakarta.persistence.SequenceGenerator;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.AbstractTenantAwareEntity;
 
 import java.util.Objects;
 
@@ -16,7 +17,7 @@ import static jakarta.persistence.GenerationType.SEQUENCE;
  * Mapping object between absence (application for leave or sick note) and sync calendar event.
  */
 @Entity
-public class AbsenceMapping {
+public class AbsenceMapping extends AbstractTenantAwareEntity {
 
     @Id
     @Column(name = "id", unique = true, nullable = false, updatable = false)
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/CalendarSettings.java b/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/CalendarSettings.java
index ddf925219..4271eb798 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/CalendarSettings.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/CalendarSettings.java
@@ -5,12 +5,13 @@ import jakarta.persistence.Entity;
 import jakarta.persistence.GeneratedValue;
 import jakarta.persistence.Id;
 import jakarta.persistence.SequenceGenerator;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.AbstractTenantAwareEntity;
 
 import static jakarta.persistence.GenerationType.SEQUENCE;
 
 
 @Entity(name = "calendar_integration_settings")
-public class CalendarSettings {
+public class CalendarSettings extends AbstractTenantAwareEntity {
 
     @Id
     @Column(name = "id", unique = true, nullable = false, updatable = false)
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/CalendarSettingsRepository.java b/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/CalendarSettingsRepository.java
index a96c034bc..d1cb87fc7 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/CalendarSettingsRepository.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/CalendarSettingsRepository.java
@@ -2,5 +2,8 @@ package org.synyx.urlaubsverwaltung.calendarintegration;
 
 import org.springframework.data.repository.CrudRepository;
 
+import java.util.List;
+
 interface CalendarSettingsRepository extends CrudRepository<CalendarSettings, Long> {
+    List<CalendarSettings> findAll();
 }
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/CalendarSettingsService.java b/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/CalendarSettingsService.java
index 4f4bcda56..6e6b002b1 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/CalendarSettingsService.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/CalendarSettingsService.java
@@ -8,7 +8,7 @@ import static java.lang.invoke.MethodHandles.lookup;
 import static org.slf4j.LoggerFactory.getLogger;
 
 @Service
-class CalendarSettingsService {
+public class CalendarSettingsService {
 
     private static final Logger LOG = getLogger(lookup().lookupClass());
 
@@ -19,20 +19,25 @@ class CalendarSettingsService {
         this.calendarSettingsRepository = calendarSettingsRepository;
     }
 
-    CalendarSettings save(CalendarSettings settings) {
+    public CalendarSettings save(CalendarSettings settings) {
         final CalendarSettings savedSettings = calendarSettingsRepository.save(settings);
         LOG.info("Updated settings: {}", savedSettings);
         return savedSettings;
     }
 
-    CalendarSettings getCalendarSettings() {
-        return calendarSettingsRepository.findById(1L)
-            .orElseGet(() -> {
-                final CalendarSettings settings = new CalendarSettings();
-                settings.setId(1L);
-                final CalendarSettings savedSettings = calendarSettingsRepository.save(settings);
-                LOG.info("Saved initial calendar settings {}", savedSettings);
-                return savedSettings;
-            });
+    public CalendarSettings getCalendarSettings() {
+        return calendarSettingsRepository.findAll().stream().findFirst()
+            .orElseThrow(() -> new IllegalStateException("No calendar settings found in database!"));
+    }
+
+    public void insertDefaultCalendarSettings() {
+
+        final long count = calendarSettingsRepository.count();
+
+        if (count == 0) {
+            final CalendarSettings settings = new CalendarSettings();
+            final CalendarSettings savedSettings = calendarSettingsRepository.save(settings);
+            LOG.info("Saved initial calendar settings {}", savedSettings);
+        }
     }
 }
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/CalendarSyncService.java b/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/CalendarSyncService.java
index e3bbfff1f..b3aca2b2f 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/CalendarSyncService.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/CalendarSyncService.java
@@ -1,6 +1,5 @@
 package org.synyx.urlaubsverwaltung.calendarintegration;
 
-import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.event.EventListener;
 import org.springframework.scheduling.annotation.Async;
@@ -26,16 +25,12 @@ import org.synyx.urlaubsverwaltung.sicknote.sicknote.SickNoteUpdatedEvent;
 
 import java.util.Optional;
 
-import static java.lang.invoke.MethodHandles.lookup;
-import static org.slf4j.LoggerFactory.getLogger;
 import static org.synyx.urlaubsverwaltung.calendarintegration.AbsenceMappingType.SICKNOTE;
 import static org.synyx.urlaubsverwaltung.calendarintegration.AbsenceMappingType.VACATION;
 
 @Service
 class CalendarSyncService {
 
-    private static final Logger LOG = getLogger(lookup().lookupClass());
-
     private final SettingsService settingsService;
     private final CalendarSettingsService calendarSettingsService;
     private final CalendarProviderService calendarProviderService;
@@ -52,7 +47,6 @@ class CalendarSyncService {
         this.calendarSettingsService = calendarSettingsService;
         this.calendarProviderService = calendarProviderService;
         this.absenceMappingRepository = absenceMappingRepository;
-        LOG.debug("The following calendar provider is configured: {}", calendarProviderService.getCalendarProvider().getClass());
     }
 
     @Async
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/GoogleApiConfiguration.java b/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/GoogleApiConfiguration.java
new file mode 100644
index 000000000..93a2f6491
--- /dev/null
+++ b/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/GoogleApiConfiguration.java
@@ -0,0 +1,19 @@
+package org.synyx.urlaubsverwaltung.calendarintegration;
+
+import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
+import com.google.api.client.json.gson.GsonFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+
+@Configuration
+public class GoogleApiConfiguration {
+
+    @Bean
+    GoogleAuthorizationCodeFlowFactory googleAuthorizationCodeFlowFactory() throws GeneralSecurityException, IOException {
+        return new GoogleAuthorizationCodeFlowFactory(GsonFactory.getDefaultInstance(), GoogleNetHttpTransport.newTrustedTransport());
+    }
+
+}
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/GoogleAuthorizationCodeFlowFactory.java b/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/GoogleAuthorizationCodeFlowFactory.java
new file mode 100644
index 000000000..9f18800f3
--- /dev/null
+++ b/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/GoogleAuthorizationCodeFlowFactory.java
@@ -0,0 +1,41 @@
+package org.synyx.urlaubsverwaltung.calendarintegration;
+
+import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
+import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
+import com.google.api.client.http.javanet.NetHttpTransport;
+import com.google.api.client.json.JsonFactory;
+import com.google.api.services.calendar.CalendarScopes;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.util.Collections;
+
+public class GoogleAuthorizationCodeFlowFactory {
+
+    private final JsonFactory jsonFactory;
+    private final NetHttpTransport netHttpTransport;
+
+    GoogleAuthorizationCodeFlowFactory(JsonFactory jsonFactory, NetHttpTransport netHttpTransport) {
+        this.jsonFactory = jsonFactory;
+        this.netHttpTransport = netHttpTransport;
+    }
+
+    public GoogleAuthorizationCodeFlow create(String clientId, String clientSecret) throws GeneralSecurityException, IOException {
+
+        final GoogleClientSecrets.Details web = new GoogleClientSecrets.Details();
+        web.setClientId(clientId);
+        web.setClientSecret(clientSecret);
+
+        final GoogleClientSecrets clientSecrets = new GoogleClientSecrets();
+
+        clientSecrets.setWeb(web);
+
+        return new GoogleAuthorizationCodeFlow.Builder(netHttpTransport, jsonFactory, clientSecrets,
+            Collections.singleton(CalendarScopes.CALENDAR))
+            .setApprovalPrompt("force")
+            .setAccessType("offline")
+            .build();
+
+
+    }
+}
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/GoogleCalendarClientProvider.java b/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/GoogleCalendarClientProvider.java
index 818bbc658..4d2d239d5 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/GoogleCalendarClientProvider.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/GoogleCalendarClientProvider.java
@@ -29,8 +29,6 @@ class GoogleCalendarClientProvider {
     private static final String APPLICATION_NAME = "Urlaubsverwaltung";
     private static final String GOOGLEAPIS_OAUTH2_V4_TOKEN = "https://www.googleapis.com/oauth2/v4/token";
 
-    private Optional<Calendar> maybeCalendarClient = Optional.empty();
-    private int refreshTokenHashCode;
 
     /**
      * Build and return an authorized google calendar client.
@@ -38,13 +36,7 @@ class GoogleCalendarClientProvider {
      * @return an authorized calendar client service
      */
     Optional<Calendar> getCalendarClient(GoogleCalendarSettings googleCalendarSettings) {
-
-        final String refreshToken = googleCalendarSettings.getRefreshToken();
-        if (maybeCalendarClient.isEmpty() || refreshToken == null || refreshTokenHashCode != refreshToken.hashCode()) {
-            maybeCalendarClient = createCalendarClient(googleCalendarSettings);
-        }
-
-        return maybeCalendarClient;
+        return createCalendarClient(googleCalendarSettings);
     }
 
     private Optional<Calendar> createCalendarClient(GoogleCalendarSettings googleCalendarSettings) {
@@ -55,9 +47,6 @@ class GoogleCalendarClientProvider {
         }
 
         final String refreshToken = googleCalendarSettings.getRefreshToken();
-        if (refreshToken != null) {
-            refreshTokenHashCode = refreshToken.hashCode();
-        }
 
         final TokenResponse tokenResponse = new TokenResponse();
         tokenResponse.setRefreshToken(refreshToken);
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/GoogleCalendarOAuthHandshakeViewController.java b/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/GoogleCalendarOAuthHandshakeViewController.java
index a901f64c1..d04cd3514 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/GoogleCalendarOAuthHandshakeViewController.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/GoogleCalendarOAuthHandshakeViewController.java
@@ -4,15 +4,12 @@ import com.google.api.client.auth.oauth2.AuthorizationCodeRequestUrl;
 import com.google.api.client.auth.oauth2.Credential;
 import com.google.api.client.auth.oauth2.TokenResponse;
 import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
-import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
-import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets.Details;
 import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
 import com.google.api.client.http.HttpResponse;
 import com.google.api.client.http.HttpTransport;
 import com.google.api.client.json.JsonFactory;
 import com.google.api.client.json.gson.GsonFactory;
 import com.google.api.services.calendar.Calendar;
-import com.google.api.services.calendar.CalendarScopes;
 import jakarta.servlet.http.HttpServletRequest;
 import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -24,7 +21,6 @@ import org.springframework.web.bind.annotation.RequestParam;
 
 import java.io.IOException;
 import java.security.GeneralSecurityException;
-import java.util.Collections;
 
 import static java.lang.invoke.MethodHandles.lookup;
 import static org.apache.http.HttpStatus.SC_OK;
@@ -43,31 +39,42 @@ public class GoogleCalendarOAuthHandshakeViewController {
 
     private final CalendarSettingsService calendarSettingsService;
     private final CalendarSyncService calendarSyncService;
-
-    private GoogleAuthorizationCodeFlow flow;
+    private final GoogleAuthorizationCodeFlowFactory googleAuthorizationCodeFlowFactory;
 
     @Autowired
     GoogleCalendarOAuthHandshakeViewController(
         CalendarSettingsService calendarSettingsService,
-        CalendarSyncService calendarSyncService
+        CalendarSyncService calendarSyncService,
+        GoogleAuthorizationCodeFlowFactory googleAuthorizationCodeFlowFactory
     ) throws GeneralSecurityException, IOException {
 
         this.calendarSettingsService = calendarSettingsService;
         this.calendarSyncService = calendarSyncService;
+        this.googleAuthorizationCodeFlowFactory = googleAuthorizationCodeFlowFactory;
+
         httpTransport = GoogleNetHttpTransport.newTrustedTransport();
     }
 
+    private static HttpResponse checkGoogleCalendar(Calendar client, CalendarSettings calendarSettings) throws IOException {
+        final String calendarId = calendarSettings.getGoogleCalendarSettings().getCalendarId();
+        return client.calendars()
+            .get(calendarId)
+            .buildHttpRequestUsingHead().execute();
+    }
+
     @PreAuthorize(IS_OFFICE)
     @GetMapping("/google-api-handshake")
-    public String googleConnectionStatus(HttpServletRequest request) {
+    public String googleConnectionStatus(HttpServletRequest request) throws GeneralSecurityException, IOException {
         return "redirect:" + authorize(request.getRequestURL().toString());
     }
 
     @PreAuthorize(IS_OFFICE)
     @GetMapping(value = "/google-api-handshake", params = "code")
-    public String oauth2Callback(@RequestParam(value = "code") String code, HttpServletRequest request) {
+    public String oauth2Callback(@RequestParam(value = "code") String code, HttpServletRequest request) throws GeneralSecurityException, IOException {
+
+        final String redirectUrl = request.getRequestURL().toString();
 
-        String redirectUrl = request.getRequestURL().toString();
+        final GoogleAuthorizationCodeFlow flow = createGoogleAuthorizationCodeFlow();
 
         try {
             final TokenResponse response = flow.newTokenRequest(code).setRedirectUri(redirectUrl).execute();
@@ -101,34 +108,19 @@ public class GoogleCalendarOAuthHandshakeViewController {
         return "redirect:/web/settings/calendar-sync";
     }
 
-    private static HttpResponse checkGoogleCalendar(Calendar client, CalendarSettings calendarSettings) throws IOException {
-        final String calendarId = calendarSettings.getGoogleCalendarSettings().getCalendarId();
-        return client.calendars()
-            .get(calendarId)
-            .buildHttpRequestUsingHead().execute();
-    }
-
-    private String authorize(String redirectUri) {
-
-        final GoogleCalendarSettings googleCalendarSettings = calendarSettingsService.getCalendarSettings().getGoogleCalendarSettings();
+    private String authorize(String redirectUri) throws GeneralSecurityException, IOException {
 
-        final Details web = new Details();
-        web.setClientId(googleCalendarSettings.getClientId());
-        web.setClientSecret(googleCalendarSettings.getClientSecret());
+        final AuthorizationCodeRequestUrl authorizationUrl = createGoogleAuthorizationCodeFlow()
+            .newAuthorizationUrl()
+            .setRedirectUri(redirectUri);
 
-        final GoogleClientSecrets clientSecrets = new GoogleClientSecrets();
-
-        clientSecrets.setWeb(web);
-
-        flow = new GoogleAuthorizationCodeFlow.Builder(httpTransport, JSON_FACTORY, clientSecrets,
-            Collections.singleton(CalendarScopes.CALENDAR))
-            .setApprovalPrompt("force")
-            .setAccessType("offline")
-            .build();
-
-        final AuthorizationCodeRequestUrl authorizationUrl = flow.newAuthorizationUrl().setRedirectUri(redirectUri);
         LOG.info("using authorizationUrl {}", authorizationUrl);
 
         return authorizationUrl.build();
     }
+
+    private GoogleAuthorizationCodeFlow createGoogleAuthorizationCodeFlow() throws GeneralSecurityException, IOException {
+        final GoogleCalendarSettings googleCalendarSettings = calendarSettingsService.getCalendarSettings().getGoogleCalendarSettings();
+        return googleAuthorizationCodeFlowFactory.create(googleCalendarSettings.getClientId(), googleCalendarSettings.getClientSecret());
+    }
 }
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/GoogleCalendarSyncProvider.java b/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/GoogleCalendarSyncProvider.java
index 1bb29605f..0cb901978 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/GoogleCalendarSyncProvider.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/GoogleCalendarSyncProvider.java
@@ -30,8 +30,6 @@ public class GoogleCalendarSyncProvider implements CalendarProvider {
 
     private final GoogleCalendarClientProvider googleCalendarClientProvider;
 
-    private Optional<Calendar> maybeCalendarClient;
-
     @Autowired
     GoogleCalendarSyncProvider(GoogleCalendarClientProvider googleCalendarClientProvider) {
         this.googleCalendarClientProvider = googleCalendarClientProvider;
@@ -41,7 +39,7 @@ public class GoogleCalendarSyncProvider implements CalendarProvider {
     public Optional<String> add(Absence absence, CalendarSettings calendarSettings) {
 
         final GoogleCalendarSettings googleCalendarSettings = calendarSettings.getGoogleCalendarSettings();
-        maybeCalendarClient = googleCalendarClientProvider.getCalendarClient(googleCalendarSettings);
+        final Optional<Calendar> maybeCalendarClient = googleCalendarClientProvider.getCalendarClient(googleCalendarSettings);
 
         if (maybeCalendarClient.isPresent()) {
             final String calendarId = googleCalendarSettings.getCalendarId();
@@ -67,7 +65,7 @@ public class GoogleCalendarSyncProvider implements CalendarProvider {
     public void update(Absence absence, String eventId, CalendarSettings calendarSettings) {
 
         final GoogleCalendarSettings googleCalendarSettings = calendarSettings.getGoogleCalendarSettings();
-        maybeCalendarClient = googleCalendarClientProvider.getCalendarClient(googleCalendarSettings);
+        final Optional<Calendar> maybeCalendarClient = googleCalendarClientProvider.getCalendarClient(googleCalendarSettings);
 
         if (maybeCalendarClient.isPresent()) {
             final String calendarId = googleCalendarSettings.getCalendarId();
@@ -94,7 +92,7 @@ public class GoogleCalendarSyncProvider implements CalendarProvider {
     public Optional<String> delete(String eventId, CalendarSettings calendarSettings) {
 
         final GoogleCalendarSettings googleCalendarSettings = calendarSettings.getGoogleCalendarSettings();
-        maybeCalendarClient = googleCalendarClientProvider.getCalendarClient(googleCalendarSettings);
+        final Optional<Calendar> maybeCalendarClient = googleCalendarClientProvider.getCalendarClient(googleCalendarSettings);
 
         if (maybeCalendarClient.isPresent()) {
             final String calendarId = googleCalendarSettings.getCalendarId();
@@ -114,7 +112,7 @@ public class GoogleCalendarSyncProvider implements CalendarProvider {
     public void checkCalendarSyncSettings(CalendarSettings calendarSettings) {
 
         final GoogleCalendarSettings googleCalendarSettings = calendarSettings.getGoogleCalendarSettings();
-        maybeCalendarClient = googleCalendarClientProvider.getCalendarClient(googleCalendarSettings);
+        final Optional<Calendar> maybeCalendarClient = googleCalendarClientProvider.getCalendarClient(googleCalendarSettings);
 
         if (maybeCalendarClient.isPresent()) {
             final String calendarId = googleCalendarSettings.getCalendarId();
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/InitialDefaultCalendarSettingsConfigurerSingleTenant.java b/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/InitialDefaultCalendarSettingsConfigurerSingleTenant.java
new file mode 100644
index 000000000..1e0d0bc0e
--- /dev/null
+++ b/src/main/java/org/synyx/urlaubsverwaltung/calendarintegration/InitialDefaultCalendarSettingsConfigurerSingleTenant.java
@@ -0,0 +1,24 @@
+package org.synyx.urlaubsverwaltung.calendarintegration;
+
+
+import org.springframework.boot.context.event.ApplicationStartedEvent;
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Component;
+import org.synyx.urlaubsverwaltung.tenancy.configuration.single.ConditionalOnSingleTenantMode;
+
+@Component
+@ConditionalOnSingleTenantMode
+class InitialDefaultCalendarSettingsConfigurerSingleTenant {
+
+
+    private final CalendarSettingsService settingsService;
+
+    InitialDefaultCalendarSettingsConfigurerSingleTenant(CalendarSettingsService settingsService) {
+        this.settingsService = settingsService;
+    }
+
+    @EventListener(ApplicationStartedEvent.class)
+    void insertDefaultSettings() {
+        settingsService.insertDefaultCalendarSettings();
+    }
+}
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/comment/AbstractComment.java b/src/main/java/org/synyx/urlaubsverwaltung/comment/AbstractComment.java
index 0bca1c00f..0a615bef8 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/comment/AbstractComment.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/comment/AbstractComment.java
@@ -4,6 +4,7 @@ import jakarta.persistence.Column;
 import jakarta.persistence.ManyToOne;
 import jakarta.persistence.MappedSuperclass;
 import org.synyx.urlaubsverwaltung.person.Person;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.AbstractTenantAwareEntity;
 
 import java.time.Clock;
 import java.time.Instant;
@@ -16,7 +17,7 @@ import static java.util.Optional.ofNullable;
  * Represents a basic comment.
  */
 @MappedSuperclass
-public abstract class AbstractComment {
+public abstract class AbstractComment extends AbstractTenantAwareEntity {
 
     // Who has written the comment?
     @ManyToOne
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/department/DepartmentEntity.java b/src/main/java/org/synyx/urlaubsverwaltung/department/DepartmentEntity.java
index 24a2f7ea3..19c33a0dd 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/department/DepartmentEntity.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/department/DepartmentEntity.java
@@ -11,6 +11,7 @@ import jakarta.persistence.OneToMany;
 import jakarta.persistence.SequenceGenerator;
 import jakarta.validation.constraints.NotNull;
 import org.synyx.urlaubsverwaltung.person.Person;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.AbstractTenantAwareEntity;
 
 import java.time.LocalDate;
 import java.util.ArrayList;
@@ -22,7 +23,7 @@ import static jakarta.persistence.GenerationType.SEQUENCE;
 import static java.time.ZoneOffset.UTC;
 
 @Entity(name = "department")
-class DepartmentEntity {
+public class DepartmentEntity extends AbstractTenantAwareEntity {
 
     @Id
     @Column(name = "id", unique = true, nullable = false, updatable = false)
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/extension/application/ApplicationEventRepublisher.java b/src/main/java/org/synyx/urlaubsverwaltung/extension/application/ApplicationEventRepublisher.java
index 7cf0784e3..0a8377474 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/extension/application/ApplicationEventRepublisher.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/extension/application/ApplicationEventRepublisher.java
@@ -9,6 +9,7 @@ import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Component;
 import org.synyx.urlaubsverwaltung.application.application.ApplicationAllowedEvent;
 import org.synyx.urlaubsverwaltung.application.application.ApplicationService;
+import org.synyx.urlaubsverwaltung.tenancy.configuration.single.ConditionalOnSingleTenantMode;
 
 import java.time.Clock;
 import java.time.LocalDate;
@@ -21,6 +22,7 @@ import static org.synyx.urlaubsverwaltung.application.application.ApplicationSta
 @Component
 @ConditionalOnProperty(value = "uv.extensions.application.republish.enabled", havingValue = "true")
 @ConditionalOnBean(ApplicationEventHandlerExtension.class)
+@ConditionalOnSingleTenantMode
 public class ApplicationEventRepublisher {
 
     private static final Logger LOG = getLogger(lookup().lookupClass());
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/extension/sicknote/SickNoteEventRepublisher.java b/src/main/java/org/synyx/urlaubsverwaltung/extension/sicknote/SickNoteEventRepublisher.java
index 5fe0f09a8..2bf4f4995 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/extension/sicknote/SickNoteEventRepublisher.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/extension/sicknote/SickNoteEventRepublisher.java
@@ -9,6 +9,7 @@ import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Component;
 import org.synyx.urlaubsverwaltung.sicknote.sicknote.SickNoteCreatedEvent;
 import org.synyx.urlaubsverwaltung.sicknote.sicknote.SickNoteService;
+import org.synyx.urlaubsverwaltung.tenancy.configuration.single.ConditionalOnSingleTenantMode;
 
 import java.time.Clock;
 import java.time.LocalDate;
@@ -20,6 +21,7 @@ import static org.slf4j.LoggerFactory.getLogger;
 @Component
 @ConditionalOnProperty(value = "uv.extensions.sicknote.republish.enabled", havingValue = "true")
 @ConditionalOnBean(SickNoteEventHandlerExtension.class)
+@ConditionalOnSingleTenantMode
 public class SickNoteEventRepublisher {
 
     private static final Logger LOG = getLogger(lookup().lookupClass());
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/extension/tenancy/TenancyConfiguration.java b/src/main/java/org/synyx/urlaubsverwaltung/extension/tenancy/TenancyConfiguration.java
index 79b70a804..8c055f3d8 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/extension/tenancy/TenancyConfiguration.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/extension/tenancy/TenancyConfiguration.java
@@ -6,9 +6,11 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.synyx.urlaubsverwaltung.tenancy.configuration.single.ConditionalOnSingleTenantMode;
 
 @Configuration
 @ConditionalOnProperty(value = "uv.extensions.enabled", havingValue = "true")
+@ConditionalOnSingleTenantMode
 @EnableConfigurationProperties(TenancyConfigurationProperties.class)
 public class TenancyConfiguration {
 
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/extension/vacationtype/VacationTypeEventRepublisher.java b/src/main/java/org/synyx/urlaubsverwaltung/extension/vacationtype/VacationTypeEventRepublisher.java
index 7d6802ac9..17df1eac1 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/extension/vacationtype/VacationTypeEventRepublisher.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/extension/vacationtype/VacationTypeEventRepublisher.java
@@ -10,6 +10,7 @@ import org.springframework.stereotype.Component;
 import org.synyx.urlaubsverwaltung.application.vacationtype.VacationType;
 import org.synyx.urlaubsverwaltung.application.vacationtype.VacationTypeService;
 import org.synyx.urlaubsverwaltung.application.vacationtype.VacationTypeUpdatedEvent;
+import org.synyx.urlaubsverwaltung.tenancy.configuration.single.ConditionalOnSingleTenantMode;
 
 import static java.lang.invoke.MethodHandles.lookup;
 import static org.slf4j.LoggerFactory.getLogger;
@@ -17,6 +18,7 @@ import static org.slf4j.LoggerFactory.getLogger;
 @Component
 @ConditionalOnProperty(value = "uv.extensions.vacationtype.republish.enabled", havingValue = "true")
 @ConditionalOnBean(VacationTypeEventHandlerExtension.class)
+@ConditionalOnSingleTenantMode
 class VacationTypeEventRepublisher {
 
     private static final Logger LOG = getLogger(lookup().lookupClass());
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/notification/UserNotificationSettingsEntity.java b/src/main/java/org/synyx/urlaubsverwaltung/notification/UserNotificationSettingsEntity.java
index 4fc1b788b..9e522eab0 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/notification/UserNotificationSettingsEntity.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/notification/UserNotificationSettingsEntity.java
@@ -3,12 +3,13 @@ package org.synyx.urlaubsverwaltung.notification;
 import jakarta.persistence.Entity;
 import jakarta.persistence.Id;
 import jakarta.persistence.Table;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.AbstractTenantAwareEntity;
 
 import java.util.Objects;
 
 @Entity
 @Table(name = "user_notification_settings")
-class UserNotificationSettingsEntity {
+public class UserNotificationSettingsEntity extends AbstractTenantAwareEntity {
 
     @Id
     private Long personId;
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/overtime/Overtime.java b/src/main/java/org/synyx/urlaubsverwaltung/overtime/Overtime.java
index 4e1806e08..743f22b69 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/overtime/Overtime.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/overtime/Overtime.java
@@ -10,6 +10,7 @@ import jakarta.persistence.SequenceGenerator;
 import org.synyx.urlaubsverwaltung.DurationConverter;
 import org.synyx.urlaubsverwaltung.absence.DateRange;
 import org.synyx.urlaubsverwaltung.person.Person;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.AbstractTenantAwareEntity;
 import org.synyx.urlaubsverwaltung.util.DecimalConverter;
 
 import java.math.BigDecimal;
@@ -33,7 +34,7 @@ import static org.synyx.urlaubsverwaltung.util.DecimalConverter.toFormattedDecim
  * @since 2.11.0
  */
 @Entity
-public class Overtime {
+public class Overtime extends AbstractTenantAwareEntity {
 
     @Id
     @Column(name = "id", unique = true, nullable = false, updatable = false)
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/person/Person.java b/src/main/java/org/synyx/urlaubsverwaltung/person/Person.java
index 40fa3584d..bede70a39 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/person/Person.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/person/Person.java
@@ -7,6 +7,7 @@ import jakarta.persistence.Enumerated;
 import jakarta.persistence.GeneratedValue;
 import jakarta.persistence.Id;
 import jakarta.persistence.SequenceGenerator;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.AbstractTenantAwareEntity;
 
 import java.util.Collection;
 import java.util.Objects;
@@ -25,7 +26,7 @@ import static org.synyx.urlaubsverwaltung.person.Role.privilegedRoles;
  * This class describes a person.
  */
 @Entity
-public class Person {
+public class Person extends AbstractTenantAwareEntity {
 
     @Id
     @Column(name = "id", unique = true, nullable = false, updatable = false)
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/person/basedata/PersonBasedataEntity.java b/src/main/java/org/synyx/urlaubsverwaltung/person/basedata/PersonBasedataEntity.java
index 393e62f49..8b0bf0078 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/person/basedata/PersonBasedataEntity.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/person/basedata/PersonBasedataEntity.java
@@ -9,13 +9,14 @@ import jakarta.persistence.Table;
 import jakarta.validation.constraints.Size;
 import org.hibernate.annotations.OnDelete;
 import org.synyx.urlaubsverwaltung.person.Person;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.AbstractTenantAwareEntity;
 
 import static jakarta.persistence.FetchType.LAZY;
 import static org.hibernate.annotations.OnDeleteAction.CASCADE;
 
 @Entity
 @Table(name = "person_basedata")
-class PersonBasedataEntity {
+public class PersonBasedataEntity extends AbstractTenantAwareEntity {
 
     @Id
     @Column(name = "person_id")
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/person/extension/PersonDTOMapper.java b/src/main/java/org/synyx/urlaubsverwaltung/person/extension/PersonDTOMapper.java
index b78d52dd0..ba10d22aa 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/person/extension/PersonDTOMapper.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/person/extension/PersonDTOMapper.java
@@ -1,7 +1,9 @@
 package org.synyx.urlaubsverwaltung.person.extension;
 
+import de.focus_shift.urlaubsverwaltung.extension.api.person.MailNotificationDTO;
 import de.focus_shift.urlaubsverwaltung.extension.api.person.PersonDTO;
 import de.focus_shift.urlaubsverwaltung.extension.api.person.RoleDTO;
+import org.synyx.urlaubsverwaltung.person.MailNotification;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.Role;
 
@@ -18,6 +20,7 @@ class PersonDTOMapper {
         final Person person = new Person(personDTO.getUsername(), personDTO.getLastName(), personDTO.getFirstName(), personDTO.getEmail());
         person.setId(personDTO.getId());
         person.setPermissions(toRoles(personDTO));
+        person.setNotifications(toMailNotifications(personDTO));
         return person;
     }
 
@@ -30,9 +33,18 @@ class PersonDTOMapper {
             .email(person.getEmail())
             .enabled(person.isActive())
             .permissions(toRoleDTOs(person))
+            .notifications(toMailNotificationDTOs(person))
             .build();
     }
 
+    private static Set<MailNotification> toMailNotifications(PersonDTO personDTO) {
+        return personDTO.getNotifications().stream().map(dto -> MailNotification.valueOf(dto.name())).collect(Collectors.toSet());
+    }
+
+    private static Set<MailNotificationDTO> toMailNotificationDTOs(Person person) {
+        return person.getNotifications().stream().map(domain -> MailNotificationDTO.valueOf(domain.name())).collect(Collectors.toSet());
+    }
+
     static Set<Role> toRoles(PersonDTO personDTO) {
         if (!personDTO.isEnabled()) {
             return Set.of(Role.INACTIVE);
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/person/metrics/PersonMetrics.java b/src/main/java/org/synyx/urlaubsverwaltung/person/metrics/PersonMetrics.java
index fd79d24d9..5b88610d6 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/person/metrics/PersonMetrics.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/person/metrics/PersonMetrics.java
@@ -5,11 +5,13 @@ import io.micrometer.core.instrument.MeterRegistry;
 import org.slf4j.Logger;
 import org.springframework.stereotype.Component;
 import org.synyx.urlaubsverwaltung.person.PersonService;
+import org.synyx.urlaubsverwaltung.tenancy.configuration.single.ConditionalOnSingleTenantMode;
 
 import static java.lang.invoke.MethodHandles.lookup;
 import static org.slf4j.LoggerFactory.getLogger;
 
 @Component
+@ConditionalOnSingleTenantMode
 class PersonMetrics {
 
     private static final String METRIC_USERS_ACTIVE = "users.active";
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/security/Oauth2LoginConfigurationProperties.java b/src/main/java/org/synyx/urlaubsverwaltung/security/Oauth2LoginConfigurationProperties.java
new file mode 100644
index 000000000..bd397f682
--- /dev/null
+++ b/src/main/java/org/synyx/urlaubsverwaltung/security/Oauth2LoginConfigurationProperties.java
@@ -0,0 +1,20 @@
+package org.synyx.urlaubsverwaltung.security;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+@ConfigurationProperties("uv.security.oauth2")
+public class Oauth2LoginConfigurationProperties {
+
+    /**
+     * redirect to a login page url
+     */
+    private String loginPageUrl;
+
+    public String getLoginPageUrl() {
+        return loginPageUrl;
+    }
+
+    public void setLoginPageUrl(String loginPageUrl) {
+        this.loginPageUrl = loginPageUrl;
+    }
+}
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/security/ReloadAuthenticationAuthoritiesFilter.java b/src/main/java/org/synyx/urlaubsverwaltung/security/ReloadAuthenticationAuthoritiesFilter.java
index f92a18fcd..b4a8d7ea6 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/security/ReloadAuthenticationAuthoritiesFilter.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/security/ReloadAuthenticationAuthoritiesFilter.java
@@ -17,6 +17,8 @@ import org.springframework.security.web.context.DelegatingSecurityContextReposit
 import org.springframework.web.filter.OncePerRequestFilter;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonService;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.TenantContextHolder;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.TenantId;
 
 import java.io.IOException;
 import java.util.List;
@@ -34,11 +36,13 @@ class ReloadAuthenticationAuthoritiesFilter extends OncePerRequestFilter {
     private final PersonService personService;
     private final SessionService sessionService;
     private final DelegatingSecurityContextRepository securityContextRepository;
+    private final TenantContextHolder tenantContextHolder;
 
-    ReloadAuthenticationAuthoritiesFilter(PersonService personService, SessionService sessionService, DelegatingSecurityContextRepository securityContextRepository) {
+    ReloadAuthenticationAuthoritiesFilter(PersonService personService, SessionService sessionService, DelegatingSecurityContextRepository securityContextRepository, TenantContextHolder tenantContextHolder) {
         this.personService = personService;
         this.sessionService = sessionService;
         this.securityContextRepository = securityContextRepository;
+        this.tenantContextHolder = tenantContextHolder;
     }
 
     @Override
@@ -57,18 +61,25 @@ class ReloadAuthenticationAuthoritiesFilter extends OncePerRequestFilter {
         final HttpSession session = request.getSession();
         sessionService.unmarkSessionToReloadAuthorities(session.getId());
 
-        final Person signedInUser = personService.getSignedInUser();
-        final List<GrantedAuthority> updatedAuthorities = getUpdatedAuthorities(signedInUser);
-
         final SecurityContext context = SecurityContextHolder.getContext();
         final Authentication authentication = context.getAuthentication();
 
         final OAuth2AuthenticationToken oAuth2Auth = (OAuth2AuthenticationToken) authentication;
-        final Authentication updatedAuthentication = new OAuth2AuthenticationToken(oAuth2Auth.getPrincipal(), updatedAuthorities, oAuth2Auth.getAuthorizedClientRegistrationId());
 
-        context.setAuthentication(updatedAuthentication);
-        securityContextRepository.saveContext(context, request, response);
-        LOG.info("Updated authorities of person with the id {} from {} to {}", signedInUser.getId(), authentication.getAuthorities(), updatedAuthorities);
+        final String tenantId = oAuth2Auth.getAuthorizedClientRegistrationId();
+
+        try {
+            tenantContextHolder.setTenantId(new TenantId(tenantId));
+            final Person signedInUser = personService.getSignedInUser();
+            final List<GrantedAuthority> updatedAuthorities = getUpdatedAuthorities(signedInUser);
+            final Authentication updatedAuthentication = new OAuth2AuthenticationToken(oAuth2Auth.getPrincipal(), updatedAuthorities, oAuth2Auth.getAuthorizedClientRegistrationId());
+
+            context.setAuthentication(updatedAuthentication);
+            securityContextRepository.saveContext(context, request, response);
+            LOG.info("Updated authorities of person with the id {} from {} to {}", signedInUser.getId(), authentication.getAuthorities(), updatedAuthorities);
+        } finally {
+            tenantContextHolder.clear();
+        }
 
         chain.doFilter(request, response);
     }
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/security/SecurityWebConfiguration.java b/src/main/java/org/synyx/urlaubsverwaltung/security/SecurityWebConfiguration.java
index a36a889b8..82ff8abd4 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/security/SecurityWebConfiguration.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/security/SecurityWebConfiguration.java
@@ -1,6 +1,7 @@
 package org.synyx.urlaubsverwaltung.security;
 
 import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.core.annotation.Order;
@@ -15,6 +16,7 @@ import org.springframework.security.web.context.DelegatingSecurityContextReposit
 import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
 import org.springframework.security.web.context.RequestAttributeSecurityContextRepository;
 import org.synyx.urlaubsverwaltung.person.PersonService;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.TenantContextHolder;
 
 import static org.springframework.http.HttpMethod.GET;
 import static org.springframework.security.config.http.SessionCreationPolicy.NEVER;
@@ -23,6 +25,7 @@ import static org.synyx.urlaubsverwaltung.person.Role.OFFICE;
 import static org.synyx.urlaubsverwaltung.person.Role.USER;
 
 @Configuration
+@EnableConfigurationProperties(Oauth2LoginConfigurationProperties.class)
 @EnableMethodSecurity
 class SecurityWebConfiguration {
 
@@ -30,14 +33,17 @@ class SecurityWebConfiguration {
     private final SessionService sessionService;
     private final OidcClientInitiatedLogoutSuccessHandler oidcClientInitiatedLogoutSuccessHandler;
     private final ClientRegistrationRepository clientRegistrationRepository;
+    private final Oauth2LoginConfigurationProperties oauth2LoginConfigurationProperties;
 
     SecurityWebConfiguration(PersonService personService, SessionService sessionService,
                              OidcClientInitiatedLogoutSuccessHandler oidcClientInitiatedLogoutSuccessHandler,
-                             ClientRegistrationRepository clientRegistrationRepository) {
+                             ClientRegistrationRepository clientRegistrationRepository,
+                             Oauth2LoginConfigurationProperties oauth2LoginConfigurationProperties) {
         this.personService = personService;
         this.sessionService = sessionService;
         this.oidcClientInitiatedLogoutSuccessHandler = oidcClientInitiatedLogoutSuccessHandler;
         this.clientRegistrationRepository = clientRegistrationRepository;
+        this.oauth2LoginConfigurationProperties = oauth2LoginConfigurationProperties;
     }
 
     @Bean
@@ -79,7 +85,7 @@ class SecurityWebConfiguration {
 
     @Bean
     @Order(4)
-    SecurityFilterChain webSecurityFilterChain(final HttpSecurity http, DelegatingSecurityContextRepository securityContextRepository) throws Exception {
+    SecurityFilterChain webSecurityFilterChain(final HttpSecurity http, DelegatingSecurityContextRepository securityContextRepository, TenantContextHolder tenantContextHolder) throws Exception {
         return http
             .authorizeHttpRequests(requests ->
                 requests
@@ -107,9 +113,16 @@ class SecurityWebConfiguration {
                     .anyRequest().authenticated()
             )
             .oauth2Login(
-                loginCustomizer -> loginCustomizer.authorizationEndpoint(
-                    endpointCustomizer -> endpointCustomizer.authorizationRequestResolver(new LoginHintAwareResolver(clientRegistrationRepository))
-                )
+                loginCustomizer -> {
+                    loginCustomizer.authorizationEndpoint(
+                        endpointCustomizer -> endpointCustomizer.authorizationRequestResolver(new LoginHintAwareResolver(clientRegistrationRepository))
+                    );
+
+                    final String loginPageUrl = oauth2LoginConfigurationProperties.getLoginPageUrl();
+                    if (loginPageUrl != null && !loginPageUrl.isBlank()) {
+                        loginCustomizer.loginPage(loginPageUrl);
+                    }
+                }
             )
             .logout(
                 logoutCustomizer -> logoutCustomizer.logoutSuccessHandler(oidcClientInitiatedLogoutSuccessHandler)
@@ -117,7 +130,7 @@ class SecurityWebConfiguration {
             .securityContext(
                 securityContext -> securityContext.securityContextRepository(securityContextRepository)
             )
-            .addFilterAfter(new ReloadAuthenticationAuthoritiesFilter(personService, sessionService, securityContextRepository), BasicAuthenticationFilter.class)
+            .addFilterAfter(new ReloadAuthenticationAuthoritiesFilter(personService, sessionService, securityContextRepository, tenantContextHolder), BasicAuthenticationFilter.class)
             .build();
     }
 
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/security/SessionServiceImpl.java b/src/main/java/org/synyx/urlaubsverwaltung/security/SessionServiceImpl.java
index 483893238..b60a2eff4 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/security/SessionServiceImpl.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/security/SessionServiceImpl.java
@@ -6,10 +6,12 @@ import org.springframework.session.FindByIndexNameSessionRepository;
 import org.springframework.session.Session;
 import org.springframework.stereotype.Service;
 import org.synyx.urlaubsverwaltung.person.PersonDeletedEvent;
+import org.synyx.urlaubsverwaltung.tenancy.configuration.single.ConditionalOnSingleTenantMode;
 
 import java.util.Map;
 
 @Service
+@ConditionalOnSingleTenantMode
 class SessionServiceImpl<S extends Session> implements SessionService {
 
     static final String RELOAD_AUTHORITIES = "reloadAuthorities";
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/security/oidc/OidcPersonMappingException.java b/src/main/java/org/synyx/urlaubsverwaltung/security/oidc/OidcPersonMappingException.java
index cc028dbc4..dbc13a7ee 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/security/oidc/OidcPersonMappingException.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/security/oidc/OidcPersonMappingException.java
@@ -3,7 +3,7 @@ package org.synyx.urlaubsverwaltung.security.oidc;
 import org.springframework.security.core.AuthenticationException;
 
 public class OidcPersonMappingException extends AuthenticationException {
-    OidcPersonMappingException(String message) {
+    public OidcPersonMappingException(String message) {
         super(message);
     }
 }
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/security/oidc/OidcSecurityConfiguration.java b/src/main/java/org/synyx/urlaubsverwaltung/security/oidc/OidcSecurityConfiguration.java
index 7a3f060ff..8615a914c 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/security/oidc/OidcSecurityConfiguration.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/security/oidc/OidcSecurityConfiguration.java
@@ -10,11 +10,13 @@ import org.springframework.security.oauth2.client.registration.ClientRegistratio
 import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
 import org.springframework.security.oauth2.core.oidc.user.OidcUser;
 import org.synyx.urlaubsverwaltung.person.PersonService;
+import org.synyx.urlaubsverwaltung.tenancy.configuration.single.ConditionalOnSingleTenantMode;
 
 import java.util.List;
 
 @Configuration
 @EnableConfigurationProperties({OidcSecurityProperties.class, RolesFromClaimMappersProperties.class})
+@ConditionalOnSingleTenantMode
 class OidcSecurityConfiguration {
 
     @Bean
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/security/oidc/RolesFromClaimMappersInfusedOAuth2UserService.java b/src/main/java/org/synyx/urlaubsverwaltung/security/oidc/RolesFromClaimMappersInfusedOAuth2UserService.java
index 394b57664..098f1c002 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/security/oidc/RolesFromClaimMappersInfusedOAuth2UserService.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/security/oidc/RolesFromClaimMappersInfusedOAuth2UserService.java
@@ -12,12 +12,12 @@ import java.util.stream.Stream;
 
 import static java.util.stream.Stream.concat;
 
-class RolesFromClaimMappersInfusedOAuth2UserService implements OAuth2UserService<OidcUserRequest, OidcUser> {
+public class RolesFromClaimMappersInfusedOAuth2UserService implements OAuth2UserService<OidcUserRequest, OidcUser> {
 
     private final OAuth2UserService<OidcUserRequest, OidcUser> delegate;
     private final List<RolesFromClaimMapper> claimMappers;
 
-    RolesFromClaimMappersInfusedOAuth2UserService(OAuth2UserService<OidcUserRequest, OidcUser> delegate, List<RolesFromClaimMapper> claimMappers) {
+    public RolesFromClaimMappersInfusedOAuth2UserService(OAuth2UserService<OidcUserRequest, OidcUser> delegate, List<RolesFromClaimMapper> claimMappers) {
         this.delegate = delegate;
         this.claimMappers = claimMappers;
     }
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/settings/InitialDefaultSettingsConfigurerSingleTenant.java b/src/main/java/org/synyx/urlaubsverwaltung/settings/InitialDefaultSettingsConfigurerSingleTenant.java
new file mode 100644
index 000000000..f351dcd52
--- /dev/null
+++ b/src/main/java/org/synyx/urlaubsverwaltung/settings/InitialDefaultSettingsConfigurerSingleTenant.java
@@ -0,0 +1,24 @@
+package org.synyx.urlaubsverwaltung.settings;
+
+
+import org.springframework.boot.context.event.ApplicationStartedEvent;
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Component;
+import org.synyx.urlaubsverwaltung.tenancy.configuration.single.ConditionalOnSingleTenantMode;
+
+@Component
+@ConditionalOnSingleTenantMode
+class InitialDefaultSettingsConfigurerSingleTenant {
+
+
+    private final SettingsService settingsService;
+
+    InitialDefaultSettingsConfigurerSingleTenant(SettingsService settingsService) {
+        this.settingsService = settingsService;
+    }
+
+    @EventListener(ApplicationStartedEvent.class)
+    void insertDefaultSettings() {
+        settingsService.insertDefaultSettings();
+    }
+}
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/settings/Settings.java b/src/main/java/org/synyx/urlaubsverwaltung/settings/Settings.java
index 5d64bb18d..2df6d2ec4 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/settings/Settings.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/settings/Settings.java
@@ -11,6 +11,7 @@ import org.synyx.urlaubsverwaltung.application.settings.ApplicationSettings;
 import org.synyx.urlaubsverwaltung.overtime.OvertimeSettings;
 import org.synyx.urlaubsverwaltung.person.settings.AvatarSettings;
 import org.synyx.urlaubsverwaltung.sicknote.settings.SickNoteSettings;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.AbstractTenantAwareEntity;
 import org.synyx.urlaubsverwaltung.workingtime.WorkingTimeSettings;
 
 import java.util.Objects;
@@ -22,7 +23,7 @@ import static jakarta.persistence.GenerationType.SEQUENCE;
  * Represents the settings / business rules for the application.
  */
 @Entity
-public class Settings {
+public class Settings extends AbstractTenantAwareEntity {
 
     @Id
     @Column(name = "id", unique = true, nullable = false, updatable = false)
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/settings/SettingsService.java b/src/main/java/org/synyx/urlaubsverwaltung/settings/SettingsService.java
index cfa5870ab..07e626882 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/settings/SettingsService.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/settings/SettingsService.java
@@ -17,4 +17,6 @@ public interface SettingsService {
      * @return settings for the application
      */
     Settings getSettings();
+
+    void insertDefaultSettings();
 }
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/settings/SettingsServiceImpl.java b/src/main/java/org/synyx/urlaubsverwaltung/settings/SettingsServiceImpl.java
index d78874251..66f91c1e7 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/settings/SettingsServiceImpl.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/settings/SettingsServiceImpl.java
@@ -32,10 +32,18 @@ public class SettingsServiceImpl implements SettingsService {
     @Override
     public Settings getSettings() {
         return settingsRepository.findAll().stream().findFirst()
-            .orElseGet(() -> {
-                final Settings savedSettings = settingsRepository.save(new Settings());
-                LOG.info("Saved initial settings {}", savedSettings);
-                return savedSettings;
-            });
+            .orElseThrow(() -> new IllegalStateException("No settings found in database!"));
+    }
+
+    @Override
+    public void insertDefaultSettings() {
+
+        final long count = settingsRepository.count();
+
+        if (count == 0) {
+            final Settings settings = new Settings();
+            final Settings savedSettings = settingsRepository.save(settings);
+            LOG.info("Saved initial settings {}", savedSettings);
+        }
     }
 }
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/SickNoteEntity.java b/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/SickNoteEntity.java
index 20c451e3d..8714c9946 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/SickNoteEntity.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/SickNoteEntity.java
@@ -11,6 +11,7 @@ import jakarta.persistence.Table;
 import org.synyx.urlaubsverwaltung.period.DayLength;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.sicknote.sicknotetype.SickNoteType;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.AbstractTenantAwareEntity;
 
 import java.time.LocalDate;
 import java.util.Objects;
@@ -23,7 +24,7 @@ import static jakarta.persistence.GenerationType.SEQUENCE;
  */
 @Entity
 @Table(name = "sick_note")
-public class SickNoteEntity {
+public class SickNoteEntity extends AbstractTenantAwareEntity {
 
     @Id
     @Column(name = "id", unique = true, nullable = false, updatable = false)
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/SickNoteMailConfiguration.java b/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/SickNoteMailConfiguration.java
index 23c54979b..df0d931f2 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/SickNoteMailConfiguration.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/SickNoteMailConfiguration.java
@@ -6,8 +6,10 @@ import org.springframework.scheduling.annotation.SchedulingConfigurer;
 import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
 import org.springframework.scheduling.config.ScheduledTaskRegistrar;
 import org.synyx.urlaubsverwaltung.config.ScheduleLocking;
+import org.synyx.urlaubsverwaltung.tenancy.configuration.single.ConditionalOnSingleTenantMode;
 
 @Configuration
+@ConditionalOnSingleTenantMode
 class SickNoteMailConfiguration implements SchedulingConfigurer {
 
     private final SickNoteProperties sickNoteProperties;
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/SickNoteMailService.java b/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/SickNoteMailService.java
index 297e32764..36c483b86 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/SickNoteMailService.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/SickNoteMailService.java
@@ -34,7 +34,7 @@ import static org.synyx.urlaubsverwaltung.person.MailNotification.NOTIFICATION_E
 import static org.synyx.urlaubsverwaltung.person.Role.OFFICE;
 
 @Service
-class SickNoteMailService {
+public class SickNoteMailService {
 
     private static final Logger LOG = getLogger(lookup().lookupClass());
 
@@ -60,7 +60,7 @@ class SickNoteMailService {
      * Sends mail to person and office if sick pay (gesetzliche Lohnfortzahlung im Krankheitsfall) is about to end.
      */
     @Async
-    void sendEndOfSickPayNotification() {
+    public void sendEndOfSickPayNotification() {
 
         final List<SickNote> sickNotes = sickNoteService.getSickNotesReachingEndOfSickPay();
 
@@ -198,10 +198,10 @@ class SickNoteMailService {
     @Async
     void sendSickNoteAcceptedNotificationToSickPerson(SickNote acceptedSickNote, Person maintainer) {
         final Mail mailToApplicant = Mail.builder()
-                .withRecipient(acceptedSickNote.getPerson(), NOTIFICATION_EMAIL_SICK_NOTE_ACCEPTED_BY_MANAGEMENT_TO_USER)
-                .withSubject("subject.sicknote.accepted_by_management.to_applicant")
-                .withTemplate("sick_note_accepted_by_management_to_applicant", locale -> Map.of("sickNote", acceptedSickNote, "maintainer", maintainer))
-                .build();
+            .withRecipient(acceptedSickNote.getPerson(), NOTIFICATION_EMAIL_SICK_NOTE_ACCEPTED_BY_MANAGEMENT_TO_USER)
+            .withSubject("subject.sicknote.accepted_by_management.to_applicant")
+            .withTemplate("sick_note_accepted_by_management_to_applicant", locale -> Map.of("sickNote", acceptedSickNote, "maintainer", maintainer))
+            .build();
         mailService.send(mailToApplicant);
     }
 
@@ -239,14 +239,14 @@ class SickNoteMailService {
     @Async
     void sendSickNoteAcceptedNotificationToOfficeAndResponsibleManagement(SickNote acceptedSickNote, Person maintainer) {
         final List<Person> recipients =
-                mailRecipientService.getRecipientsOfInterest(acceptedSickNote.getPerson(), NOTIFICATION_EMAIL_SICK_NOTE_ACCEPTED_BY_MANAGEMENT_TO_MANAGEMENT)
-                        .stream().filter(recipient -> !recipient.equals(maintainer))
-                        .toList();
+            mailRecipientService.getRecipientsOfInterest(acceptedSickNote.getPerson(), NOTIFICATION_EMAIL_SICK_NOTE_ACCEPTED_BY_MANAGEMENT_TO_MANAGEMENT)
+                .stream().filter(recipient -> !recipient.equals(maintainer))
+                .toList();
         final Mail mailToOfficeAndResponsibleManagement = Mail.builder()
-                .withRecipient(recipients)
-                .withSubject("subject.sicknote.accepted_by_management.to_management", acceptedSickNote.getPerson().getNiceName())
-                .withTemplate("sick_note_accepted_by_management_to_management", locale -> Map.of("sickNote", acceptedSickNote, "maintainer", maintainer))
-                .build();
+            .withRecipient(recipients)
+            .withSubject("subject.sicknote.accepted_by_management.to_management", acceptedSickNote.getPerson().getNiceName())
+            .withTemplate("sick_note_accepted_by_management_to_management", locale -> Map.of("sickNote", acceptedSickNote, "maintainer", maintainer))
+            .build();
 
         mailService.send(mailToOfficeAndResponsibleManagement);
     }
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/extend/SickNoteExtensionEntity.java b/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/extend/SickNoteExtensionEntity.java
index 07e233815..82c3404b3 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/extend/SickNoteExtensionEntity.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/extend/SickNoteExtensionEntity.java
@@ -6,6 +6,7 @@ import jakarta.persistence.Enumerated;
 import jakarta.persistence.GeneratedValue;
 import jakarta.persistence.Id;
 import jakarta.persistence.SequenceGenerator;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.AbstractTenantAwareEntity;
 
 import java.time.Instant;
 import java.time.LocalDate;
@@ -15,7 +16,7 @@ import static jakarta.persistence.EnumType.STRING;
 import static jakarta.persistence.GenerationType.SEQUENCE;
 
 @Entity(name = "sick_note_extension")
-class SickNoteExtensionEntity {
+public class SickNoteExtensionEntity extends AbstractTenantAwareEntity {
 
     @Id
     @Column(name = "id", unique = true, nullable = false, updatable = false)
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknotetype/InitialDefaultSickNoteTypesConfigurerSingleTenant.java b/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknotetype/InitialDefaultSickNoteTypesConfigurerSingleTenant.java
new file mode 100644
index 000000000..2abb7ab64
--- /dev/null
+++ b/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknotetype/InitialDefaultSickNoteTypesConfigurerSingleTenant.java
@@ -0,0 +1,22 @@
+package org.synyx.urlaubsverwaltung.sicknote.sicknotetype;
+
+import org.springframework.boot.context.event.ApplicationStartedEvent;
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Component;
+import org.synyx.urlaubsverwaltung.tenancy.configuration.single.ConditionalOnSingleTenantMode;
+
+@Component
+@ConditionalOnSingleTenantMode
+class InitialDefaultSickNoteTypesConfigurerSingleTenant {
+
+    private final SickNoteTypeService sickNoteTypeService;
+
+    InitialDefaultSickNoteTypesConfigurerSingleTenant(SickNoteTypeService sickNoteTypeService) {
+        this.sickNoteTypeService = sickNoteTypeService;
+    }
+
+    @EventListener(ApplicationStartedEvent.class)
+    void insertDefaultSickNoteTypes() {
+        sickNoteTypeService.insertDefaultSickNoteTypes();
+    }
+}
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknotetype/SickNoteType.java b/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknotetype/SickNoteType.java
index e82198332..2160f1428 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknotetype/SickNoteType.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknotetype/SickNoteType.java
@@ -1,19 +1,27 @@
 package org.synyx.urlaubsverwaltung.sicknote.sicknotetype;
 
+import jakarta.persistence.Column;
 import jakarta.persistence.Entity;
 import jakarta.persistence.Enumerated;
+import jakarta.persistence.GeneratedValue;
 import jakarta.persistence.Id;
+import jakarta.persistence.SequenceGenerator;
 import jakarta.validation.constraints.NotNull;
 import org.synyx.urlaubsverwaltung.sicknote.sicknote.SickNoteCategory;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.AbstractTenantAwareEntity;
 
 import java.util.Objects;
 
 import static jakarta.persistence.EnumType.STRING;
+import static jakarta.persistence.GenerationType.SEQUENCE;
 
 @Entity
-public class SickNoteType {
+public class SickNoteType extends AbstractTenantAwareEntity {
 
     @Id
+    @Column(name = "id", unique = true, nullable = false, updatable = false)
+    @GeneratedValue(strategy = SEQUENCE, generator = "sick_note_type_generator")
+    @SequenceGenerator(name = "sick_note_type_generator", sequenceName = "sick_note_type_id_seq")
     private Long id;
 
     @NotNull
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknotetype/SickNoteTypeService.java b/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknotetype/SickNoteTypeService.java
index 6e11a0c5b..389d4a40b 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknotetype/SickNoteTypeService.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknotetype/SickNoteTypeService.java
@@ -10,4 +10,6 @@ public interface SickNoteTypeService {
      * @return list of all types
      */
     List<SickNoteType> getSickNoteTypes();
+
+    void insertDefaultSickNoteTypes();
 }
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknotetype/SickNoteTypeServiceImpl.java b/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknotetype/SickNoteTypeServiceImpl.java
index d4c41f310..e172b0b90 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknotetype/SickNoteTypeServiceImpl.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/sicknote/sicknotetype/SickNoteTypeServiceImpl.java
@@ -2,8 +2,6 @@ package org.synyx.urlaubsverwaltung.sicknote.sicknotetype;
 
 import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.context.event.ApplicationStartedEvent;
-import org.springframework.context.event.EventListener;
 import org.springframework.data.domain.Sort;
 import org.springframework.stereotype.Service;
 
@@ -31,18 +29,17 @@ class SickNoteTypeServiceImpl implements SickNoteTypeService {
         return this.sickNoteTypeRepository.findAll(Sort.by("id"));
     }
 
-    @EventListener(ApplicationStartedEvent.class)
-    void insertDefaultSickNoteTypes() {
+
+    @Override
+    public void insertDefaultSickNoteTypes() {
         final long count = sickNoteTypeRepository.count();
         if (count == 0) {
 
             final SickNoteType sickNote = new SickNoteType();
-            sickNote.setId(1000L);
             sickNote.setCategory(SICK_NOTE);
             sickNote.setMessageKey("application.data.sicknotetype.sicknote");
 
             final SickNoteType sickNoteChild = new SickNoteType();
-            sickNoteChild.setId(2000L);
             sickNoteChild.setCategory(SICK_NOTE_CHILD);
             sickNoteChild.setMessageKey("application.data.sicknotetype.sicknotechild");
 
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/tenancy/configuration/single/ConditionalOnSingleTenantMode.java b/src/main/java/org/synyx/urlaubsverwaltung/tenancy/configuration/single/ConditionalOnSingleTenantMode.java
new file mode 100644
index 000000000..61dea391c
--- /dev/null
+++ b/src/main/java/org/synyx/urlaubsverwaltung/tenancy/configuration/single/ConditionalOnSingleTenantMode.java
@@ -0,0 +1,21 @@
+package org.synyx.urlaubsverwaltung.tenancy.configuration.single;
+
+import org.springframework.context.annotation.Conditional;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates that a component is only eligible for registration when single tenant mode is enabled.
+ *
+ * @see Conditional
+ */
+@Target({ElementType.TYPE, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Conditional(IsSingleTenantMode.class)
+public @interface ConditionalOnSingleTenantMode {
+}
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/tenancy/configuration/single/IsSingleTenantMode.java b/src/main/java/org/synyx/urlaubsverwaltung/tenancy/configuration/single/IsSingleTenantMode.java
new file mode 100644
index 000000000..e8a27dd34
--- /dev/null
+++ b/src/main/java/org/synyx/urlaubsverwaltung/tenancy/configuration/single/IsSingleTenantMode.java
@@ -0,0 +1,21 @@
+package org.synyx.urlaubsverwaltung.tenancy.configuration.single;
+
+import org.springframework.context.annotation.Condition;
+import org.springframework.context.annotation.ConditionContext;
+import org.springframework.core.type.AnnotatedTypeMetadata;
+
+public class IsSingleTenantMode implements Condition {
+
+    protected static final String URLAUBSVERWALTUNG_TENANT_MODE = "uv.tenant.mode";
+    protected static final String SINGLE_MODE = "single";
+
+    @Override
+    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
+        final String property = context.getEnvironment().getProperty(URLAUBSVERWALTUNG_TENANT_MODE);
+
+        if (property == null || property.isBlank()) {
+            return true;
+        }
+        return SINGLE_MODE.equals(property);
+    }
+}
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/tenancy/configuration/single/SingleTenantConfiguration.java b/src/main/java/org/synyx/urlaubsverwaltung/tenancy/configuration/single/SingleTenantConfiguration.java
new file mode 100644
index 000000000..18e53e280
--- /dev/null
+++ b/src/main/java/org/synyx/urlaubsverwaltung/tenancy/configuration/single/SingleTenantConfiguration.java
@@ -0,0 +1,10 @@
+package org.synyx.urlaubsverwaltung.tenancy.configuration.single;
+
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@EnableConfigurationProperties(SingleTenantConfigurationProperties.class)
+@ConditionalOnSingleTenantMode
+public class SingleTenantConfiguration {
+}
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/tenancy/configuration/single/SingleTenantConfigurationProperties.java b/src/main/java/org/synyx/urlaubsverwaltung/tenancy/configuration/single/SingleTenantConfigurationProperties.java
new file mode 100644
index 000000000..ec12853c6
--- /dev/null
+++ b/src/main/java/org/synyx/urlaubsverwaltung/tenancy/configuration/single/SingleTenantConfigurationProperties.java
@@ -0,0 +1,26 @@
+package org.synyx.urlaubsverwaltung.tenancy.configuration.single;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Size;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.validation.annotation.Validated;
+
+@Validated
+@ConfigurationProperties("uv.tenant.single")
+public class SingleTenantConfigurationProperties {
+
+    /**
+     * Sets the id of the default tenant, default is 'default'
+     */
+    @NotBlank
+    @Size(min = 1, max = 255)
+    private String defaultTenantId = "default";
+
+    public String getDefaultTenantId() {
+        return defaultTenantId;
+    }
+
+    public void setDefaultTenantId(String defaultTenantId) {
+        this.defaultTenantId = defaultTenantId;
+    }
+}
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/tenancy/configuration/single/TenantContextHolderSingleTenant.java b/src/main/java/org/synyx/urlaubsverwaltung/tenancy/configuration/single/TenantContextHolderSingleTenant.java
new file mode 100644
index 000000000..1f370a6a5
--- /dev/null
+++ b/src/main/java/org/synyx/urlaubsverwaltung/tenancy/configuration/single/TenantContextHolderSingleTenant.java
@@ -0,0 +1,25 @@
+package org.synyx.urlaubsverwaltung.tenancy.configuration.single;
+
+import org.springframework.stereotype.Component;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.TenantContextHolder;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.TenantId;
+
+import java.util.Optional;
+
+
+@Component
+@ConditionalOnSingleTenantMode
+class TenantContextHolderSingleTenant implements TenantContextHolder {
+
+    private final String defaultTenantId;
+
+    TenantContextHolderSingleTenant(SingleTenantConfigurationProperties singleTenantConfigurationProperties) {
+        this.defaultTenantId = singleTenantConfigurationProperties.getDefaultTenantId();
+    }
+
+    @Override
+    public Optional<TenantId> getCurrentTenantId() {
+        return Optional.of(new TenantId(defaultTenantId));
+    }
+
+}
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/tenancy/tenant/AbstractTenantAwareEntity.java b/src/main/java/org/synyx/urlaubsverwaltung/tenancy/tenant/AbstractTenantAwareEntity.java
new file mode 100644
index 000000000..428fa9421
--- /dev/null
+++ b/src/main/java/org/synyx/urlaubsverwaltung/tenancy/tenant/AbstractTenantAwareEntity.java
@@ -0,0 +1,35 @@
+package org.synyx.urlaubsverwaltung.tenancy.tenant;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.EntityListeners;
+import jakarta.persistence.MappedSuperclass;
+import jakarta.validation.constraints.Size;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+@MappedSuperclass
+@EntityListeners(TenantListener.class)
+public abstract class AbstractTenantAwareEntity implements TenantAware, Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 8093106407703011072L;
+
+    @Size(max = 255)
+    @Column(name = "tenant_id")
+    private String tenantId;
+
+    protected AbstractTenantAwareEntity() {
+        // OK
+    }
+
+    @Override
+    public String getTenantId() {
+        return tenantId;
+    }
+
+    @Override
+    public void setTenantId(String tenantId) {
+        this.tenantId = tenantId;
+    }
+}
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/tenancy/tenant/MissingTenantException.java b/src/main/java/org/synyx/urlaubsverwaltung/tenancy/tenant/MissingTenantException.java
new file mode 100644
index 000000000..b2c9e16d2
--- /dev/null
+++ b/src/main/java/org/synyx/urlaubsverwaltung/tenancy/tenant/MissingTenantException.java
@@ -0,0 +1,7 @@
+package org.synyx.urlaubsverwaltung.tenancy.tenant;
+
+public class MissingTenantException extends RuntimeException {
+    MissingTenantException(String message) {
+        super(message);
+    }
+}
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/tenancy/tenant/TenantAware.java b/src/main/java/org/synyx/urlaubsverwaltung/tenancy/tenant/TenantAware.java
new file mode 100644
index 000000000..689d7c657
--- /dev/null
+++ b/src/main/java/org/synyx/urlaubsverwaltung/tenancy/tenant/TenantAware.java
@@ -0,0 +1,8 @@
+package org.synyx.urlaubsverwaltung.tenancy.tenant;
+
+interface TenantAware {
+
+    String getTenantId();
+
+    void setTenantId(String tenantId);
+}
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/tenancy/tenant/TenantContextHolder.java b/src/main/java/org/synyx/urlaubsverwaltung/tenancy/tenant/TenantContextHolder.java
new file mode 100644
index 000000000..0bf178905
--- /dev/null
+++ b/src/main/java/org/synyx/urlaubsverwaltung/tenancy/tenant/TenantContextHolder.java
@@ -0,0 +1,41 @@
+package org.synyx.urlaubsverwaltung.tenancy.tenant;
+
+import java.util.Optional;
+import java.util.function.Consumer;
+
+public interface TenantContextHolder {
+
+    default Optional<TenantId> getCurrentTenantId() {
+        return Optional.empty();
+    }
+
+    default void setTenantId(TenantId tenantId) {
+
+    }
+
+    default void clear() {
+
+    }
+
+    default void runInTenantIdContext(String tenantId, Consumer<String> function) {
+        runInTenantIdContext(new TenantId(tenantId), function);
+    }
+
+    default void runInTenantIdContext(TenantId tenantId, Consumer<String> function) {
+        try {
+            setTenantId(tenantId);
+            function.accept(tenantId.tenantId());
+        } finally {
+            clear();
+        }
+    }
+
+    default void runInTenantIdContext(TenantId tenantId, Runnable function) {
+        try {
+            setTenantId(tenantId);
+            function.run();
+        } finally {
+            clear();
+        }
+    }
+}
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/tenancy/tenant/TenantId.java b/src/main/java/org/synyx/urlaubsverwaltung/tenancy/tenant/TenantId.java
new file mode 100644
index 000000000..e32bc0108
--- /dev/null
+++ b/src/main/java/org/synyx/urlaubsverwaltung/tenancy/tenant/TenantId.java
@@ -0,0 +1,10 @@
+package org.synyx.urlaubsverwaltung.tenancy.tenant;
+
+
+import org.springframework.util.StringUtils;
+
+public record TenantId(String tenantId) {
+    public boolean valid() {
+        return StringUtils.hasText(tenantId) && tenantId.length() <= 255;
+    }
+}
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/tenancy/tenant/TenantListener.java b/src/main/java/org/synyx/urlaubsverwaltung/tenancy/tenant/TenantListener.java
new file mode 100644
index 000000000..5b7707f18
--- /dev/null
+++ b/src/main/java/org/synyx/urlaubsverwaltung/tenancy/tenant/TenantListener.java
@@ -0,0 +1,29 @@
+package org.synyx.urlaubsverwaltung.tenancy.tenant;
+
+import jakarta.persistence.PrePersist;
+import jakarta.persistence.PreRemove;
+import jakarta.persistence.PreUpdate;
+import org.springframework.stereotype.Component;
+
+@Component
+class TenantListener {
+
+    private final TenantContextHolder tenantContextHolder;
+
+    public TenantListener(TenantContextHolder tenantContextHolder) {
+        this.tenantContextHolder = tenantContextHolder;
+    }
+
+    @PreUpdate
+    @PreRemove
+    @PrePersist
+    public void setTenant(Object entity) {
+        if (entity instanceof TenantAware tenantAware) {
+            final String tenantId = tenantContextHolder.getCurrentTenantId()
+                .map(TenantId::tenantId)
+                .orElseThrow(() -> new MissingTenantException("No tenant found in security context"));
+
+            tenantAware.setTenantId(tenantId);
+        }
+    }
+}
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/user/UserSettingsEntity.java b/src/main/java/org/synyx/urlaubsverwaltung/user/UserSettingsEntity.java
index 386ca278f..4ed2e9b90 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/user/UserSettingsEntity.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/user/UserSettingsEntity.java
@@ -9,6 +9,7 @@ import jakarta.persistence.PrimaryKeyJoinColumn;
 import jakarta.persistence.Table;
 import jakarta.validation.constraints.NotNull;
 import org.synyx.urlaubsverwaltung.person.Person;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.AbstractTenantAwareEntity;
 
 import java.util.Locale;
 import java.util.Objects;
@@ -18,7 +19,7 @@ import static jakarta.persistence.FetchType.LAZY;
 
 @Entity
 @Table(name = "user_settings")
-class UserSettingsEntity {
+public class UserSettingsEntity extends AbstractTenantAwareEntity {
 
     @Id
     @Column(name = "person_id")
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/user/pagination/UserPaginationSettingsEntity.java b/src/main/java/org/synyx/urlaubsverwaltung/user/pagination/UserPaginationSettingsEntity.java
index 023d8ecfd..54a0bcc73 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/user/pagination/UserPaginationSettingsEntity.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/user/pagination/UserPaginationSettingsEntity.java
@@ -9,6 +9,7 @@ import jakarta.persistence.Table;
 import jakarta.validation.constraints.NotNull;
 import jakarta.validation.constraints.Positive;
 import org.synyx.urlaubsverwaltung.person.Person;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.AbstractTenantAwareEntity;
 
 import java.util.Objects;
 
@@ -16,7 +17,7 @@ import static jakarta.persistence.FetchType.LAZY;
 
 @Entity
 @Table(name = "user_pagination_settings")
-class UserPaginationSettingsEntity {
+public class UserPaginationSettingsEntity extends AbstractTenantAwareEntity {
 
     @Id
     @Column(name = "person_id")
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/workingtime/WorkingTimeEntity.java b/src/main/java/org/synyx/urlaubsverwaltung/workingtime/WorkingTimeEntity.java
index 6751c8ddf..90b12b21b 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/workingtime/WorkingTimeEntity.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/workingtime/WorkingTimeEntity.java
@@ -9,6 +9,7 @@ import jakarta.persistence.OneToOne;
 import jakarta.persistence.SequenceGenerator;
 import org.synyx.urlaubsverwaltung.period.DayLength;
 import org.synyx.urlaubsverwaltung.person.Person;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.AbstractTenantAwareEntity;
 
 import java.time.LocalDate;
 import java.util.Objects;
@@ -22,7 +23,7 @@ import static org.synyx.urlaubsverwaltung.period.DayLength.ZERO;
  * Entity representing the working time of a person.
  */
 @Entity(name = "working_time")
-class WorkingTimeEntity {
+public class WorkingTimeEntity extends AbstractTenantAwareEntity {
 
     @Id
     @Column(name = "id", unique = true, nullable = false, updatable = false)
diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml
index e8e8038d8..a0d8b4135 100644
--- a/src/main/resources/application.yaml
+++ b/src/main/resources/application.yaml
@@ -2,6 +2,8 @@ uv:
   mail:
     fromDisplayName: Urlaubsverwaltung
     replyToDisplayName: Urlaubsverwaltung
+  tenant:
+    mode: single
 
 spring:
   web:
diff --git a/src/main/resources/dbchangelogs/changelog-5.10.0-sick-note-type-seq.xml b/src/main/resources/dbchangelogs/changelog-5.10.0-sick-note-type-seq.xml
new file mode 100644
index 000000000..33ce6969e
--- /dev/null
+++ b/src/main/resources/dbchangelogs/changelog-5.10.0-sick-note-type-seq.xml
@@ -0,0 +1,11 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+                   xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.27.xsd">
+
+  <changeSet author="grafjo" id="add-sick-note-type-seq">
+    <createSequence cacheSize="1" cycle="false" dataType="bigint" incrementBy="50" maxValue="9223372036854775807"
+                    minValue="2001" sequenceName="sick_note_type_id_seq" startValue="2002"/>
+  </changeSet>
+
+</databaseChangeLog>
diff --git a/src/main/resources/dbchangelogs/changelog-5.10.0-singletenant.xml b/src/main/resources/dbchangelogs/changelog-5.10.0-singletenant.xml
new file mode 100644
index 000000000..a3037f54d
--- /dev/null
+++ b/src/main/resources/dbchangelogs/changelog-5.10.0-singletenant.xml
@@ -0,0 +1,382 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+                   xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.27.xsd">
+
+  <changeSet author="grafjo" id="account-tenancy">
+    <preConditions>
+      <tableExists tableName="account"/>
+      <not>
+        <columnExists tableName="account" columnName="tenant_id"/>
+      </not>
+    </preConditions>
+    <addColumn tableName="account">
+      <column name="tenant_id" type="text"/>
+    </addColumn>
+    <update tableName="account">
+      <column name="tenant_id" value="default"/>
+    </update>
+  </changeSet>
+
+  <changeSet author="grafjo" id="application-tenancy">
+    <preConditions>
+      <tableExists tableName="application"/>
+      <not>
+        <columnExists tableName="application" columnName="tenant_id"/>
+      </not>
+    </preConditions>
+    <addColumn tableName="application">
+      <column name="tenant_id" type="text"/>
+    </addColumn>
+    <update tableName="application">
+      <column name="tenant_id" value="default"/>
+    </update>
+  </changeSet>
+
+
+  <changeSet author="grafjo" id="application-comment-tenancy">
+    <preConditions>
+      <tableExists tableName="application_comment"/>
+      <not>
+        <columnExists tableName="application_comment" columnName="tenant_id"/>
+      </not>
+    </preConditions>
+    <addColumn tableName="application_comment">
+      <column name="tenant_id" type="text"/>
+    </addColumn>
+    <update tableName="application_comment">
+      <column name="tenant_id" value="default"/>
+    </update>
+  </changeSet>
+
+  <changeSet author="grafjo" id="special-leave-settings-tenancy">
+    <preConditions>
+      <tableExists tableName="special_leave_settings"/>
+      <not>
+        <columnExists tableName="special_leave_settings" columnName="tenant_id"/>
+      </not>
+    </preConditions>
+    <addColumn tableName="special_leave_settings">
+      <column name="tenant_id" type="text"/>
+    </addColumn>
+    <update tableName="special_leave_settings">
+      <column name="tenant_id" value="default"/>
+    </update>
+  </changeSet>
+
+  <changeSet author="grafjo" id="vacation-type-tenancy">
+    <preConditions>
+      <tableExists tableName="vacation_type"/>
+      <not>
+        <columnExists tableName="vacation_type" columnName="tenant_id"/>
+      </not>
+    </preConditions>
+    <addColumn tableName="vacation_type">
+      <column name="tenant_id" type="text"/>
+    </addColumn>
+    <update tableName="vacation_type">
+      <column name="tenant_id" value="default"/>
+    </update>
+  </changeSet>
+
+  <changeSet author="grafjo" id="calendar-accessible-tenancy">
+    <preConditions>
+      <tableExists tableName="calendar_accessible"/>
+      <not>
+        <columnExists tableName="calendar_accessible" columnName="tenant_id"/>
+      </not>
+    </preConditions>
+    <addColumn tableName="calendar_accessible">
+      <column name="tenant_id" type="text"/>
+    </addColumn>
+    <update tableName="calendar_accessible">
+      <column name="tenant_id" value="default"/>
+    </update>
+  </changeSet>
+
+  <changeSet author="grafjo" id="company-calendar-tenancy">
+    <preConditions>
+      <tableExists tableName="company_calendar"/>
+      <not>
+        <columnExists tableName="company_calendar" columnName="tenant_id"/>
+      </not>
+    </preConditions>
+    <addColumn tableName="company_calendar">
+      <column name="tenant_id" type="text"/>
+    </addColumn>
+    <update tableName="company_calendar">
+      <column name="tenant_id" value="default"/>
+    </update>
+  </changeSet>
+
+  <changeSet author="grafjo" id="department-calendar-tenancy">
+    <preConditions>
+      <tableExists tableName="department_calendar"/>
+      <not>
+        <columnExists tableName="department_calendar" columnName="tenant_id"/>
+      </not>
+    </preConditions>
+    <addColumn tableName="department_calendar">
+      <column name="tenant_id" type="text"/>
+    </addColumn>
+    <update tableName="department_calendar">
+      <column name="tenant_id" value="default"/>
+    </update>
+  </changeSet>
+
+  <changeSet author="grafjo" id="person-calendar-tenancy">
+    <preConditions>
+      <tableExists tableName="person_calendar"/>
+      <not>
+        <columnExists tableName="person_calendar" columnName="tenant_id"/>
+      </not>
+    </preConditions>
+    <addColumn tableName="person_calendar">
+      <column name="tenant_id" type="text"/>
+    </addColumn>
+    <update tableName="person_calendar">
+      <column name="tenant_id" value="default"/>
+    </update>
+  </changeSet>
+
+  <changeSet author="grafjo" id="absence-mapping-tenancy">
+    <preConditions>
+      <tableExists tableName="absence_mapping"/>
+      <not>
+        <columnExists tableName="absence_mapping" columnName="tenant_id"/>
+      </not>
+    </preConditions>
+    <addColumn tableName="absence_mapping">
+      <column name="tenant_id" type="text"/>
+    </addColumn>
+    <update tableName="absence_mapping">
+      <column name="tenant_id" value="default"/>
+    </update>
+  </changeSet>
+
+  <changeSet author="grafjo" id="calendar-integration-settings-tenancy">
+    <preConditions>
+      <tableExists tableName="calendar_integration_settings"/>
+      <not>
+        <columnExists tableName="calendar_integration_settings" columnName="tenant_id"/>
+      </not>
+    </preConditions>
+    <addColumn tableName="calendar_integration_settings">
+      <column name="tenant_id" type="text"/>
+    </addColumn>
+    <update tableName="calendar_integration_settings">
+      <column name="tenant_id" value="default"/>
+    </update>
+  </changeSet>
+
+  <changeSet author="grafjo" id="department-tenancy">
+    <preConditions>
+      <tableExists tableName="department"/>
+      <not>
+        <columnExists tableName="department" columnName="tenant_id"/>
+      </not>
+    </preConditions>
+    <addColumn tableName="department">
+      <column name="tenant_id" type="text"/>
+    </addColumn>
+    <update tableName="department">
+      <column name="tenant_id" value="default"/>
+    </update>
+  </changeSet>
+
+  <changeSet author="grafjo" id="user-notification-settings-tenancy">
+    <preConditions>
+      <tableExists tableName="user_notification_settings"/>
+      <not>
+        <columnExists tableName="user_notification_settings" columnName="tenant_id"/>
+      </not>
+    </preConditions>
+    <addColumn tableName="user_notification_settings">
+      <column name="tenant_id" type="text"/>
+    </addColumn>
+    <update tableName="user_notification_settings">
+      <column name="tenant_id" value="default"/>
+    </update>
+  </changeSet>
+
+  <changeSet author="grafjo" id="overtime-tenancy">
+    <preConditions>
+      <tableExists tableName="overtime"/>
+      <not>
+        <columnExists tableName="overtime" columnName="tenant_id"/>
+      </not>
+    </preConditions>
+    <addColumn tableName="overtime">
+      <column name="tenant_id" type="text"/>
+    </addColumn>
+    <update tableName="overtime">
+      <column name="tenant_id" value="default"/>
+    </update>
+  </changeSet>
+
+  <changeSet author="grafjo" id="overtime-comment-tenancy">
+    <preConditions>
+      <tableExists tableName="overtime_comment"/>
+      <not>
+        <columnExists tableName="overtime_comment" columnName="tenant_id"/>
+      </not>
+    </preConditions>
+    <addColumn tableName="overtime_comment">
+      <column name="tenant_id" type="text"/>
+    </addColumn>
+    <update tableName="overtime_comment">
+      <column name="tenant_id" value="default"/>
+    </update>
+  </changeSet>
+
+  <changeSet author="grafjo" id="person-tenancy">
+    <preConditions>
+      <tableExists tableName="person"/>
+      <not>
+        <columnExists tableName="person" columnName="tenant_id"/>
+      </not>
+    </preConditions>
+    <addColumn tableName="person">
+      <column name="tenant_id" type="text"/>
+    </addColumn>
+    <update tableName="person">
+      <column name="tenant_id" value="default"/>
+    </update>
+  </changeSet>
+
+  <changeSet author="grafjo" id="person-basedata-tenancy">
+    <preConditions>
+      <tableExists tableName="person_basedata"/>
+      <not>
+        <columnExists tableName="person_basedata" columnName="tenant_id"/>
+      </not>
+    </preConditions>
+    <addColumn tableName="person_basedata">
+      <column name="tenant_id" type="text"/>
+    </addColumn>
+    <update tableName="person_basedata">
+      <column name="tenant_id" value="default"/>
+    </update>
+  </changeSet>
+
+  <changeSet author="grafjo" id="settings-tenancy">
+    <preConditions>
+      <tableExists tableName="settings"/>
+      <not>
+        <columnExists tableName="settings" columnName="tenant_id"/>
+      </not>
+    </preConditions>
+    <addColumn tableName="settings">
+      <column name="tenant_id" type="text"/>
+    </addColumn>
+    <update tableName="settings">
+      <column name="tenant_id" value="default"/>
+    </update>
+  </changeSet>
+
+  <changeSet author="grafjo" id="sick-note-tenancy">
+    <preConditions>
+      <tableExists tableName="sick_note"/>
+      <not>
+        <columnExists tableName="sick_note" columnName="tenant_id"/>
+      </not>
+    </preConditions>
+    <addColumn tableName="sick_note">
+      <column name="tenant_id" type="text"/>
+    </addColumn>
+    <update tableName="sick_note">
+      <column name="tenant_id" value="default"/>
+    </update>
+  </changeSet>
+
+  <changeSet author="grafjo" id="sick-note-type-tenancy">
+    <preConditions>
+      <tableExists tableName="sick_note_type"/>
+      <not>
+        <columnExists tableName="sick_note_type" columnName="tenant_id"/>
+      </not>
+    </preConditions>
+    <addColumn tableName="sick_note_type">
+      <column name="tenant_id" type="text"/>
+    </addColumn>
+    <update tableName="sick_note_type">
+      <column name="tenant_id" value="default"/>
+    </update>
+  </changeSet>
+
+  <changeSet author="grafjo" id="sick-note-comment-tenancy">
+    <preConditions>
+      <tableExists tableName="sick_note_comment"/>
+      <not>
+        <columnExists tableName="sick_note_comment" columnName="tenant_id"/>
+      </not>
+    </preConditions>
+    <addColumn tableName="sick_note_comment">
+      <column name="tenant_id" type="text"/>
+    </addColumn>
+    <update tableName="sick_note_comment">
+      <column name="tenant_id" value="default"/>
+    </update>
+  </changeSet>
+
+  <changeSet author="grafjo" id="sick-note-extension-tenancy">
+    <preConditions>
+      <tableExists tableName="sick_note_extension"/>
+      <not>
+        <columnExists tableName="sick_note_extension" columnName="tenant_id"/>
+      </not>
+    </preConditions>
+    <addColumn tableName="sick_note_extension">
+      <column name="tenant_id" type="text"/>
+    </addColumn>
+    <update tableName="sick_note_extension">
+      <column name="tenant_id" value="default"/>
+    </update>
+  </changeSet>
+
+  <changeSet author="grafjo" id="user-pagination-settings-tenancy">
+    <preConditions>
+      <tableExists tableName="user_pagination_settings"/>
+      <not>
+        <columnExists tableName="user_pagination_settings" columnName="tenant_id"/>
+      </not>
+    </preConditions>
+    <addColumn tableName="user_pagination_settings">
+      <column name="tenant_id" type="text"/>
+    </addColumn>
+    <update tableName="user_pagination_settings">
+      <column name="tenant_id" value="default"/>
+    </update>
+  </changeSet>
+
+  <changeSet author="grafjo" id="user-settings-tenancy">
+    <preConditions>
+      <tableExists tableName="user_settings"/>
+      <not>
+        <columnExists tableName="user_settings" columnName="tenant_id"/>
+      </not>
+    </preConditions>
+    <addColumn tableName="user_settings">
+      <column name="tenant_id" type="text"/>
+    </addColumn>
+    <update tableName="user_settings">
+      <column name="tenant_id" value="default"/>
+    </update>
+  </changeSet>
+
+  <changeSet author="grafjo" id="working-time-tenancy">
+    <preConditions>
+      <tableExists tableName="working_time"/>
+      <not>
+        <columnExists tableName="working_time" columnName="tenant_id"/>
+      </not>
+    </preConditions>
+    <addColumn tableName="working_time">
+      <column name="tenant_id" type="text"/>
+    </addColumn>
+    <update tableName="working_time">
+      <column name="tenant_id" value="default"/>
+    </update>
+  </changeSet>
+
+</databaseChangeLog>
diff --git a/src/main/resources/dbchangelogs/changelogmaster.xml b/src/main/resources/dbchangelogs/changelogmaster.xml
index 935a57768..b61f4af7c 100644
--- a/src/main/resources/dbchangelogs/changelogmaster.xml
+++ b/src/main/resources/dbchangelogs/changelogmaster.xml
@@ -12,4 +12,7 @@
   <include relativeToChangelogFile="true" file="changelog-5.4.0-sicknote-submission-by-user.xml"/>
   <include relativeToChangelogFile="true" file="changelog-5.6.0-trim-person.xml"/>
   <include relativeToChangelogFile="true" file="changelog-5.7.0-add-sicknote-extension.xml"/>
+  <include relativeToChangelogFile="true" file="changelog-5.10.0-singletenant.xml"/>
+  <include relativeToChangelogFile="true" file="changelog-5.10.0-sick-note-type-seq.xml"/>
+
 </databaseChangeLog>


Test patch:
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/EntityArchTest.java b/src/test/java/org/synyx/urlaubsverwaltung/EntityArchTest.java
new file mode 100644
index 000000000..ca3e216d3
--- /dev/null
+++ b/src/test/java/org/synyx/urlaubsverwaltung/EntityArchTest.java
@@ -0,0 +1,22 @@
+package org.synyx.urlaubsverwaltung;
+
+import com.tngtech.archunit.core.domain.JavaClasses;
+import com.tngtech.archunit.junit.AnalyzeClasses;
+import com.tngtech.archunit.junit.ArchTest;
+import com.tngtech.archunit.lang.syntax.ArchRuleDefinition;
+import jakarta.persistence.Entity;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.AbstractTenantAwareEntity;
+
+@AnalyzeClasses(packages = "org.synyx.urlaubsverwaltung")
+class EntityArchTest {
+
+    @ArchTest
+    void ensureEntityClassesExtendAbstractTenantAwareEntity(JavaClasses classes) {
+        ArchRuleDefinition.classes()
+            .that().areAnnotatedWith(Entity.class)
+            .should().beAssignableTo(AbstractTenantAwareEntity.class)
+            .andShould().bePublic()
+            .check(classes);
+    }
+
+}
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/SingleTenantArchTest.java b/src/test/java/org/synyx/urlaubsverwaltung/SingleTenantArchTest.java
new file mode 100644
index 000000000..fcc72fc8b
--- /dev/null
+++ b/src/test/java/org/synyx/urlaubsverwaltung/SingleTenantArchTest.java
@@ -0,0 +1,84 @@
+package org.synyx.urlaubsverwaltung;
+
+import com.tngtech.archunit.base.DescribedPredicate;
+import com.tngtech.archunit.core.domain.JavaAnnotation;
+import com.tngtech.archunit.core.domain.JavaClass;
+import com.tngtech.archunit.core.domain.JavaClasses;
+import com.tngtech.archunit.core.domain.JavaMethod;
+import com.tngtech.archunit.core.importer.ImportOption.DoNotIncludeTests;
+import com.tngtech.archunit.junit.AnalyzeClasses;
+import com.tngtech.archunit.junit.ArchTest;
+import org.springframework.boot.context.event.ApplicationReadyEvent;
+import org.springframework.boot.context.event.ApplicationStartedEvent;
+import org.springframework.context.event.EventListener;
+import org.springframework.scheduling.annotation.SchedulingConfigurer;
+import org.synyx.urlaubsverwaltung.tenancy.configuration.single.ConditionalOnSingleTenantMode;
+
+import java.lang.annotation.Annotation;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Predicate;
+
+import static com.tngtech.archunit.base.DescribedPredicate.describe;
+import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;
+
+@AnalyzeClasses(
+    packages = "org.synyx.urlaubsverwaltung",
+    importOptions = {DoNotIncludeTests.class}
+)
+class SingleTenantArchTest {
+
+
+    @ArchTest
+    void ensureSchedulingConfigurerIsAnnotatedWithConditional(JavaClasses classes) {
+        classes()
+            .that().implement(SchedulingConfigurer.class)
+            .should().beAnnotatedWith(ConditionalOnSingleTenantMode.class)
+            .check(classes);
+    }
+
+
+    @ArchTest
+    void ensureApplicationStartedOrReadyEventListenerClassesAreAnnotatedWithConditional(JavaClasses classes) {
+
+        final DescribedPredicate<JavaMethod> listeningToApplicationStarted =
+            describe("is annotated with @EventListener(ApplicationStartedEvent)", isListeningTo(ApplicationStartedEvent.class));
+
+        final DescribedPredicate<JavaMethod> listeningToApplicationReady =
+            describe("is annotated with @EventListener(ApplicationReadyEvent)", isListeningTo(ApplicationReadyEvent.class));
+
+        classes()
+            .that().containAnyMethodsThat(listeningToApplicationReady)
+            .or().containAnyMethodsThat(listeningToApplicationStarted)
+            .should().beAnnotatedWith(ConditionalOnSingleTenantMode.class)
+            .check(classes);
+    }
+
+    private static Predicate<JavaMethod> isListeningTo(Class<?> event) {
+        return method ->
+            method.getAnnotations().stream()
+                .anyMatch(annotation -> as(annotation, EventListener.class)
+                    .map(eventListener -> contains(method.getRawParameterTypes(), event) || contains(eventListener.classes(), event) || contains(eventListener.value(), event))
+                    .orElse(false));
+    }
+
+    private static boolean contains(Class<?>[] classes, Class<?> event) {
+        return List.of(classes).contains(event);
+    }
+
+    private static boolean contains(List<JavaClass> javaClasses, Class<?> event) {
+        return javaClasses.stream().anyMatch(c -> c.isAssignableTo(event));
+    }
+
+    private static <A extends Annotation> Optional<A> as(JavaAnnotation<?> annotation, Class<A> annotationType) {
+        if (isEquivalentTo(annotation, annotationType)) {
+            return Optional.of(annotation.as(annotationType));
+        } else {
+            return Optional.empty();
+        }
+    }
+
+    private static boolean isEquivalentTo(JavaAnnotation<?> annotation, Class<?> annotationType) {
+        return annotation.getRawType().isEquivalentTo(annotationType);
+    }
+}
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/TestContainersBase.java b/src/test/java/org/synyx/urlaubsverwaltung/SingleTenantTestContainersBase.java
similarity index 68%
rename from src/test/java/org/synyx/urlaubsverwaltung/TestContainersBase.java
rename to src/test/java/org/synyx/urlaubsverwaltung/SingleTenantTestContainersBase.java
index 73c4a5fd3..f6417d3f8 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/TestContainersBase.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/SingleTenantTestContainersBase.java
@@ -3,9 +3,9 @@ package org.synyx.urlaubsverwaltung;
 import org.springframework.test.context.DynamicPropertyRegistry;
 import org.springframework.test.context.DynamicPropertySource;
 
-public abstract class TestContainersBase {
+public abstract class SingleTenantTestContainersBase {
 
-    static final TestPostgreSQLContainer postgre = new TestPostgreSQLContainer();
+    static final SingleTenantTestPostgreSQLContainer postgre = new SingleTenantTestPostgreSQLContainer();
 
     @DynamicPropertySource
     static void registerProperties(DynamicPropertyRegistry registry) {
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/TestPostgreSQLContainer.java b/src/test/java/org/synyx/urlaubsverwaltung/SingleTenantTestPostgreSQLContainer.java
similarity index 78%
rename from src/test/java/org/synyx/urlaubsverwaltung/TestPostgreSQLContainer.java
rename to src/test/java/org/synyx/urlaubsverwaltung/SingleTenantTestPostgreSQLContainer.java
index 7d19e1921..afec9b5de 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/TestPostgreSQLContainer.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/SingleTenantTestPostgreSQLContainer.java
@@ -3,11 +3,11 @@ package org.synyx.urlaubsverwaltung;
 import org.springframework.test.context.DynamicPropertyRegistry;
 import org.testcontainers.containers.PostgreSQLContainer;
 
-public class TestPostgreSQLContainer extends PostgreSQLContainer<TestPostgreSQLContainer> {
+public class SingleTenantTestPostgreSQLContainer extends PostgreSQLContainer<SingleTenantTestPostgreSQLContainer> {
 
     private static final String VERSION = "15.3";
 
-    public TestPostgreSQLContainer() {
+    public SingleTenantTestPostgreSQLContainer() {
         super(IMAGE + ":" + VERSION);
         this.withCommand("--max_connections=1000", "--shared_buffers=240MB");
     }
@@ -17,7 +17,7 @@ public class TestPostgreSQLContainer extends PostgreSQLContainer<TestPostgreSQLC
      *
      * <p>Usage:</p>
      * <pre><code>
-     * static final TestPostgreContainer postgre = new TestPostgreContainer();
+     * static final SingleTenantTestPostgreSQLContainer postgre = new SingleTenantTestPostgreSQLContainer();
      * &#64;DynamicPropertySource
      * static void setupDataSource(DynamicPropertySource registry) {
      *     postgre.start();
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/absence/AbsenceApiControllerSecurityIT.java b/src/test/java/org/synyx/urlaubsverwaltung/absence/AbsenceApiControllerSecurityIT.java
index 3f3e4a4fb..1b54ff756 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/absence/AbsenceApiControllerSecurityIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/absence/AbsenceApiControllerSecurityIT.java
@@ -11,7 +11,7 @@ import org.springframework.test.web.servlet.ResultActions;
 import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 import org.springframework.web.context.WebApplicationContext;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.department.Department;
 import org.synyx.urlaubsverwaltung.department.DepartmentService;
 import org.synyx.urlaubsverwaltung.person.Person;
@@ -36,7 +36,7 @@ import static org.synyx.urlaubsverwaltung.person.Role.DEPARTMENT_HEAD;
 import static org.synyx.urlaubsverwaltung.person.Role.SECOND_STAGE_AUTHORITY;
 
 @SpringBootTest
-class AbsenceApiControllerSecurityIT extends TestContainersBase {
+class AbsenceApiControllerSecurityIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private WebApplicationContext context;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/account/AccountRepositoryIT.java b/src/test/java/org/synyx/urlaubsverwaltung/account/AccountRepositoryIT.java
index 57e883316..09f395acf 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/account/AccountRepositoryIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/account/AccountRepositoryIT.java
@@ -5,7 +5,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.dao.DataIntegrityViolationException;
 import org.springframework.transaction.annotation.Transactional;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonService;
 
@@ -21,7 +21,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 @SpringBootTest
 @Transactional
-class AccountRepositoryIT extends TestContainersBase {
+class AccountRepositoryIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private AccountRepository sut;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/account/TurnOfTheYearAccountUpdaterServiceIT.java b/src/test/java/org/synyx/urlaubsverwaltung/account/TurnOfTheYearAccountUpdaterServiceIT.java
index bea530c01..dee00e5fb 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/account/TurnOfTheYearAccountUpdaterServiceIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/account/TurnOfTheYearAccountUpdaterServiceIT.java
@@ -14,7 +14,7 @@ import org.springframework.boot.test.context.TestConfiguration;
 import org.springframework.context.annotation.Bean;
 import org.springframework.test.context.bean.override.mockito.MockitoBean;
 import org.springframework.transaction.annotation.Transactional;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonService;
 
@@ -34,7 +34,7 @@ import static org.synyx.urlaubsverwaltung.person.Role.OFFICE;
 
 @SpringBootTest(properties = {"spring.mail.port=3025", "spring.mail.host=localhost", "spring.main.allow-bean-definition-overriding=true"})
 @Transactional
-class TurnOfTheYearAccountUpdaterServiceIT extends TestContainersBase {
+class TurnOfTheYearAccountUpdaterServiceIT extends SingleTenantTestContainersBase {
 
     @RegisterExtension
     static final GreenMailExtension greenMail = new GreenMailExtension(ServerSetupTest.SMTP_IMAP);
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/account/VacationDaysReminderServiceIT.java b/src/test/java/org/synyx/urlaubsverwaltung/account/VacationDaysReminderServiceIT.java
index a3db926a0..2e353ce16 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/account/VacationDaysReminderServiceIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/account/VacationDaysReminderServiceIT.java
@@ -11,7 +11,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.context.bean.override.mockito.MockitoBean;
 import org.springframework.transaction.annotation.Transactional;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.mail.MailService;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonService;
@@ -32,7 +32,7 @@ import static org.mockito.Mockito.when;
 
 @SpringBootTest(properties = {"spring.mail.port=3025", "spring.mail.host=localhost"})
 @Transactional
-class VacationDaysReminderServiceIT extends TestContainersBase {
+class VacationDaysReminderServiceIT extends SingleTenantTestContainersBase {
 
     @RegisterExtension
     static final GreenMailExtension greenMail = new GreenMailExtension(SMTP_IMAP);
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/application/application/ApplicationMailServiceIT.java b/src/test/java/org/synyx/urlaubsverwaltung/application/application/ApplicationMailServiceIT.java
index 43d7055be..549051c8b 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/application/application/ApplicationMailServiceIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/application/application/ApplicationMailServiceIT.java
@@ -18,7 +18,7 @@ import org.springframework.context.MessageSource;
 import org.springframework.context.annotation.Bean;
 import org.springframework.test.context.bean.override.mockito.MockitoBean;
 import org.springframework.transaction.annotation.Transactional;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.application.comment.ApplicationComment;
 import org.synyx.urlaubsverwaltung.application.comment.ApplicationCommentAction;
 import org.synyx.urlaubsverwaltung.department.DepartmentService;
@@ -81,7 +81,7 @@ import static org.synyx.urlaubsverwaltung.person.Role.USER;
 
 @SpringBootTest(properties = {"spring.mail.port=3025", "spring.mail.host=localhost", "spring.main.allow-bean-definition-overriding=true"})
 @Transactional
-class ApplicationMailServiceIT extends TestContainersBase {
+class ApplicationMailServiceIT extends SingleTenantTestContainersBase {
 
     @RegisterExtension
     static final GreenMailExtension greenMail = new GreenMailExtension(ServerSetupTest.SMTP_IMAP);
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/application/application/ApplicationRepositoryIT.java b/src/test/java/org/synyx/urlaubsverwaltung/application/application/ApplicationRepositoryIT.java
index bff77ec13..e75cbae2d 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/application/application/ApplicationRepositoryIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/application/application/ApplicationRepositoryIT.java
@@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.transaction.annotation.Transactional;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.application.vacationtype.VacationCategory;
 import org.synyx.urlaubsverwaltung.application.vacationtype.VacationTypeEntity;
 import org.synyx.urlaubsverwaltung.application.vacationtype.VacationTypeService;
@@ -40,7 +40,7 @@ import static org.synyx.urlaubsverwaltung.period.DayLength.NOON;
 
 @SpringBootTest
 @Transactional
-class ApplicationRepositoryIT extends TestContainersBase {
+class ApplicationRepositoryIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private ApplicationRepository sut;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/application/comment/ApplicationCommentRepositoryIT.java b/src/test/java/org/synyx/urlaubsverwaltung/application/comment/ApplicationCommentRepositoryIT.java
index e59e2667f..cf8b0d915 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/application/comment/ApplicationCommentRepositoryIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/application/comment/ApplicationCommentRepositoryIT.java
@@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.transaction.annotation.Transactional;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.application.application.Application;
 import org.synyx.urlaubsverwaltung.application.application.ApplicationService;
 import org.synyx.urlaubsverwaltung.application.vacationtype.VacationType;
@@ -20,7 +20,7 @@ import static org.synyx.urlaubsverwaltung.application.comment.ApplicationComment
 
 @SpringBootTest
 @Transactional
-class ApplicationCommentRepositoryIT extends TestContainersBase {
+class ApplicationCommentRepositoryIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private ApplicationCommentRepository sut;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/application/vacationtype/VacationTypeEntityRepositoryIT.java b/src/test/java/org/synyx/urlaubsverwaltung/application/vacationtype/VacationTypeEntityRepositoryIT.java
index fa8d198a4..ae85455f0 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/application/vacationtype/VacationTypeEntityRepositoryIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/application/vacationtype/VacationTypeEntityRepositoryIT.java
@@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.transaction.annotation.Transactional;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 
 import java.util.List;
 import java.util.Locale;
@@ -17,7 +17,7 @@ import static org.synyx.urlaubsverwaltung.application.vacationtype.VacationTypeC
 
 @SpringBootTest
 @Transactional
-class VacationTypeEntityRepositoryIT extends TestContainersBase {
+class VacationTypeEntityRepositoryIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private VacationTypeRepository sut;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/calendar/CalendarSharingViewControllerCompanyCalendarSecurityIT.java b/src/test/java/org/synyx/urlaubsverwaltung/calendar/CalendarSharingViewControllerCompanyCalendarSecurityIT.java
index dd565cb27..b15680be7 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/calendar/CalendarSharingViewControllerCompanyCalendarSecurityIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/calendar/CalendarSharingViewControllerCompanyCalendarSecurityIT.java
@@ -10,7 +10,7 @@ import org.springframework.test.context.bean.override.mockito.MockitoBean;
 import org.springframework.test.web.servlet.ResultActions;
 import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
 import org.springframework.web.context.WebApplicationContext;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.department.DepartmentService;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonService;
@@ -27,7 +27,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
 import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
 
 @SpringBootTest
-class CalendarSharingViewControllerCompanyCalendarSecurityIT extends TestContainersBase {
+class CalendarSharingViewControllerCompanyCalendarSecurityIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private WebApplicationContext context;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/calendar/CalendarSharingViewControllerDepartmentCalendarSecurityIT.java b/src/test/java/org/synyx/urlaubsverwaltung/calendar/CalendarSharingViewControllerDepartmentCalendarSecurityIT.java
index 60e1b9e1f..fba470011 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/calendar/CalendarSharingViewControllerDepartmentCalendarSecurityIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/calendar/CalendarSharingViewControllerDepartmentCalendarSecurityIT.java
@@ -5,12 +5,12 @@ import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.ValueSource;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.bean.override.mockito.MockitoBean;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.test.context.bean.override.mockito.MockitoBean;
 import org.springframework.test.web.servlet.ResultActions;
 import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
 import org.springframework.web.context.WebApplicationContext;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.department.Department;
 import org.synyx.urlaubsverwaltung.department.DepartmentService;
 import org.synyx.urlaubsverwaltung.person.Person;
@@ -32,7 +32,7 @@ import static org.synyx.urlaubsverwaltung.TestDataCreator.createPerson;
 import static org.synyx.urlaubsverwaltung.person.Role.BOSS;
 
 @SpringBootTest
-class CalendarSharingViewControllerDepartmentCalendarSecurityIT extends TestContainersBase {
+class CalendarSharingViewControllerDepartmentCalendarSecurityIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private WebApplicationContext context;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/calendar/CalendarSharingViewControllerPersonCalendarSecurityIT.java b/src/test/java/org/synyx/urlaubsverwaltung/calendar/CalendarSharingViewControllerPersonCalendarSecurityIT.java
index 78d0634b2..a0c39d994 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/calendar/CalendarSharingViewControllerPersonCalendarSecurityIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/calendar/CalendarSharingViewControllerPersonCalendarSecurityIT.java
@@ -5,12 +5,12 @@ import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.ValueSource;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.bean.override.mockito.MockitoBean;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.test.context.bean.override.mockito.MockitoBean;
 import org.springframework.test.web.servlet.ResultActions;
 import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
 import org.springframework.web.context.WebApplicationContext;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.department.DepartmentService;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonService;
@@ -29,7 +29,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
 import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
 
 @SpringBootTest
-class CalendarSharingViewControllerPersonCalendarSecurityIT extends TestContainersBase {
+class CalendarSharingViewControllerPersonCalendarSecurityIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private WebApplicationContext context;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/calendar/CompanyCalendarRepositoryIT.java b/src/test/java/org/synyx/urlaubsverwaltung/calendar/CompanyCalendarRepositoryIT.java
index 73832a03d..52370037b 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/calendar/CompanyCalendarRepositoryIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/calendar/CompanyCalendarRepositoryIT.java
@@ -5,7 +5,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.dao.DataIntegrityViolationException;
 import org.springframework.transaction.annotation.Transactional;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonService;
 
@@ -16,7 +16,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
 
 @SpringBootTest
 @Transactional
-class CompanyCalendarRepositoryIT extends TestContainersBase {
+class CompanyCalendarRepositoryIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private PersonService personService;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/calendar/DepartmentCalendarRepositoryIT.java b/src/test/java/org/synyx/urlaubsverwaltung/calendar/DepartmentCalendarRepositoryIT.java
index bbcdc0328..9e62fd879 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/calendar/DepartmentCalendarRepositoryIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/calendar/DepartmentCalendarRepositoryIT.java
@@ -7,7 +7,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.dao.DataIntegrityViolationException;
 import org.springframework.transaction.annotation.Transactional;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.department.Department;
 import org.synyx.urlaubsverwaltung.department.DepartmentService;
 import org.synyx.urlaubsverwaltung.person.Person;
@@ -22,7 +22,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
 
 @SpringBootTest
 @Transactional
-class DepartmentCalendarRepositoryIT extends TestContainersBase {
+class DepartmentCalendarRepositoryIT extends SingleTenantTestContainersBase {
 
     @PersistenceContext
     private EntityManager entityManager;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/calendar/ICalViewControllerSecurityIT.java b/src/test/java/org/synyx/urlaubsverwaltung/calendar/ICalViewControllerSecurityIT.java
index 5f144353a..8d480a53c 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/calendar/ICalViewControllerSecurityIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/calendar/ICalViewControllerSecurityIT.java
@@ -3,12 +3,12 @@ package org.synyx.urlaubsverwaltung.calendar;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.bean.override.mockito.MockitoBean;
 import org.springframework.core.io.ByteArrayResource;
+import org.springframework.test.context.bean.override.mockito.MockitoBean;
 import org.springframework.test.web.servlet.ResultActions;
 import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
 import org.springframework.web.context.WebApplicationContext;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 
 import static java.util.Locale.GERMAN;
 import static org.mockito.Mockito.when;
@@ -18,7 +18,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
 import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
 
 @SpringBootTest
-class ICalViewControllerSecurityIT extends TestContainersBase {
+class ICalViewControllerSecurityIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private WebApplicationContext context;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/calendar/PersonCalendarRepositoryIT.java b/src/test/java/org/synyx/urlaubsverwaltung/calendar/PersonCalendarRepositoryIT.java
index edff0fcb9..ac0f97dba 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/calendar/PersonCalendarRepositoryIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/calendar/PersonCalendarRepositoryIT.java
@@ -5,7 +5,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.dao.DataIntegrityViolationException;
 import org.springframework.transaction.annotation.Transactional;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonService;
 
@@ -16,7 +16,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
 
 @SpringBootTest
 @Transactional
-class PersonCalendarRepositoryIT extends TestContainersBase {
+class PersonCalendarRepositoryIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private PersonService personService;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/calendar/PersonDisabledListenerIT.java b/src/test/java/org/synyx/urlaubsverwaltung/calendar/PersonDisabledListenerIT.java
index 5461b5bc7..19161d789 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/calendar/PersonDisabledListenerIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/calendar/PersonDisabledListenerIT.java
@@ -3,17 +3,17 @@ package org.synyx.urlaubsverwaltung.calendar;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.bean.override.mockito.MockitoBean;
 import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.test.context.ContextConfiguration;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.springframework.test.context.bean.override.mockito.MockitoBean;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.person.PersonDisabledEvent;
 
 import static org.mockito.Mockito.verify;
 
 @SpringBootTest
 @ContextConfiguration(classes = {PersonDisabledListener.class})
-class PersonDisabledListenerIT extends TestContainersBase {
+class PersonDisabledListenerIT extends SingleTenantTestContainersBase {
 
     @MockitoBean
     private PersonCalendarService personCalendarService;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/calendar/PersonLeftDepartmentListenerIT.java b/src/test/java/org/synyx/urlaubsverwaltung/calendar/PersonLeftDepartmentListenerIT.java
index b562438fb..72900e1f9 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/calendar/PersonLeftDepartmentListenerIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/calendar/PersonLeftDepartmentListenerIT.java
@@ -3,17 +3,17 @@ package org.synyx.urlaubsverwaltung.calendar;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.bean.override.mockito.MockitoBean;
 import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.test.context.ContextConfiguration;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.springframework.test.context.bean.override.mockito.MockitoBean;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.department.PersonLeftDepartmentEvent;
 
 import static org.mockito.Mockito.verify;
 
 @SpringBootTest
 @ContextConfiguration(classes = {PersonLeftDepartmentListener.class})
-class PersonLeftDepartmentListenerIT extends TestContainersBase {
+class PersonLeftDepartmentListenerIT extends SingleTenantTestContainersBase {
 
     @MockitoBean
     private DepartmentCalendarService departmentCalendarService;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/department/DepartmentRepositoryIT.java b/src/test/java/org/synyx/urlaubsverwaltung/department/DepartmentRepositoryIT.java
index 4a1d4a547..0910508c2 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/department/DepartmentRepositoryIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/department/DepartmentRepositoryIT.java
@@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.transaction.annotation.Transactional;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonService;
 
@@ -19,7 +19,7 @@ import static org.synyx.urlaubsverwaltung.person.Role.USER;
 
 @SpringBootTest
 @Transactional
-class DepartmentRepositoryIT extends TestContainersBase {
+class DepartmentRepositoryIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private DepartmentRepository sut;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/department/api/DepartmentApiControllerSecurityIT.java b/src/test/java/org/synyx/urlaubsverwaltung/department/api/DepartmentApiControllerSecurityIT.java
index 22ad2c55a..5beb3fd6c 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/department/api/DepartmentApiControllerSecurityIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/department/api/DepartmentApiControllerSecurityIT.java
@@ -10,7 +10,7 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority;
 import org.springframework.test.web.servlet.ResultActions;
 import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
 import org.springframework.web.context.WebApplicationContext;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 
 import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.oidcLogin;
 import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
@@ -19,7 +19,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
 import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
 
 @SpringBootTest
-class DepartmentApiControllerSecurityIT extends TestContainersBase {
+class DepartmentApiControllerSecurityIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private WebApplicationContext context;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/overtime/OvertimeMailServiceIT.java b/src/test/java/org/synyx/urlaubsverwaltung/overtime/OvertimeMailServiceIT.java
index abbac8dcd..87586d28e 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/overtime/OvertimeMailServiceIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/overtime/OvertimeMailServiceIT.java
@@ -10,7 +10,7 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.transaction.annotation.Transactional;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonService;
 
@@ -30,7 +30,7 @@ import static org.synyx.urlaubsverwaltung.person.Role.USER;
 
 @SpringBootTest(properties = {"spring.mail.port=3025", "spring.mail.host=localhost"})
 @Transactional
-class OvertimeMailServiceIT extends TestContainersBase {
+class OvertimeMailServiceIT extends SingleTenantTestContainersBase {
 
     @RegisterExtension
     static final GreenMailExtension greenMail = new GreenMailExtension(ServerSetupTest.SMTP_IMAP);
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/overtime/OvertimeRepositoryIT.java b/src/test/java/org/synyx/urlaubsverwaltung/overtime/OvertimeRepositoryIT.java
index c7ea04e5d..d8150ab65 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/overtime/OvertimeRepositoryIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/overtime/OvertimeRepositoryIT.java
@@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.transaction.annotation.Transactional;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonService;
 
@@ -19,7 +19,7 @@ import static org.assertj.core.api.Assertions.assertThat;
 
 @SpringBootTest
 @Transactional
-class OvertimeRepositoryIT extends TestContainersBase {
+class OvertimeRepositoryIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private PersonService personService;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/person/PersonMailServiceIT.java b/src/test/java/org/synyx/urlaubsverwaltung/person/PersonMailServiceIT.java
index 920735513..953fb9463 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/person/PersonMailServiceIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/person/PersonMailServiceIT.java
@@ -11,7 +11,7 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.transaction.annotation.Transactional;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.person.web.PersonPermissionsRoleDto;
 
 import java.io.IOException;
@@ -26,7 +26,7 @@ import static org.synyx.urlaubsverwaltung.person.web.PersonPermissionsRoleDto.SE
 
 @SpringBootTest(properties = {"spring.mail.port=3025", "spring.mail.host=localhost"})
 @Transactional
-class PersonMailServiceIT extends TestContainersBase {
+class PersonMailServiceIT extends SingleTenantTestContainersBase {
 
     @RegisterExtension
     static final GreenMailExtension greenMail = new GreenMailExtension(ServerSetupTest.SMTP_IMAP);
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/person/PersonRepositoryIT.java b/src/test/java/org/synyx/urlaubsverwaltung/person/PersonRepositoryIT.java
index 1dc3d20ba..6745a8796 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/person/PersonRepositoryIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/person/PersonRepositoryIT.java
@@ -6,7 +6,7 @@ import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageRequest;
 import org.springframework.transaction.annotation.Transactional;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 
 import java.util.List;
 
@@ -18,7 +18,7 @@ import static org.synyx.urlaubsverwaltung.person.Role.USER;
 
 @SpringBootTest
 @Transactional
-class PersonRepositoryIT extends TestContainersBase {
+class PersonRepositoryIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private PersonRepository sut;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/person/PersonServiceIT.java b/src/test/java/org/synyx/urlaubsverwaltung/person/PersonServiceIT.java
index 4923740bf..0ba3d562e 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/person/PersonServiceIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/person/PersonServiceIT.java
@@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.transaction.annotation.Transactional;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.application.application.Application;
 import org.synyx.urlaubsverwaltung.application.application.ApplicationService;
 import org.synyx.urlaubsverwaltung.application.application.HolidayReplacementEntity;
@@ -36,7 +36,7 @@ import static org.synyx.urlaubsverwaltung.person.Role.USER;
 
 @SpringBootTest
 @Transactional
-class PersonServiceIT extends TestContainersBase {
+class PersonServiceIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private PersonService personService;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/person/api/PersonApiControllerIT.java b/src/test/java/org/synyx/urlaubsverwaltung/person/api/PersonApiControllerIT.java
index 8faa75336..09198ff18 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/person/api/PersonApiControllerIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/person/api/PersonApiControllerIT.java
@@ -12,7 +12,7 @@ import org.springframework.test.web.servlet.ResultActions;
 import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 import org.springframework.web.context.WebApplicationContext;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonService;
 
@@ -33,7 +33,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
 
 @ExtendWith(MockitoExtension.class)
 @SpringBootTest
-class PersonApiControllerIT extends TestContainersBase {
+class PersonApiControllerIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private WebApplicationContext context;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/person/api/PersonApiControllerSecurityIT.java b/src/test/java/org/synyx/urlaubsverwaltung/person/api/PersonApiControllerSecurityIT.java
index 00cb6d325..07ebfe1e6 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/person/api/PersonApiControllerSecurityIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/person/api/PersonApiControllerSecurityIT.java
@@ -6,13 +6,13 @@ import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.ValueSource;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.bean.override.mockito.MockitoBean;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.test.context.bean.override.mockito.MockitoBean;
 import org.springframework.test.web.servlet.ResultActions;
 import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 import org.springframework.web.context.WebApplicationContext;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.department.DepartmentService;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonService;
@@ -31,7 +31,7 @@ import static org.synyx.urlaubsverwaltung.person.Role.DEPARTMENT_HEAD;
 import static org.synyx.urlaubsverwaltung.person.Role.USER;
 
 @SpringBootTest
-class PersonApiControllerSecurityIT extends TestContainersBase {
+class PersonApiControllerSecurityIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private WebApplicationContext context;
@@ -44,9 +44,9 @@ class PersonApiControllerSecurityIT extends TestContainersBase {
     @Test
     void ensureAccessIsUnAuthorizedIfNoAuthenticationIsAvailableOnCurrentPerson() throws Exception {
         perform(
-                get("/api/persons/me")
+            get("/api/persons/me")
         )
-                .andExpect(status().is4xxClientError());
+            .andExpect(status().is4xxClientError());
     }
 
     @Test
@@ -55,23 +55,23 @@ class PersonApiControllerSecurityIT extends TestContainersBase {
         when(personService.getPersonByUsername("shane@example.org")).thenReturn(Optional.of(new Person()));
 
         perform(get("/api/persons/me")
-                .with(oidcLogin().idToken(builder -> builder.subject("shane@example.org")).authorities(new SimpleGrantedAuthority("USER")))
+            .with(oidcLogin().idToken(builder -> builder.subject("shane@example.org")).authorities(new SimpleGrantedAuthority("USER")))
         ).andExpect(status().isOk());
     }
 
     @Test
     void ensureAccessIsUnAuthorizedIfNoAuthenticationIsAvailableOnSpecificPerson() throws Exception {
         perform(
-                get("/api/persons/1")
+            get("/api/persons/1")
         )
-                .andExpect(status().is4xxClientError());
+            .andExpect(status().is4xxClientError());
     }
 
     @ParameterizedTest
     @ValueSource(strings = {"USER", "INACTIVE"})
     void ensureAccessIsForbiddenForOtherUsersOnSpecificPerson(final String role) throws Exception {
         perform(get("/api/persons/1")
-                .with(oidcLogin().authorities(new SimpleGrantedAuthority("USER"), new SimpleGrantedAuthority(role)))
+            .with(oidcLogin().authorities(new SimpleGrantedAuthority("USER"), new SimpleGrantedAuthority(role)))
         ).andExpect(status().isForbidden());
     }
 
@@ -82,7 +82,7 @@ class PersonApiControllerSecurityIT extends TestContainersBase {
         when(personService.getPersonByID(1L)).thenReturn(Optional.of(new Person()));
 
         perform(get("/api/persons/1")
-                .with(oidcLogin().authorities(new SimpleGrantedAuthority("USER"), new SimpleGrantedAuthority(role)))
+            .with(oidcLogin().authorities(new SimpleGrantedAuthority("USER"), new SimpleGrantedAuthority(role)))
         ).andExpect(status().isOk());
     }
 
@@ -97,10 +97,10 @@ class PersonApiControllerSecurityIT extends TestContainersBase {
         when(departmentService.isDepartmentHeadAllowedToManagePerson(departmentHead, person)).thenReturn(true);
 
         perform(
-                get("/api/persons/1")
-                        .with(oidcLogin().idToken(builder -> builder.subject("departmentHead")).authorities(new SimpleGrantedAuthority("USER"), new SimpleGrantedAuthority("DEPARTMENT_HEAD")))
+            get("/api/persons/1")
+                .with(oidcLogin().idToken(builder -> builder.subject("departmentHead")).authorities(new SimpleGrantedAuthority("USER"), new SimpleGrantedAuthority("DEPARTMENT_HEAD")))
         )
-                .andExpect(status().isOk());
+            .andExpect(status().isOk());
     }
 
     @Test
@@ -114,10 +114,10 @@ class PersonApiControllerSecurityIT extends TestContainersBase {
         when(departmentService.isDepartmentHeadAllowedToManagePerson(departmentHead, person)).thenReturn(true);
 
         perform(
-                get("/api/persons/1")
-                        .with(oidcLogin().idToken(builder -> builder.subject("ssa")).authorities(new SimpleGrantedAuthority("USER"), new SimpleGrantedAuthority("SECOND_STAGE_AUTHORITY")))
+            get("/api/persons/1")
+                .with(oidcLogin().idToken(builder -> builder.subject("ssa")).authorities(new SimpleGrantedAuthority("USER"), new SimpleGrantedAuthority("SECOND_STAGE_AUTHORITY")))
         )
-                .andExpect(status().isOk());
+            .andExpect(status().isOk());
     }
 
     @Test
@@ -128,10 +128,10 @@ class PersonApiControllerSecurityIT extends TestContainersBase {
         when(personService.getPersonByID(1L)).thenReturn(Optional.of(person));
 
         perform(
-                get("/api/persons/1")
-                        .with(oidcLogin().idToken(builder -> builder.subject("user")).authorities(new SimpleGrantedAuthority("USER")))
+            get("/api/persons/1")
+                .with(oidcLogin().idToken(builder -> builder.subject("user")).authorities(new SimpleGrantedAuthority("USER")))
         )
-                .andExpect(status().isOk());
+            .andExpect(status().isOk());
     }
 
     @Test
@@ -142,10 +142,10 @@ class PersonApiControllerSecurityIT extends TestContainersBase {
         when(personService.getPersonByID(1L)).thenReturn(Optional.of(person));
 
         perform(
-                get("/api/persons/1")
-                        .with(oidcLogin().idToken(builder -> builder.subject("differentUser")).authorities(new SimpleGrantedAuthority("USER")))
+            get("/api/persons/1")
+                .with(oidcLogin().idToken(builder -> builder.subject("differentUser")).authorities(new SimpleGrantedAuthority("USER")))
         )
-                .andExpect(status().isForbidden());
+            .andExpect(status().isForbidden());
     }
 
     @Test
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/person/basedata/PersonBasedataViewControllerSecurityIT.java b/src/test/java/org/synyx/urlaubsverwaltung/person/basedata/PersonBasedataViewControllerSecurityIT.java
index 617cfc2cd..1d07b12e6 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/person/basedata/PersonBasedataViewControllerSecurityIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/person/basedata/PersonBasedataViewControllerSecurityIT.java
@@ -5,12 +5,12 @@ import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.ValueSource;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.bean.override.mockito.MockitoBean;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.test.context.bean.override.mockito.MockitoBean;
 import org.springframework.test.web.servlet.ResultActions;
 import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
 import org.springframework.web.context.WebApplicationContext;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonService;
 
@@ -28,7 +28,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
 import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
 
 @SpringBootTest
-class PersonBasedataViewControllerSecurityIT extends TestContainersBase {
+class PersonBasedataViewControllerSecurityIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private WebApplicationContext context;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/person/extension/PersonDTOMapperTest.java b/src/test/java/org/synyx/urlaubsverwaltung/person/extension/PersonDTOMapperTest.java
index 14b7975ba..737113e5c 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/person/extension/PersonDTOMapperTest.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/person/extension/PersonDTOMapperTest.java
@@ -1,6 +1,7 @@
 package org.synyx.urlaubsverwaltung.person.extension;
 
 
+import de.focus_shift.urlaubsverwaltung.extension.api.person.MailNotificationDTO;
 import de.focus_shift.urlaubsverwaltung.extension.api.person.PersonDTO;
 import de.focus_shift.urlaubsverwaltung.extension.api.person.RoleDTO;
 import org.junit.jupiter.api.Nested;
@@ -11,6 +12,7 @@ import org.synyx.urlaubsverwaltung.person.Role;
 import java.util.Set;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.synyx.urlaubsverwaltung.person.MailNotification.NOTIFICATION_EMAIL_APPLICATION_ALLOWED;
 import static org.synyx.urlaubsverwaltung.person.Role.INACTIVE;
 import static org.synyx.urlaubsverwaltung.person.Role.USER;
 
@@ -24,6 +26,7 @@ class PersonDTOMapperTest {
             final Person person = new Person("muster", "Muster", "Marlene", "muster@example.org");
             person.setId(1L);
             person.setPermissions(Set.of(USER));
+            person.setNotifications(Set.of(NOTIFICATION_EMAIL_APPLICATION_ALLOWED));
 
             final PersonDTO dto = PersonDTOMapper.toPersonDTO(person);
 
@@ -34,6 +37,7 @@ class PersonDTOMapperTest {
             assertThat(dto.getFirstName()).isEqualTo("Marlene");
             assertThat(dto.getEmail()).isEqualTo("muster@example.org");
             assertThat(dto.getPermissions()).containsOnly(RoleDTO.USER);
+            assertThat(dto.getNotifications()).containsOnly(MailNotificationDTO.NOTIFICATION_EMAIL_APPLICATION_ALLOWED);
             assertThat(dto.isEnabled()).isTrue();
         }
 
@@ -43,6 +47,7 @@ class PersonDTOMapperTest {
             final Person person = new Person("muster", "Muster", "Marlene", "muster@example.org");
             person.setId(1L);
             person.setPermissions(Set.of(INACTIVE));
+            person.setNotifications(Set.of(NOTIFICATION_EMAIL_APPLICATION_ALLOWED));
 
             final PersonDTO dto = PersonDTOMapper.toPersonDTO(person);
 
@@ -53,6 +58,7 @@ class PersonDTOMapperTest {
             assertThat(dto.getFirstName()).isEqualTo("Marlene");
             assertThat(dto.getEmail()).isEqualTo("muster@example.org");
             assertThat(dto.getPermissions()).isEmpty();
+            assertThat(dto.getNotifications()).containsOnly(MailNotificationDTO.NOTIFICATION_EMAIL_APPLICATION_ALLOWED);
             assertThat(dto.isEnabled()).isFalse();
         }
     }
@@ -70,6 +76,7 @@ class PersonDTOMapperTest {
                 .email("muster@example.org")
                 .enabled(true)
                 .permissions(Set.of(RoleDTO.USER))
+                .notifications(Set.of(MailNotificationDTO.NOTIFICATION_EMAIL_APPLICATION_ALLOWED))
                 .build();
 
             final Person person = PersonDTOMapper.toPerson(personDTO);
@@ -81,6 +88,7 @@ class PersonDTOMapperTest {
             assertThat(person.getFirstName()).isEqualTo("Marlene");
             assertThat(person.getEmail()).isEqualTo("muster@example.org");
             assertThat(person.getPermissions()).containsOnly(Role.USER);
+            assertThat(person.getNotifications()).containsOnly(NOTIFICATION_EMAIL_APPLICATION_ALLOWED);
             assertThat(person.isActive()).isTrue();
         }
 
@@ -94,6 +102,7 @@ class PersonDTOMapperTest {
                 .firstName("Marlene")
                 .email("muster@example.org")
                 .permissions(Set.of())
+                .notifications(Set.of(MailNotificationDTO.NOTIFICATION_EMAIL_APPLICATION_ALLOWED))
                 .build()
                 .disable();
 
@@ -106,6 +115,7 @@ class PersonDTOMapperTest {
             assertThat(person.getFirstName()).isEqualTo("Marlene");
             assertThat(person.getEmail()).isEqualTo("muster@example.org");
             assertThat(person.getPermissions()).containsOnly(INACTIVE);
+            assertThat(person.getNotifications()).containsOnly(NOTIFICATION_EMAIL_APPLICATION_ALLOWED);
             assertThat(person.isActive()).isFalse();
         }
     }
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/person/extension/PersonServiceExtensionImplTest.java b/src/test/java/org/synyx/urlaubsverwaltung/person/extension/PersonServiceExtensionImplTest.java
index 5bdde77a2..c79e4559c 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/person/extension/PersonServiceExtensionImplTest.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/person/extension/PersonServiceExtensionImplTest.java
@@ -1,6 +1,7 @@
 package org.synyx.urlaubsverwaltung.person.extension;
 
 
+import de.focus_shift.urlaubsverwaltung.extension.api.person.MailNotificationDTO;
 import de.focus_shift.urlaubsverwaltung.extension.api.person.PersonDTO;
 import de.focus_shift.urlaubsverwaltung.extension.api.person.RoleDTO;
 import org.junit.jupiter.api.Test;
@@ -12,6 +13,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageImpl;
 import org.springframework.data.domain.Sort;
+import org.synyx.urlaubsverwaltung.person.MailNotification;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonService;
 import org.synyx.urlaubsverwaltung.person.Role;
@@ -43,6 +45,7 @@ class PersonServiceExtensionImplTest {
         final Person createdPerson = new Person(personDTO.getUsername(), personDTO.getLastName(), personDTO.getFirstName(), personDTO.getEmail());
         createdPerson.setId(personDTO.getId());
         createdPerson.setPermissions(Set.of(Role.USER));
+        createdPerson.setNotifications(Set.of(MailNotification.NOTIFICATION_EMAIL_APPLICATION_ALLOWED));
         return createdPerson;
     }
 
@@ -59,6 +62,7 @@ class PersonServiceExtensionImplTest {
             .email("muster@example.org")
             .enabled(true)
             .permissions(Set.of(RoleDTO.USER))
+            .notifications(Set.of(MailNotificationDTO.NOTIFICATION_EMAIL_APPLICATION_ALLOWED))
             .build();
     }
 
@@ -68,6 +72,7 @@ class PersonServiceExtensionImplTest {
         final Person createdPerson = new Person("muster", "Muster", "Marlene", "muster@example.org");
         createdPerson.setId(1L);
         createdPerson.setPermissions(List.of(Role.USER));
+        createdPerson.setNotifications(List.of(MailNotification.NOTIFICATION_EMAIL_APPLICATION_ALLOWED));
         when(personService.create(any(String.class), any(String.class), any(String.class), any(String.class))).thenReturn(createdPerson);
 
         final PersonDTO createdDTO = sut.create(anyPersonDTO());
@@ -77,6 +82,7 @@ class PersonServiceExtensionImplTest {
         assertThat(createdDTO.getFirstName()).isEqualTo("Marlene");
         assertThat(createdDTO.getEmail()).isEqualTo("muster@example.org");
         assertThat(createdDTO.getPermissions()).containsOnly(RoleDTO.USER);
+        assertThat(createdDTO.getNotifications()).containsOnly(MailNotificationDTO.NOTIFICATION_EMAIL_APPLICATION_ALLOWED);
         assertThat(createdDTO.isEnabled()).isTrue();
     }
 
@@ -96,6 +102,7 @@ class PersonServiceExtensionImplTest {
         assertThat(updatedPersonDTO.getFirstName()).isEqualTo("Marlene");
         assertThat(updatedPersonDTO.getEmail()).isEqualTo("muster@example.org");
         assertThat(updatedPersonDTO.getPermissions()).containsOnly(RoleDTO.USER);
+        assertThat(updatedPersonDTO.getNotifications()).containsOnly(MailNotificationDTO.NOTIFICATION_EMAIL_APPLICATION_ALLOWED);
         assertThat(updatedPersonDTO.isEnabled()).isTrue();
 
 
@@ -300,6 +307,7 @@ class PersonServiceExtensionImplTest {
         assertThat(appointedPerson.getFirstName()).isEqualTo("Marlene");
         assertThat(appointedPerson.getEmail()).isEqualTo("muster@example.org");
         assertThat(appointedPerson.getPermissions()).containsOnly(RoleDTO.USER);
+        assertThat(appointedPerson.getNotifications()).containsOnly(MailNotificationDTO.NOTIFICATION_EMAIL_APPLICATION_ALLOWED);
         assertThat(appointedPerson.isEnabled()).isTrue();
 
         ArgumentCaptor<Person> personArgumentCaptor = ArgumentCaptor.forClass(Person.class);
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/person/web/PersonNotificationsViewControllerSecurityIT.java b/src/test/java/org/synyx/urlaubsverwaltung/person/web/PersonNotificationsViewControllerSecurityIT.java
index 2677353e6..4d1e3c759 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/person/web/PersonNotificationsViewControllerSecurityIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/person/web/PersonNotificationsViewControllerSecurityIT.java
@@ -10,7 +10,7 @@ import org.springframework.test.context.bean.override.mockito.MockitoBean;
 import org.springframework.test.web.servlet.ResultActions;
 import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
 import org.springframework.web.context.WebApplicationContext;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.notification.UserNotificationSettings;
 import org.synyx.urlaubsverwaltung.notification.UserNotificationSettingsService;
 import org.synyx.urlaubsverwaltung.person.Person;
@@ -35,7 +35,7 @@ import static org.synyx.urlaubsverwaltung.person.Role.OFFICE;
 import static org.synyx.urlaubsverwaltung.person.Role.USER;
 
 @SpringBootTest
-class PersonNotificationsViewControllerSecurityIT extends TestContainersBase {
+class PersonNotificationsViewControllerSecurityIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private WebApplicationContext context;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/publicholiday/PublicHolidayApiControllerSecurityIT.java b/src/test/java/org/synyx/urlaubsverwaltung/publicholiday/PublicHolidayApiControllerSecurityIT.java
index efcfdaf1e..d189a37d3 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/publicholiday/PublicHolidayApiControllerSecurityIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/publicholiday/PublicHolidayApiControllerSecurityIT.java
@@ -5,12 +5,12 @@ import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.ValueSource;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.bean.override.mockito.MockitoBean;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.test.context.bean.override.mockito.MockitoBean;
 import org.springframework.test.web.servlet.ResultActions;
 import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
 import org.springframework.web.context.WebApplicationContext;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.department.DepartmentService;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonService;
@@ -34,7 +34,7 @@ import static org.synyx.urlaubsverwaltung.person.Role.SECOND_STAGE_AUTHORITY;
 import static org.synyx.urlaubsverwaltung.workingtime.FederalState.GERMANY_BAYERN;
 
 @SpringBootTest
-class PublicHolidayApiControllerSecurityIT extends TestContainersBase {
+class PublicHolidayApiControllerSecurityIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private WebApplicationContext context;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/security/ReloadAuthenticationAuthoritiesFilterTest.java b/src/test/java/org/synyx/urlaubsverwaltung/security/ReloadAuthenticationAuthoritiesFilterTest.java
index 958e7feed..e0649f341 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/security/ReloadAuthenticationAuthoritiesFilterTest.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/security/ReloadAuthenticationAuthoritiesFilterTest.java
@@ -17,6 +17,7 @@ import org.springframework.security.oauth2.core.oidc.user.OidcUser;
 import org.springframework.security.web.context.DelegatingSecurityContextRepository;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonService;
+import org.synyx.urlaubsverwaltung.tenancy.tenant.TenantContextHolder;
 
 import java.io.IOException;
 import java.util.List;
@@ -40,10 +41,12 @@ class ReloadAuthenticationAuthoritiesFilterTest {
     private SessionService sessionService;
     @Mock
     private DelegatingSecurityContextRepository securityContextRepository;
+    @Mock
+    private TenantContextHolder tenantContextHolder;
 
     @BeforeEach
     void setUp() {
-        sut = new ReloadAuthenticationAuthoritiesFilter(personService, sessionService, securityContextRepository);
+        sut = new ReloadAuthenticationAuthoritiesFilter(personService, sessionService, securityContextRepository, tenantContextHolder);
     }
 
     @Test
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/settings/SettingsServiceImplTest.java b/src/test/java/org/synyx/urlaubsverwaltung/settings/SettingsServiceImplTest.java
index babf6ea0e..f20ef3922 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/settings/SettingsServiceImplTest.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/settings/SettingsServiceImplTest.java
@@ -9,8 +9,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
 import java.util.List;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.AdditionalAnswers.returnsFirstArg;
-import static org.mockito.ArgumentMatchers.any;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.mockito.Mockito.when;
 
 @ExtendWith(MockitoExtension.class)
@@ -29,7 +28,6 @@ class SettingsServiceImplTest {
     @Test
     void ensureGetSettingsReturnsFromDB() {
         final Settings settings = new Settings();
-        settings.setId(1L);
         when(settingsRepository.findAll()).thenReturn(List.of(settings));
 
         final Settings actualSettings = sut.getSettings();
@@ -37,11 +35,13 @@ class SettingsServiceImplTest {
     }
 
     @Test
-    void ensureGetNewEmptySettingIfNothingIsSaved() {
+    void ensureGetSettingsRequiresInitializationFirst() {
+
         when(settingsRepository.findAll()).thenReturn(List.of());
-        when(settingsRepository.save(any(Settings.class))).thenAnswer(returnsFirstArg());
 
-        final Settings actualSettings = sut.getSettings();
-        assertThat(actualSettings).isInstanceOf(Settings.class);
+        assertThatThrownBy(() -> sut.getSettings())
+            .isInstanceOf(IllegalStateException.class)
+            .hasMessage("No settings found in database!");
+
     }
 }
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/sicknote/comment/SickNoteCommentEntityRepositoryIT.java b/src/test/java/org/synyx/urlaubsverwaltung/sicknote/comment/SickNoteCommentEntityRepositoryIT.java
index 2473943dd..064847476 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/sicknote/comment/SickNoteCommentEntityRepositoryIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/sicknote/comment/SickNoteCommentEntityRepositoryIT.java
@@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.transaction.annotation.Transactional;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonService;
 import org.synyx.urlaubsverwaltung.sicknote.sicknote.SickNote;
@@ -20,7 +20,7 @@ import static org.assertj.core.api.Assertions.assertThat;
 
 @SpringBootTest
 @Transactional
-class SickNoteCommentEntityRepositoryIT extends TestContainersBase {
+class SickNoteCommentEntityRepositoryIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private SickNoteCommentEntityRepository sut;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/sicknote/sickdays/SickDaysOverviewViewControllerSecurityIT.java b/src/test/java/org/synyx/urlaubsverwaltung/sicknote/sickdays/SickDaysOverviewViewControllerSecurityIT.java
index bf993aa7e..1f5f16827 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/sicknote/sickdays/SickDaysOverviewViewControllerSecurityIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/sicknote/sickdays/SickDaysOverviewViewControllerSecurityIT.java
@@ -5,13 +5,13 @@ import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.ValueSource;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.bean.override.mockito.MockitoBean;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.test.context.bean.override.mockito.MockitoBean;
 import org.springframework.test.web.servlet.ResultActions;
 import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 import org.springframework.web.context.WebApplicationContext;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonService;
 import org.synyx.urlaubsverwaltung.util.DateAndTimeFormat;
@@ -26,7 +26,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder
 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
 
 @SpringBootTest
-class SickDaysOverviewViewControllerSecurityIT extends TestContainersBase {
+class SickDaysOverviewViewControllerSecurityIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private WebApplicationContext context;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/SickNoteApiControllerSecurityIT.java b/src/test/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/SickNoteApiControllerSecurityIT.java
index 9185e4d7c..9d5c8b6fe 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/SickNoteApiControllerSecurityIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/SickNoteApiControllerSecurityIT.java
@@ -5,12 +5,12 @@ import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.ValueSource;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.bean.override.mockito.MockitoBean;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.test.context.bean.override.mockito.MockitoBean;
 import org.springframework.test.web.servlet.ResultActions;
 import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
 import org.springframework.web.context.WebApplicationContext;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.department.DepartmentService;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonService;
@@ -33,7 +33,7 @@ import static org.synyx.urlaubsverwaltung.person.Role.SICK_NOTE_VIEW;
 import static org.synyx.urlaubsverwaltung.person.Role.USER;
 
 @SpringBootTest
-class SickNoteApiControllerSecurityIT extends TestContainersBase {
+class SickNoteApiControllerSecurityIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private WebApplicationContext context;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/SickNoteMailServiceIT.java b/src/test/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/SickNoteMailServiceIT.java
index 2322787d1..efbeed687 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/SickNoteMailServiceIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/SickNoteMailServiceIT.java
@@ -11,7 +11,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.context.bean.override.mockito.MockitoBean;
 import org.springframework.transaction.annotation.Transactional;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.mail.MailRecipientService;
 import org.synyx.urlaubsverwaltung.period.DayLength;
 import org.synyx.urlaubsverwaltung.person.Person;
@@ -43,7 +43,7 @@ import static org.synyx.urlaubsverwaltung.sicknote.sicknote.SickNoteCategory.SIC
 
 @SpringBootTest(properties = {"spring.mail.port=3025", "spring.mail.host=localhost"})
 @Transactional
-class SickNoteMailServiceIT extends TestContainersBase {
+class SickNoteMailServiceIT extends SingleTenantTestContainersBase {
 
     @RegisterExtension
     static final GreenMailExtension greenMail = new GreenMailExtension(ServerSetupTest.SMTP_IMAP);
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/SickNoteRepositoryIT.java b/src/test/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/SickNoteRepositoryIT.java
index 699ff0db5..091205b85 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/SickNoteRepositoryIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/SickNoteRepositoryIT.java
@@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.transaction.annotation.Transactional;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonService;
 
@@ -20,7 +20,7 @@ import static org.synyx.urlaubsverwaltung.sicknote.sicknote.SickNoteStatus.CANCE
 
 @SpringBootTest
 @Transactional
-class SickNoteRepositoryIT extends TestContainersBase {
+class SickNoteRepositoryIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private SickNoteRepository sickNoteRepository;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/extend/SickNoteExtensionRepositoryIT.java b/src/test/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/extend/SickNoteExtensionRepositoryIT.java
index 87c28e548..9eb5a0ead 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/extend/SickNoteExtensionRepositoryIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/sicknote/sicknote/extend/SickNoteExtensionRepositoryIT.java
@@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.transaction.annotation.Transactional;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonService;
 import org.synyx.urlaubsverwaltung.sicknote.sicknote.SickNote;
@@ -21,7 +21,7 @@ import static org.synyx.urlaubsverwaltung.person.Role.USER;
 
 @SpringBootTest
 @Transactional
-class SickNoteExtensionRepositoryIT  extends TestContainersBase {
+class SickNoteExtensionRepositoryIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private SickNoteExtensionRepository sut;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/sicknote/sicknotetype/SickNoteTypeServiceImplTest.java b/src/test/java/org/synyx/urlaubsverwaltung/sicknote/sicknotetype/SickNoteTypeServiceImplTest.java
index 29086d664..3410c462b 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/sicknote/sicknotetype/SickNoteTypeServiceImplTest.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/sicknote/sicknotetype/SickNoteTypeServiceImplTest.java
@@ -52,18 +52,17 @@ class SickNoteTypeServiceImplTest {
         sut.insertDefaultSickNoteTypes();
 
         final SickNoteType sickNote = new SickNoteType();
-        sickNote.setId(1000L);
         sickNote.setCategory(SICK_NOTE);
         sickNote.setMessageKey("application.data.sicknotetype.sicknote");
 
         final SickNoteType sickNoteChild = new SickNoteType();
-        sickNoteChild.setId(2000L);
         sickNoteChild.setCategory(SICK_NOTE_CHILD);
         sickNoteChild.setMessageKey("application.data.sicknotetype.sicknotechild");
 
         verify(sickNoteTypeRepository).saveAll(sickNoteTypeArgumentCaptor.capture());
         final List<SickNoteType> sickNoteTypes = sickNoteTypeArgumentCaptor.getValue();
         assertThat(sickNoteTypes)
+            .usingRecursiveFieldByFieldElementComparatorOnFields("category", "messageKey")
             .containsExactly(sickNote, sickNoteChild);
     }
 
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/ui/ApplicationForLeaveUIIT.java b/src/test/java/org/synyx/urlaubsverwaltung/ui/ApplicationForLeaveUIIT.java
index 9644942b7..7b37abcbe 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/ui/ApplicationForLeaveUIIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/ui/ApplicationForLeaveUIIT.java
@@ -9,8 +9,8 @@ import org.springframework.boot.test.web.server.LocalServerPort;
 import org.springframework.context.MessageSource;
 import org.springframework.test.context.DynamicPropertyRegistry;
 import org.springframework.test.context.DynamicPropertySource;
+import org.synyx.urlaubsverwaltung.SingleTenantTestPostgreSQLContainer;
 import org.synyx.urlaubsverwaltung.TestKeycloakContainer;
-import org.synyx.urlaubsverwaltung.TestPostgreSQLContainer;
 import org.synyx.urlaubsverwaltung.account.AccountInteractionService;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonService;
@@ -23,8 +23,8 @@ import org.synyx.urlaubsverwaltung.ui.pages.ApplicationPage;
 import org.synyx.urlaubsverwaltung.ui.pages.LoginPage;
 import org.synyx.urlaubsverwaltung.ui.pages.NavigationPage;
 import org.synyx.urlaubsverwaltung.ui.pages.OverviewPage;
-import org.synyx.urlaubsverwaltung.ui.pages.settings.SettingsWorkingTimePage;
 import org.synyx.urlaubsverwaltung.ui.pages.settings.SettingsPage;
+import org.synyx.urlaubsverwaltung.ui.pages.settings.SettingsWorkingTimePage;
 import org.synyx.urlaubsverwaltung.workingtime.FederalState;
 import org.synyx.urlaubsverwaltung.workingtime.WorkingTimeWriteService;
 import org.testcontainers.junit.jupiter.Container;
@@ -68,7 +68,7 @@ class ApplicationForLeaveUIIT {
     private int port;
 
     @Container
-    private static final TestPostgreSQLContainer postgre = new TestPostgreSQLContainer();
+    private static final SingleTenantTestPostgreSQLContainer postgre = new SingleTenantTestPostgreSQLContainer();
     @Container
     private static final TestKeycloakContainer keycloak = new TestKeycloakContainer();
 
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/ui/CustomAbsenceTypeUIIT.java b/src/test/java/org/synyx/urlaubsverwaltung/ui/CustomAbsenceTypeUIIT.java
index efb3f9d4a..18961d525 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/ui/CustomAbsenceTypeUIIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/ui/CustomAbsenceTypeUIIT.java
@@ -8,8 +8,8 @@ import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.boot.test.web.server.LocalServerPort;
 import org.springframework.test.context.DynamicPropertyRegistry;
 import org.springframework.test.context.DynamicPropertySource;
+import org.synyx.urlaubsverwaltung.SingleTenantTestPostgreSQLContainer;
 import org.synyx.urlaubsverwaltung.TestKeycloakContainer;
-import org.synyx.urlaubsverwaltung.TestPostgreSQLContainer;
 import org.synyx.urlaubsverwaltung.account.AccountInteractionService;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonService;
@@ -59,7 +59,7 @@ class CustomAbsenceTypeUIIT {
     private int port;
 
     @Container
-    private static final TestPostgreSQLContainer postgre = new TestPostgreSQLContainer();
+    private static final SingleTenantTestPostgreSQLContainer postgre = new SingleTenantTestPostgreSQLContainer();
     @Container
     private static final TestKeycloakContainer keycloak = new TestKeycloakContainer();
 
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/ui/OvertimeUIIT.java b/src/test/java/org/synyx/urlaubsverwaltung/ui/OvertimeUIIT.java
index c5a5636a6..5b2450862 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/ui/OvertimeUIIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/ui/OvertimeUIIT.java
@@ -7,8 +7,8 @@ import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.boot.test.web.server.LocalServerPort;
 import org.springframework.test.context.DynamicPropertyRegistry;
 import org.springframework.test.context.DynamicPropertySource;
+import org.synyx.urlaubsverwaltung.SingleTenantTestPostgreSQLContainer;
 import org.synyx.urlaubsverwaltung.TestKeycloakContainer;
-import org.synyx.urlaubsverwaltung.TestPostgreSQLContainer;
 import org.synyx.urlaubsverwaltung.account.AccountInteractionService;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonService;
@@ -60,7 +60,7 @@ class OvertimeUIIT {
     private int port;
 
     @Container
-    private static final TestPostgreSQLContainer postgre = new TestPostgreSQLContainer();
+    private static final SingleTenantTestPostgreSQLContainer postgre = new SingleTenantTestPostgreSQLContainer();
     @Container
     private static final TestKeycloakContainer keycloak = new TestKeycloakContainer();
 
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/ui/SickNoteUIIT.java b/src/test/java/org/synyx/urlaubsverwaltung/ui/SickNoteUIIT.java
index 307183f07..76e1b2567 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/ui/SickNoteUIIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/ui/SickNoteUIIT.java
@@ -11,8 +11,8 @@ import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Primary;
 import org.springframework.test.context.DynamicPropertyRegistry;
 import org.springframework.test.context.DynamicPropertySource;
+import org.synyx.urlaubsverwaltung.SingleTenantTestPostgreSQLContainer;
 import org.synyx.urlaubsverwaltung.TestKeycloakContainer;
-import org.synyx.urlaubsverwaltung.TestPostgreSQLContainer;
 import org.synyx.urlaubsverwaltung.account.AccountInteractionService;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonService;
@@ -81,7 +81,7 @@ class SickNoteUIIT {
     private int port;
 
     @Container
-    private static final TestPostgreSQLContainer postgre = new TestPostgreSQLContainer();
+    private static final SingleTenantTestPostgreSQLContainer postgre = new SingleTenantTestPostgreSQLContainer();
     @Container
     private static final TestKeycloakContainer keycloak = new TestKeycloakContainer();
 
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/ui/pages/SickNotePage.java b/src/test/java/org/synyx/urlaubsverwaltung/ui/pages/SickNotePage.java
index 98cf18632..270a7a956 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/ui/pages/SickNotePage.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/ui/pages/SickNotePage.java
@@ -23,8 +23,8 @@ public class SickNotePage {
     private final Page page;
 
     private enum Type {
-        SICK_NOTE("1000"),
-        CHILD_SICK_NOTE("2000");
+        SICK_NOTE("1953"),
+        CHILD_SICK_NOTE("1954");
 
         final String value;
 
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/user/UserSettingsRepositoryIT.java b/src/test/java/org/synyx/urlaubsverwaltung/user/UserSettingsRepositoryIT.java
index 08503d8f0..596721729 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/user/UserSettingsRepositoryIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/user/UserSettingsRepositoryIT.java
@@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.transaction.annotation.Transactional;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonService;
 
@@ -16,7 +16,7 @@ import static org.synyx.urlaubsverwaltung.user.Theme.SYSTEM;
 
 @SpringBootTest
 @Transactional
-class UserSettingsRepositoryIT extends TestContainersBase {
+class UserSettingsRepositoryIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private UserSettingsRepository sut;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/user/pagination/UserPaginationSettingsRepositoryIT.java b/src/test/java/org/synyx/urlaubsverwaltung/user/pagination/UserPaginationSettingsRepositoryIT.java
index 5dc711678..f76950e33 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/user/pagination/UserPaginationSettingsRepositoryIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/user/pagination/UserPaginationSettingsRepositoryIT.java
@@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.transaction.annotation.Transactional;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonId;
 import org.synyx.urlaubsverwaltung.person.PersonService;
@@ -15,7 +15,7 @@ import static org.assertj.core.api.Assertions.assertThat;
 
 @SpringBootTest
 @Transactional
-class UserPaginationSettingsRepositoryIT extends TestContainersBase {
+class UserPaginationSettingsRepositoryIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private UserPaginationSettingsRepository sut;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/vacations/VacationApiControllerSecurityIT.java b/src/test/java/org/synyx/urlaubsverwaltung/vacations/VacationApiControllerSecurityIT.java
index 850a290b9..56859331d 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/vacations/VacationApiControllerSecurityIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/vacations/VacationApiControllerSecurityIT.java
@@ -10,7 +10,7 @@ import org.springframework.test.context.bean.override.mockito.MockitoBean;
 import org.springframework.test.web.servlet.ResultActions;
 import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
 import org.springframework.web.context.WebApplicationContext;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.application.application.ApplicationService;
 import org.synyx.urlaubsverwaltung.department.DepartmentService;
 import org.synyx.urlaubsverwaltung.person.Person;
@@ -32,7 +32,7 @@ import static org.synyx.urlaubsverwaltung.person.Role.SECOND_STAGE_AUTHORITY;
 import static org.synyx.urlaubsverwaltung.person.Role.USER;
 
 @SpringBootTest
-class VacationApiControllerSecurityIT extends TestContainersBase {
+class VacationApiControllerSecurityIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private WebApplicationContext context;
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/workingtime/WorkingTimeCalendarApiControllerSecurityIT.java b/src/test/java/org/synyx/urlaubsverwaltung/workingtime/WorkingTimeCalendarApiControllerSecurityIT.java
index a08ee5517..6b6927d31 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/workingtime/WorkingTimeCalendarApiControllerSecurityIT.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/workingtime/WorkingTimeCalendarApiControllerSecurityIT.java
@@ -5,12 +5,12 @@ import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.ValueSource;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.bean.override.mockito.MockitoBean;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.test.context.bean.override.mockito.MockitoBean;
 import org.springframework.test.web.servlet.ResultActions;
 import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
 import org.springframework.web.context.WebApplicationContext;
-import org.synyx.urlaubsverwaltung.TestContainersBase;
+import org.synyx.urlaubsverwaltung.SingleTenantTestContainersBase;
 import org.synyx.urlaubsverwaltung.department.DepartmentService;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonService;
@@ -31,7 +31,7 @@ import static org.synyx.urlaubsverwaltung.person.Role.SECOND_STAGE_AUTHORITY;
 import static org.synyx.urlaubsverwaltung.person.Role.USER;
 
 @SpringBootTest
-class WorkingTimeCalendarApiControllerSecurityIT extends TestContainersBase {
+class WorkingTimeCalendarApiControllerSecurityIT extends SingleTenantTestContainersBase {
 
     @Autowired
     private WebApplicationContext context;
diff --git a/src/test/resources/application.yaml b/src/test/resources/application.yaml
index 3be25ef9b..db1a1cfe7 100644
--- a/src/test/resources/application.yaml
+++ b/src/test/resources/application.yaml
@@ -7,6 +7,8 @@ uv:
     fromDisplayName: Urlaubsverwaltung
     replyTo: sender@example.org
     replyToDisplayName: Urlaubsverwaltung
+  tenant:
+    mode: single
 
 spring:
   security: