diff --git a/changelogs/unreleased/repmgr-guardrails.yml b/changelogs/unreleased/repmgr-guardrails.yml
new file mode 100644
index 0000000000000000000000000000000000000000..0bafcd45e84e85379fe2f82acb458a96afcc1b29
--- /dev/null
+++ b/changelogs/unreleased/repmgr-guardrails.yml
@@ -0,0 +1,5 @@
+---
+title: Switch to enabling patroni by default with new patroni role
+merge_request: 4851
+author:
+type: changed
diff --git a/doc/roles/README.md b/doc/roles/README.md
index 052dc4a47d6cdb20af0e3108c0f4b9d783844d98..47b8f5609e45b9e6fc3c80a7201be27e149f0c86 100644
--- a/doc/roles/README.md
+++ b/doc/roles/README.md
@@ -113,6 +113,12 @@ Documentation on the usage of the PostgreSQL Roles can be found in [Configuring
 
   *By default, enables no other services.*
 
+- **patroni_role** (`gitlab-ee`)
+
+  Enables the PostgreSQL, patroni, and Consul services on the machine
+
+  *By default, enables no other services.*
+
 - **pgbouncer_role** (`gitlab-ee`)
 
   Enables the PgBouncer and Consul services on the machine
diff --git a/files/gitlab-cookbooks/consul/libraries/consul_helper.rb b/files/gitlab-cookbooks/consul/libraries/consul_helper.rb
index 85ee1c480f6aada21972fba5f17b43f21e0a234a..0b6ecbb539dee68a7918b1201d5530798497b4cd 100644
--- a/files/gitlab-cookbooks/consul/libraries/consul_helper.rb
+++ b/files/gitlab-cookbooks/consul/libraries/consul_helper.rb
@@ -102,8 +102,8 @@ class ConsulHelper
   end
 
   def postgresql_ha_solution
-    return 'repmgr' unless Gitlab['patroni']['enable']
-    return 'patroni_standby_cluster' if Gitlab['patroni'].key?('standby_cluster') && Gitlab['patroni']['standby_cluster']['enable']
+    return 'repmgr' unless node['patroni']['enable']
+    return 'patroni_standby_cluster' if node['patroni'].key?('standby_cluster') && node['patroni']['standby_cluster']['enable']
 
     'patroni'
   end
diff --git a/files/gitlab-cookbooks/gitlab/libraries/helpers/base_pg_helper.rb b/files/gitlab-cookbooks/gitlab/libraries/helpers/base_pg_helper.rb
index cd4b8e0ccd1e4ece6b911a48130bdc73f82e99c7..b0a7cc2f551f869a9e2d8d95766d836f2dc65695 100644
--- a/files/gitlab-cookbooks/gitlab/libraries/helpers/base_pg_helper.rb
+++ b/files/gitlab-cookbooks/gitlab/libraries/helpers/base_pg_helper.rb
@@ -291,15 +291,15 @@ class BasePgHelper < BaseHelper
     # When Patroni is enabled, the configuration of PostgreSQL instance must be delegated to it.
     # PostgreSQL cookbook skips some of the steps that are must be done either during or after
     # Patroni bootstraping.
-    Gitlab['patroni']['enable'] && !Gitlab['repmgr']['enable']
+    node['patroni']['enable'] && !Gitlab['repmgr']['enable']
   end
 
   def config_dir
-    Gitlab['patroni']['enable'] ? node['patroni']['data_dir'] : node['postgresql']['data_dir']
+    node['patroni']['enable'] ? node['patroni']['data_dir'] : node['postgresql']['data_dir']
   end
 
   def postgresql_config
-    ::File.join(config_dir, "postgresql#{Gitlab['patroni']['enable'] ? '.base' : ''}.conf")
+    ::File.join(config_dir, "postgresql#{node['patroni']['enable'] ? '.base' : ''}.conf")
   end
 
   def postgresql_runtime_config
diff --git a/files/gitlab-cookbooks/gitlab/recipes/default.rb b/files/gitlab-cookbooks/gitlab/recipes/default.rb
index 5e76c9ead1f59d660f987c62bd82f7d48508729b..93ad661b7a7e885e4656990bedc3d370431bdcba 100644
--- a/files/gitlab-cookbooks/gitlab/recipes/default.rb
+++ b/files/gitlab-cookbooks/gitlab/recipes/default.rb
@@ -29,6 +29,10 @@ OmnibusHelper.check_deprecations
 OmnibusHelper.check_environment
 OmnibusHelper.check_locale
 
+# Setup additional postgresql attributes
+include_recipe 'postgresql::directory_locations'
+OmnibusHelper.new(node).check_invalid_pg_ha
+
 directory "/etc/gitlab" do
   owner "root"
   group "root"
diff --git a/files/gitlab-cookbooks/package/libraries/config/gitlab.rb b/files/gitlab-cookbooks/package/libraries/config/gitlab.rb
index e32148dc3aaaf32c2a045d98ba9a8b1d13c665f9..d3a0e2fe4e4e908669b2aa80da254a1168c5a50e 100644
--- a/files/gitlab-cookbooks/package/libraries/config/gitlab.rb
+++ b/files/gitlab-cookbooks/package/libraries/config/gitlab.rb
@@ -38,6 +38,7 @@ module Gitlab
   role('monitoring').use { MonitoringRole }
   role('postgres').use { PostgresRole }
   role('pgbouncer').use { PgbouncerRole }
+  role('patroni').use { PatroniRole }
   role('consul').use { ConsulRole }
   role('pages').use { PagesRole }
 
diff --git a/files/gitlab-cookbooks/package/libraries/config/roles/patroni.rb b/files/gitlab-cookbooks/package/libraries/config/roles/patroni.rb
new file mode 100644
index 0000000000000000000000000000000000000000..5d4ad09ee8e3fd362eeb5cdd80d1f336fcaca247
--- /dev/null
+++ b/files/gitlab-cookbooks/package/libraries/config/roles/patroni.rb
@@ -0,0 +1,23 @@
+# Copyright:: Copyright (c) 2021 GitLab Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+module PatroniRole
+  def self.load_role
+    return unless Gitlab['patroni_role']['enable']
+
+    Services.enable_group('patroni_role')
+  end
+end
diff --git a/files/gitlab-cookbooks/package/libraries/config/roles/postgres.rb b/files/gitlab-cookbooks/package/libraries/config/roles/postgres.rb
index a63efbcf30748d2d646de294e25def2160ee7f18..d285e5645b3c5e39cb302b7e1aa3514b017d6dd4 100644
--- a/files/gitlab-cookbooks/package/libraries/config/roles/postgres.rb
+++ b/files/gitlab-cookbooks/package/libraries/config/roles/postgres.rb
@@ -18,7 +18,7 @@ module PostgresRole
   def self.load_role
     return unless Gitlab['postgres_role']['enable']
 
-    Gitlab['repmgr']['enable'] = true if !Gitlab['patroni']['enable'] && Gitlab['repmgr']['enable'].nil?
+    Gitlab['repmgr']['enable'] = true if !Gitlab['patroni']['enable'] && !Gitlab['patroni_role']['enable'] && Gitlab['repmgr']['enable'].nil?
     Services.enable_group('postgres_role')
   end
 end
diff --git a/files/gitlab-cookbooks/package/libraries/config/services.rb b/files/gitlab-cookbooks/package/libraries/config/services.rb
index 88bc36f2ba04922bad097e95af4f5f1ce44c6434..9fecb30bc2815cb3f5e33a7ca5ace804d33466db 100644
--- a/files/gitlab-cookbooks/package/libraries/config/services.rb
+++ b/files/gitlab-cookbooks/package/libraries/config/services.rb
@@ -29,11 +29,11 @@ module Services
     service 'gitaly',             groups: [DEFAULT_GROUP, 'rails']
     service 'redis',              groups: [DEFAULT_GROUP, 'redis', 'redis_node']
     service 'redis_exporter',     groups: [DEFAULT_GROUP, 'redis', 'redis_node', 'monitoring']
-    service 'postgresql',         groups: [DEFAULT_GROUP, 'postgres', 'postgres_role']
+    service 'postgresql',         groups: [DEFAULT_GROUP, 'postgres', 'postgres_role', 'patroni_role']
     service 'nginx',              groups: [DEFAULT_GROUP, 'pages_role']
     service 'prometheus',         groups: [DEFAULT_GROUP, 'monitoring', 'monitoring_role']
     service 'alertmanager',       groups: [DEFAULT_GROUP, 'monitoring', 'monitoring_role']
-    service 'postgres_exporter',  groups: [DEFAULT_GROUP, 'monitoring', 'postgres', 'postgres_role']
+    service 'postgres_exporter',  groups: [DEFAULT_GROUP, 'monitoring', 'postgres', 'postgres_role', 'patroni_role']
     service 'grafana',            groups: [DEFAULT_GROUP, 'monitoring', 'monitoring_role']
     service 'gitlab_pages',       groups: ['pages_role']
     service 'mailroom'
@@ -55,8 +55,8 @@ module Services
     service 'pgbouncer',          groups: %w(postgres pgbouncer_role)
     service 'pgbouncer_exporter', groups: %w(pgbouncer_role)
     service 'repmgrd',            groups: %w(postgres postgres_role)
-    service 'patroni',            groups: %w(postgres)
-    service 'consul',             groups: %w(consul_role ha pgbouncer_role postgres_role)
+    service 'patroni',            groups: %w(postgres patroni_role)
+    service 'consul',             groups: %w(consul_role ha pgbouncer_role postgres_role patroni_role)
     service 'sidekiq_cluster',    groups: ['sidekiq']
   end
 end
diff --git a/files/gitlab-cookbooks/package/libraries/omnibus_helper.rb b/files/gitlab-cookbooks/package/libraries/omnibus_helper.rb
index c39df04a4cbe6fb698cf3dc6e91c0569d185302b..4290fc0e00373a3011f1bff3909c83cc85fd867f 100644
--- a/files/gitlab-cookbooks/package/libraries/omnibus_helper.rb
+++ b/files/gitlab-cookbooks/package/libraries/omnibus_helper.rb
@@ -103,6 +103,21 @@ class OmnibusHelper
     LoggingHelper.note(msg)
   end
 
+  def check_invalid_pg_ha
+    return unless Services.enabled?('repmgr') && Services.enabled?('repmgrd')
+
+    geo_pg_helper = GeoPgHelper.new(node)
+    pg_helper = PgHelper.new(node)
+
+    main_db_version = pg_helper.database_version if Services.enabled?('postgresql')
+    geo_db_version = geo_pg_helper.database_version if Services.enabled?('geo_postgresql')
+    db_version = node['postgresql']['version'] || main_db_version || geo_db_version
+
+    return unless db_version.nil? || db_version.to_f >= 12
+
+    raise 'The included Repmgr is not supported on PostgreSQL 12, please use Patroni: https://docs.gitlab.com/ee/administration/postgresql/replication_and_failover.html'
+  end
+
   def self.utf8_variable?(var)
     ENV[var]&.downcase&.include?('utf-8') || ENV[var]&.downcase&.include?('utf8')
   end
diff --git a/files/gitlab-cookbooks/patroni/libraries/patroni_helper.rb b/files/gitlab-cookbooks/patroni/libraries/patroni_helper.rb
index 9015c36efebc5b760876695a5f8dc8b2fa595efb..5b24855a6eb4c452dca01d3b57ca4341372a7b40 100644
--- a/files/gitlab-cookbooks/patroni/libraries/patroni_helper.rb
+++ b/files/gitlab-cookbooks/patroni/libraries/patroni_helper.rb
@@ -77,7 +77,7 @@ class PatroniHelper < BaseHelper
   end
 
   def public_attributes
-    return {} unless Gitlab['patroni']['enable']
+    return {} unless node['patroni']['enable']
 
     {
       'patroni' => {
diff --git a/spec/chef/patroni/recipes/patroni_spec.rb b/spec/chef/patroni/recipes/patroni_spec.rb
index 32a9d0dc2dba6e6dfffd843a8437b0920c41e22f..1668feb6a6a7694c59c52a9d10b7f26f73b65025 100644
--- a/spec/chef/patroni/recipes/patroni_spec.rb
+++ b/spec/chef/patroni/recipes/patroni_spec.rb
@@ -14,10 +14,46 @@ RSpec.describe 'patroni cookbook' do
     expect(chef_run).to include_recipe('patroni::disable')
   end
 
+  context 'when postgres_role is enabled' do
+    before do
+      stub_gitlab_rb(roles: %w(postgres_role))
+    end
+
+    it 'should be disabled while repmgr is enabled' do
+      expect(chef_run).to include_recipe('repmgr::enable')
+      expect(chef_run).to include_recipe('patroni::disable')
+    end
+  end
+
+  context 'when patroni_role is enabled' do
+    before do
+      stub_gitlab_rb(roles: %w(patroni_role))
+    end
+
+    it 'should be enabled while repmgr is disabled' do
+      expect(chef_run).to include_recipe('repmgr::disable')
+      expect(chef_run).to include_recipe('patroni::enable')
+    end
+  end
+
+  context 'when patroni_role and postgres_role is enabled' do
+    before do
+      stub_gitlab_rb(roles: %w(postgres_role patroni_role))
+    end
+
+    it 'should be enabled while repmgr is disabled' do
+      expect(chef_run).to include_recipe('repmgr::disable')
+      expect(chef_run).to include_recipe('patroni::enable')
+    end
+  end
+
   context 'when repmgr is enabled' do
     before do
       stub_gitlab_rb(
-        roles: %w(postgres_role)
+        roles: %w(postgres_role),
+        repmgr: {
+          enable: true
+        }
       )
     end
 
@@ -30,10 +66,7 @@ RSpec.describe 'patroni cookbook' do
   context 'when enabled with default config' do
     before do
       stub_gitlab_rb(
-        roles: %w(postgres_role),
-        patroni: {
-          enable: true
-        },
+        roles: %w(patroni_role),
         postgresql: {
           pgbouncer_user_password: ''
         }
diff --git a/spec/chef/postgresql/resources/config_spec.rb b/spec/chef/postgresql/resources/config_spec.rb
index 85f76feb2a45e2fb05c6ea4be4332ca79fe2ca74..43bcb053b2ada02257bf693f9785c7a2fbad3088 100644
--- a/spec/chef/postgresql/resources/config_spec.rb
+++ b/spec/chef/postgresql/resources/config_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe 'postgresql_config' do
     end
   end
 
-  let(:chef_run) { runner.converge('test_postgresql::postgresql_config') }
+  let(:chef_run) { runner.converge('gitlab::config', 'test_postgresql::postgresql_config') }
 
   before do
     allow_any_instance_of(PgHelper).to receive(:postgresql_user).and_return('fakeuser')