diff --git a/ansible/group_vars/all.yml b/ansible/group_vars/all.yml
index 641fa7467c..52e7db6df2 100644
--- a/ansible/group_vars/all.yml
+++ b/ansible/group_vars/all.yml
@@ -353,13 +353,18 @@ ceilometer_database_type: "mongodb"
 #################################
 cinder_backend_ceph: "{{ enable_ceph }}"
 
-
 #######################
 # Nova options
 #######################
 nova_backend_ceph: "{{ enable_ceph }}"
 nova_backend: "{{ 'rbd' if nova_backend_ceph | bool else 'default' }}"
 
+
+#######################
+# Horizon options
+#######################
+horizon_backend_database: "no"
+
 ###################
 # Ceph options
 ###################
diff --git a/ansible/roles/horizon/defaults/main.yml b/ansible/roles/horizon/defaults/main.yml
index e07b9ba0aa..169bfd68be 100644
--- a/ansible/roles/horizon/defaults/main.yml
+++ b/ansible/roles/horizon/defaults/main.yml
@@ -1,6 +1,13 @@
 ---
 project_name: "horizon"
 
+####################
+# Database
+####################
+horizon_database_name: "horizon"
+horizon_database_user: "horizon"
+horizon_database_address: "{{ kolla_internal_fqdn }}:{{ database_port }}"
+
 ####################
 # Docker
 ####################
diff --git a/ansible/roles/horizon/tasks/bootstrap.yml b/ansible/roles/horizon/tasks/bootstrap.yml
new file mode 100644
index 0000000000..6e6127495a
--- /dev/null
+++ b/ansible/roles/horizon/tasks/bootstrap.yml
@@ -0,0 +1,41 @@
+---
+- name: Creating Horizon database
+  command: docker exec -t kolla_toolbox /usr/bin/ansible localhost
+    -m mysql_db
+    -a "login_host='{{ database_address }}'
+        login_port='{{ database_port }}'
+        login_user='{{ database_user }}'
+        login_password='{{ database_password }}'
+        name='{{ horizon_database_name }}'"
+  register: database
+  changed_when: "{{ database.stdout.find('localhost | SUCCESS => ') != -1 and
+                    (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed }}"
+  failed_when: database.stdout.split()[2] != 'SUCCESS'
+  run_once: True
+  delegate_to: "{{ groups['horizon'][0] }}"
+
+- name: Reading json from variable
+  set_fact:
+    database_created: "{{ (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed }}"
+
+- name: Creating Horizon database user and setting permissions
+  command: docker exec -t kolla_toolbox /usr/bin/ansible localhost
+    -m mysql_user
+    -a "login_host='{{ database_address }}'
+        login_port='{{ database_port }}'
+        login_user='{{ database_user }}'
+        login_password='{{ database_password }}'
+        name='{{ horizon_database_name }}'
+        password='{{ horizon_database_password }}'
+        host='%'
+        priv='{{ horizon_database_name }}.*:ALL'
+        append_privs='yes'"
+  register: database_user_create
+  changed_when: "{{ database_user_create.stdout.find('localhost | SUCCESS => ') != -1 and
+                    (database_user_create.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed }}"
+  failed_when: database_user_create.stdout.split()[2] != 'SUCCESS'
+  run_once: True
+  delegate_to: "{{ groups['horizon'][0] }}"
+
+- include: bootstrap_service.yml
+  when: database_created
diff --git a/ansible/roles/horizon/tasks/bootstrap_service.yml b/ansible/roles/horizon/tasks/bootstrap_service.yml
new file mode 100644
index 0000000000..c20280f6bd
--- /dev/null
+++ b/ansible/roles/horizon/tasks/bootstrap_service.yml
@@ -0,0 +1,19 @@
+---
+- name: Running Horizon bootstrap container
+  kolla_docker:
+    action: "start_container"
+    common_options: "{{ docker_common_options }}"
+    detach: False
+    environment:
+      KOLLA_BOOTSTRAP:
+      KOLLA_CONFIG_STRATEGY: "{{ config_strategy }}"
+    image: "{{ horizon_image_full }}"
+    labels:
+      BOOTSTRAP:
+    name: "bootstrap_horizon"
+    restart_policy: "never"
+    volumes:
+      - "{{ node_config_directory }}/horizon/:{{ container_config_directory }}/:ro"
+      - "kolla_logs:/var/log/kolla/"
+  run_once: True
+  delegate_to: "{{ groups['horizon'][0] }}"
diff --git a/ansible/roles/horizon/tasks/deploy.yml b/ansible/roles/horizon/tasks/deploy.yml
index 16fae2dadc..3c04e136d2 100644
--- a/ansible/roles/horizon/tasks/deploy.yml
+++ b/ansible/roles/horizon/tasks/deploy.yml
@@ -3,4 +3,7 @@
 
 - include: register.yml
 
+- include: bootstrap.yml
+  when: horizon_backend_database | bool
+
 - include: start.yml
diff --git a/ansible/roles/horizon/templates/local_settings.j2 b/ansible/roles/horizon/templates/local_settings.j2
index 05386f1d00..cabaf99afe 100644
--- a/ansible/roles/horizon/templates/local_settings.j2
+++ b/ansible/roles/horizon/templates/local_settings.j2
@@ -29,6 +29,20 @@ WEBROOT = '/'
 # https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
 ALLOWED_HOSTS = ['*']
 
+{% if horizon_backend_database | bool %}
+SESSION_ENGINE = 'django.contrib.sessions.backends.db'
+DATABASES = {
+    'default': {
+    'ENGINE': 'django.db.backends.mysql',
+    'NAME': '{{ horizon_database_name }}',
+    'USER': '{{ horizon_database_user }}',
+    'PASSWORD': '{{ horizon_database_password }}',
+    'HOST': '{{ database_address }}',
+    'PORT': '{{ database_port }}'
+    }
+}
+{% endif %}
+
 # Set SSL proxy settings:
 # Pass this header from the proxy after terminating the SSL,
 # and don't forget to strip it from the client's request.
diff --git a/docker/horizon/extend_start.sh b/docker/horizon/extend_start.sh
index a34d33f52f..51be17405b 100644
--- a/docker/horizon/extend_start.sh
+++ b/docker/horizon/extend_start.sh
@@ -1,5 +1,16 @@
 #!/bin/bash
 
+# Bootstrap and exit if KOLLA_BOOTSTRAP variable is set. This catches all cases
+# of the KOLLA_BOOTSTRAP variable being set, including empty.
+if [[ "${!KOLLA_BOOTSTRAP[@]}" ]]; then
+    MANAGE_PY="/usr/bin/python /usr/bin/manage.py"
+    if [[ -f "/var/lib/kolla/venv/bin/python" ]]; then
+        MANAGE_PY="/var/lib/kolla/venv/bin/python /var/lib/kolla/venv/bin/manage.py"
+    fi
+    $MANAGE_PY syncdb --noinput
+    exit 0
+fi
+
 # NOTE(pbourke): httpd will not clean up after itself in some cases which
 # results in the container not being able to restart. (bug #1489676, 1557036)
 if [[ "${KOLLA_BASE_DISTRO}" =~ debian|ubuntu ]]; then
diff --git a/docker/openstack-base/Dockerfile.j2 b/docker/openstack-base/Dockerfile.j2
index bb42093db4..cdfe6131cb 100644
--- a/docker/openstack-base/Dockerfile.j2
+++ b/docker/openstack-base/Dockerfile.j2
@@ -199,6 +199,7 @@ ENV DEBIAN_FRONTEND noninteractive
             'libxslt-devel',
             'libyaml-devel',
             'MariaDB-devel',
+            'MySQL-python',
             'openldap-devel',
             'openssl-devel',
             'postgresql',
diff --git a/etc/kolla/globals.yml b/etc/kolla/globals.yml
index 13fcfc26f2..bfb3d7d507 100644
--- a/etc/kolla/globals.yml
+++ b/etc/kolla/globals.yml
@@ -207,6 +207,12 @@ kolla_internal_vip_address: "10.10.10.254"
 #nova_backend_ceph: "{{ enable_ceph }}"
 
 
+#######################
+# Horizon options
+#######################
+#horizon_backend_database: "no"
+
+
 #######################################
 # Manila - Shared File Systems Options
 #######################################
diff --git a/etc/kolla/passwords.yml b/etc/kolla/passwords.yml
index e7799c4adb..93a54f55e9 100644
--- a/etc/kolla/passwords.yml
+++ b/etc/kolla/passwords.yml
@@ -93,6 +93,7 @@ senlin_database_password:
 senlin_keystone_password:
 
 horizon_secret_key:
+horizon_database_password:
 
 telemetry_secret_key:
 
diff --git a/releasenotes/notes/configurable-horizon-sessions-1dd22eae714a7001.yaml b/releasenotes/notes/configurable-horizon-sessions-1dd22eae714a7001.yaml
new file mode 100644
index 0000000000..5b8c83545a
--- /dev/null
+++ b/releasenotes/notes/configurable-horizon-sessions-1dd22eae714a7001.yaml
@@ -0,0 +1,4 @@
+---
+features:
+  - Allow the use of a database backend for Horizon
+    sessions.