diff --git a/ansible/group_vars/all.yml b/ansible/group_vars/all.yml
index c6fc6f245d..c5a6092f49 100644
--- a/ansible/group_vars/all.yml
+++ b/ansible/group_vars/all.yml
@@ -168,6 +168,8 @@ openstack_logging_debug: "False"
 
 openstack_region_name: "RegionOne"
 
+openstack_service_workers: "{{ [ansible_processor_vcpus, 5]|min }}"
+
 # Optionally allow Kolla to set sysctl values
 set_sysctl: "yes"
 
diff --git a/ansible/roles/cinder/templates/cinder.conf.j2 b/ansible/roles/cinder/templates/cinder.conf.j2
index 642225ebdd..d5a40174e8 100644
--- a/ansible/roles/cinder/templates/cinder.conf.j2
+++ b/ansible/roles/cinder/templates/cinder.conf.j2
@@ -9,6 +9,7 @@ use_forwarded_for = true
 use_stderr = False
 
 enable_v1_api=false
+osapi_volume_workers = {{ openstack_service_worker }}
 volume_name_template = volume-%s
 
 glance_api_servers = {{ internal_protocol }}://{{ kolla_internal_fqdn }}:{{ glance_api_port }}
diff --git a/ansible/roles/glance/templates/glance-api.conf.j2 b/ansible/roles/glance/templates/glance-api.conf.j2
index 86ae85f1cf..6751161e87 100644
--- a/ansible/roles/glance/templates/glance-api.conf.j2
+++ b/ansible/roles/glance/templates/glance-api.conf.j2
@@ -7,6 +7,7 @@ use_forwarded_for = true
 
 bind_host = {{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }}
 bind_port = {{ glance_api_port }}
+workers = {{ openstack_service_workers }}
 
 registry_host = {{ kolla_internal_fqdn }}
 
diff --git a/ansible/roles/glance/templates/glance-registry.conf.j2 b/ansible/roles/glance/templates/glance-registry.conf.j2
index 55146ac870..92d4fcd6fe 100644
--- a/ansible/roles/glance/templates/glance-registry.conf.j2
+++ b/ansible/roles/glance/templates/glance-registry.conf.j2
@@ -6,6 +6,7 @@ log_file = /var/log/kolla/glance/registry.log
 
 bind_host = {{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }}
 bind_port = {{ glance_registry_port }}
+workers = {{ openstack_service_workers }}
 
 [database]
 connection = mysql+pymysql://{{ glance_database_user }}:{{ glance_database_password }}@{{ glance_database_address }}/{{ glance_database_name }}
diff --git a/ansible/roles/heat/templates/heat.conf.j2 b/ansible/roles/heat/templates/heat.conf.j2
index e9f9088261..faccf7d67f 100644
--- a/ansible/roles/heat/templates/heat.conf.j2
+++ b/ansible/roles/heat/templates/heat.conf.j2
@@ -14,6 +14,7 @@ stack_user_domain_name = heat_user_domain
 rpc_backend = rabbit
 deferred_auth_method = trusts
 trusts_delegated_role = heat_stack_owner
+num_engine_workers = {{ openstack_service_workers }}
 
 [oslo_messaging_rabbit]
 rabbit_userid = {{ rabbitmq_user }}
@@ -25,6 +26,7 @@ rabbit_hosts = {% for host in groups['rabbitmq'] %}{{ hostvars[host]['ansible_'
 [heat_api]
 bind_host = {{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }}
 bind_port = {{ heat_api_port }}
+works = {{ openstack_service_workers }}
 {% endif %}
 
 {% if service_name == 'heat-api-cfn' %}
diff --git a/ansible/roles/murano/templates/murano.conf.j2 b/ansible/roles/murano/templates/murano.conf.j2
index 822596ce21..feb28f25f2 100644
--- a/ansible/roles/murano/templates/murano.conf.j2
+++ b/ansible/roles/murano/templates/murano.conf.j2
@@ -8,6 +8,9 @@ bind_host = {{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4'][
 bind_port = {{ murano_api_port }}
 {% endif %}
 
+[engine]
+workers = {{ openstack_service_workers }}
+
 [database]
 connection = mysql+pymysql://{{ murano_database_user }}:{{ murano_database_password }}@{{ murano_database_address }}/{{ murano_database_name }}
 max_retries = -1
diff --git a/ansible/roles/neutron/templates/neutron.conf.j2 b/ansible/roles/neutron/templates/neutron.conf.j2
index f84226656e..0fa7078f01 100644
--- a/ansible/roles/neutron/templates/neutron.conf.j2
+++ b/ansible/roles/neutron/templates/neutron.conf.j2
@@ -14,6 +14,9 @@ bind_port = {{ neutron_server_port }}
 api_paste_config = /usr/share/neutron/api-paste.ini
 endpoint_type = internalURL
 
+api_workers = {{ openstack_service_workers }}
+metadata_works = {{ openstack_service_workers }}
+
 # NOTE(SamYaple): We must specify this value here rather than the metadata conf
 # because it is used by the l3 and dhcp agents. The reason the path has 'kolla'
 # in it is because we are sharing this socket in a volume which is it's own dir
diff --git a/ansible/roles/nova/templates/nova.conf.j2 b/ansible/roles/nova/templates/nova.conf.j2
index dde95a4d6a..f1dd54955e 100644
--- a/ansible/roles/nova/templates/nova.conf.j2
+++ b/ansible/roles/nova/templates/nova.conf.j2
@@ -14,6 +14,8 @@ secure_proxy_ssl_header = X-Forwarded-Proto
 
 osapi_compute_listen = {{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }}
 osapi_compute_listen_port = {{ nova_api_port }}
+osapi_compute_workers = {{ openstack_service_workers }}
+metadata_workers = {{ openstack_service_workers }}
 
 metadata_listen = {{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }}
 metadata_listen_port = {{ nova_metadata_port }}
@@ -60,6 +62,9 @@ compute_monitors=nova.compute.monitors.cpu.virt_driver
 {% endif %}
 {% endif %}
 
+[conductor]
+workers = {{ openstack_service_workers }}
+
 {% if nova_console == 'novnc' %}
 [vnc]
 novncproxy_host = {{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }}