diff --git a/stack/erp5/buildout.hash.cfg b/stack/erp5/buildout.hash.cfg
index ab95d16ec22ccc788295e6c2f0bd40408b6af686..f7e4ce95d0a8417b735c2e27c877375bd4e94097 100644
--- a/stack/erp5/buildout.hash.cfg
+++ b/stack/erp5/buildout.hash.cfg
@@ -78,7 +78,7 @@ md5sum = 68b329da9893e34099c7d8ad5cb9c940
 
 [template-erp5]
 filename = instance-erp5.cfg.in
-md5sum = 0920a53b10d3811a5f49930adffb62d8
+md5sum = 5ea4bcdf74fb429f254af8e8fb7b38a3
 
 [template-zeo]
 filename = instance-zeo.cfg.in
@@ -86,7 +86,7 @@ md5sum = 0648e38bd5d3a15bb9f93264932740b9
 
 [template-zope]
 filename = instance-zope.cfg.in
-md5sum = 41a224cf7bc42e582a7fd735ed64a618
+md5sum = d942854541f20faa57716b58959e1310
 
 [template-balancer]
 filename = instance-balancer.cfg.in
diff --git a/stack/erp5/instance-erp5.cfg.in b/stack/erp5/instance-erp5.cfg.in
index 73e24cf65e166174b6b370ab349fe7308c6edb2c..ca25cf4f10f780e784b98482c9ead088d4ba0d20 100644
--- a/stack/erp5/instance-erp5.cfg.in
+++ b/stack/erp5/instance-erp5.cfg.in
@@ -173,6 +173,7 @@ return =
   zope-address-list
   hosts-dict
   monitor-base-url
+  software-release-url
 {%- if test_runner_enabled %}
   test-runner-address-list
 {% endif %}
@@ -234,6 +235,7 @@ software-type = zope
 {% for custom_name, zope_parameter_dict in zope_partition_dict.items() -%}
 {%   set partition_name = 'zope-' ~ custom_name -%}
 {%   set section_name = 'request-' ~ partition_name -%}
+{%   set promise_software_url_section_name = 'promise-software-url' ~ partition_name -%}
 {%   set zope_family = zope_parameter_dict.get('family', 'default') -%}
 {%   do zope_family_name_list.append(zope_family) %}
 {%   set backend_path = zope_parameter_dict.get('backend-path', '') % {'site-id': site_id} %}
@@ -262,6 +264,18 @@ config-port-base = {{ dumps(zope_parameter_dict.get('port-base', 2200)) }}
 config-webdav = {{ dumps(zope_parameter_dict.get('webdav', False)) }}
 {%   if test_runner_enabled -%}
 config-test-runner-apache-url-list = ${publish-early:{{ zope_family }}-test-runner-url-list}
+
+[{{ promise_software_url_section_name }}]
+# Promise to wait for zope partition to use the expected software URL,
+# used on upgrades.
+recipe = slapos.cookbook:check_parameter
+value = {{ '${' ~ section_name ~ ':connection-software-release-url}' }}
+expected-not-value =
+expected-value = ${slap-connection:software-release-url}
+path = ${directory:bin}/${:_buildout_section_name_}
+
+{% do root_common.section(promise_software_url_section_name) -%}
+
 {%   endif -%}
 {% endfor -%}
 
diff --git a/stack/erp5/instance-zope.cfg.in b/stack/erp5/instance-zope.cfg.in
index 33ce4d9905917b4ca0ab9d45a9f7fd13daeec888..dac5079c18fd71aab528a1aec835000dc3fee803 100644
--- a/stack/erp5/instance-zope.cfg.in
+++ b/stack/erp5/instance-zope.cfg.in
@@ -549,6 +549,7 @@ hard to guess.
 hosts-dict = {{ dumps(hosts_dict) }}
 monitor-base-url = ${monitor-publish-parameters:monitor-base-url}
 test-runner-address-list = {{ dumps(test_runner_address_list) }}
+software-release-url = ${slap-connection:software-release-url}
 
 [monitor-instance-parameter]
 monitor-httpd-ipv6 = {{ (ipv6_set | list)[0] }}