diff --git a/docs/source/running-doorman.rst b/docs/source/running-doorman.rst
index 5915c23965..ddb69dd735 100644
--- a/docs/source/running-doorman.rst
+++ b/docs/source/running-doorman.rst
@@ -57,7 +57,7 @@ Allowed parameters are:
 
 :rootStorePath: Path for the root keystore
 
-:approveInterval: How often to process Jira approved requests in seconds
+:approveInterval: How often to process Jira approved requests in seconds. This will also be added to the http header, to be use as poll interval in Corda client.
 
 :signInterval: How often to sign the network map in seconds
 
diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/NetworkManagementServer.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/NetworkManagementServer.kt
index 919ca722be..dc829e64b3 100644
--- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/NetworkManagementServer.kt
+++ b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/NetworkManagementServer.kt
@@ -18,6 +18,7 @@ import net.corda.nodeapi.internal.network.NetworkParameters
 import net.corda.nodeapi.internal.persistence.CordaPersistence
 import java.io.Closeable
 import java.net.URI
+import java.time.Duration
 import java.time.Instant
 import java.util.concurrent.Executors
 import java.util.concurrent.TimeUnit
@@ -35,7 +36,7 @@ class NetworkManagementServer : Closeable {
             try {
                 closeAction()
             } catch (e: Exception) {
-                logger.warn("Discregarding exception thrown during close", e)
+                logger.warn("Disregarding exception thrown during close", e)
             }
         }
     }
@@ -111,7 +112,7 @@ class NetworkManagementServer : Closeable {
         scheduledExecutor.scheduleAtFixedRate(approvalThread, config.approveInterval, config.approveInterval, TimeUnit.MILLISECONDS)
         closeActions += scheduledExecutor::shutdown
 
-        return RegistrationWebService(requestProcessor)
+        return RegistrationWebService(requestProcessor, Duration.ofMillis(config.approveInterval))
     }
 
     fun start(hostAndPort: NetworkHostAndPort,
diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/webservice/RegistrationWebService.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/webservice/RegistrationWebService.kt
index 278bef3e63..7478cabc67 100644
--- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/webservice/RegistrationWebService.kt
+++ b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/webservice/RegistrationWebService.kt
@@ -8,6 +8,7 @@ import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_ROOT_CA
 import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest
 import java.io.ByteArrayOutputStream
 import java.io.InputStream
+import java.time.Duration
 import java.util.zip.ZipEntry
 import java.util.zip.ZipOutputStream
 import javax.servlet.http.HttpServletRequest
@@ -22,7 +23,7 @@ import javax.ws.rs.core.Response.Status.UNAUTHORIZED
  * Provides functionality for asynchronous submission of certificate signing requests and retrieval of the results.
  */
 @Path("certificate")
-class RegistrationWebService(private val csrHandler: CsrHandler) {
+class RegistrationWebService(private val csrHandler: CsrHandler, private val clientPollInterval: Duration) {
     @Context lateinit var request: HttpServletRequest
     /**
      * Accept stream of [PKCS10CertificationRequest] from user and persists in [CertificateRequestStorage] for approval.
@@ -63,7 +64,7 @@ class RegistrationWebService(private val csrHandler: CsrHandler) {
                         .type("application/zip")
                         .header("Content-Disposition", "attachment; filename=\"certificates.zip\"")
             }
-            is CertificateResponse.NotReady -> noContent()
+            is CertificateResponse.NotReady -> noContent().header("Cache-Control", "max-age=${clientPollInterval.seconds}")
             is CertificateResponse.Unauthorised -> status(UNAUTHORIZED).entity(response.message)
         }.build()
     }
diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/webservice/RegistrationWebServiceTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/webservice/RegistrationWebServiceTest.kt
index d17ec4dbf3..d74a3ff4af 100644
--- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/webservice/RegistrationWebServiceTest.kt
+++ b/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/webservice/RegistrationWebServiceTest.kt
@@ -9,6 +9,8 @@ import net.corda.core.crypto.Crypto
 import net.corda.core.crypto.SecureHash
 import net.corda.core.identity.CordaX500Name
 import net.corda.core.utilities.NetworkHostAndPort
+import net.corda.core.utilities.seconds
+import net.corda.node.utilities.registration.cacheControl
 import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair
 import net.corda.nodeapi.internal.crypto.CertificateType
 import net.corda.nodeapi.internal.crypto.X509CertificateFactory
@@ -43,6 +45,7 @@ class RegistrationWebServiceTest : TestBase() {
     private lateinit var webServer: NetworkManagementWebServer
     private lateinit var rootCaCert: X509Certificate
     private lateinit var intermediateCa: CertificateAndKeyPair
+    private val pollInterval = 10.seconds
 
     @Before
     fun init() {
@@ -52,7 +55,7 @@ class RegistrationWebServiceTest : TestBase() {
     }
 
     private fun startSigningServer(csrHandler: CsrHandler) {
-        webServer = NetworkManagementWebServer(NetworkHostAndPort("localhost", 0), RegistrationWebService(csrHandler))
+        webServer = NetworkManagementWebServer(NetworkHostAndPort("localhost", 0), RegistrationWebService(csrHandler, pollInterval))
         webServer.start()
     }
 
@@ -115,7 +118,9 @@ class RegistrationWebServiceTest : TestBase() {
         }
 
         startSigningServer(requestProcessor)
-        assertThat(pollForResponse(id)).isEqualTo(PollResponse.NotReady)
+
+        val response = pollForResponse(id)
+        assertEquals(pollInterval, (response as PollResponse.NotReady).pollInterval.seconds)
 
         requestProcessor.processRequests()
 
@@ -163,7 +168,9 @@ class RegistrationWebServiceTest : TestBase() {
         }
 
         startSigningServer(storage)
-        assertThat(pollForResponse(id)).isEqualTo(PollResponse.NotReady)
+        val response = pollForResponse(id)
+        assertEquals(pollInterval, (response as PollResponse.NotReady).pollInterval.seconds)
+
         storage.processRequests()
 
         val certificates = (pollForResponse(id) as PollResponse.Ready).certChain
@@ -218,14 +225,14 @@ class RegistrationWebServiceTest : TestBase() {
                 }
                 PollResponse.Ready(certificates)
             }
-            HTTP_NO_CONTENT -> PollResponse.NotReady
+            HTTP_NO_CONTENT -> PollResponse.NotReady(conn.cacheControl().maxAgeSeconds())
             HTTP_UNAUTHORIZED -> PollResponse.Unauthorised(IOUtils.toString(conn.errorStream, UTF_8))
             else -> throw IOException("Cannot connect to Certificate Signing Server, HTTP response code : ${conn.responseCode}")
         }
     }
 
     private interface PollResponse {
-        object NotReady : PollResponse
+        data class NotReady(val pollInterval: Int) : PollResponse
         data class Ready(val certChain: List<X509Certificate>) : PollResponse
         data class Unauthorised(val message: String) : PollResponse
     }
diff --git a/node/src/main/kotlin/net/corda/node/services/network/NetworkMapClient.kt b/node/src/main/kotlin/net/corda/node/services/network/NetworkMapClient.kt
index 9c12056315..39b4a2eb31 100644
--- a/node/src/main/kotlin/net/corda/node/services/network/NetworkMapClient.kt
+++ b/node/src/main/kotlin/net/corda/node/services/network/NetworkMapClient.kt
@@ -14,6 +14,7 @@ import net.corda.core.utilities.seconds
 import net.corda.core.utilities.trace
 import net.corda.node.services.api.NetworkMapCacheInternal
 import net.corda.node.utilities.NamedThreadFactory
+import net.corda.node.utilities.registration.cacheControl
 import net.corda.nodeapi.internal.SignedNodeInfo
 import net.corda.nodeapi.internal.network.NetworkMap
 import net.corda.nodeapi.internal.network.NetworkParameters
@@ -54,7 +55,7 @@ class NetworkMapClient(compatibilityZoneURL: URL, private val trustedRoot: X509C
         val connection = networkMapUrl.openHttpConnection()
         val signedNetworkMap = connection.responseAs<SignedDataWithCert<NetworkMap>>()
         val networkMap = signedNetworkMap.verifiedNetworkMapCert(trustedRoot)
-        val timeout = CacheControl.parse(Headers.of(connection.headerFields.filterKeys { it != null }.mapValues { it.value[0] })).maxAgeSeconds().seconds
+        val timeout = connection.cacheControl().maxAgeSeconds().seconds
         logger.trace { "Fetched network map update from $networkMapUrl successfully, retrieved ${networkMap.nodeInfoHashes.size} node info hashes. Node Info hashes: ${networkMap.nodeInfoHashes.joinToString("\n")}" }
         return NetworkMapResponse(networkMap, timeout)
     }
diff --git a/node/src/main/kotlin/net/corda/node/utilities/registration/HTTPNetworkRegistrationService.kt b/node/src/main/kotlin/net/corda/node/utilities/registration/HTTPNetworkRegistrationService.kt
index ce6d974184..2a6236c10c 100644
--- a/node/src/main/kotlin/net/corda/node/utilities/registration/HTTPNetworkRegistrationService.kt
+++ b/node/src/main/kotlin/net/corda/node/utilities/registration/HTTPNetworkRegistrationService.kt
@@ -2,7 +2,10 @@ package net.corda.node.utilities.registration
 
 import com.google.common.net.MediaType
 import net.corda.core.internal.openHttpConnection
+import net.corda.core.utilities.seconds
 import net.corda.nodeapi.internal.crypto.X509CertificateFactory
+import okhttp3.CacheControl
+import okhttp3.Headers
 import org.apache.commons.io.IOUtils
 import org.bouncycastle.pkcs.PKCS10CertificationRequest
 import java.io.IOException
@@ -22,10 +25,13 @@ class HTTPNetworkRegistrationService(compatibilityZoneURL: URL) : NetworkRegistr
     }
 
     @Throws(CertificateRequestException::class)
-    override fun retrieveCertificates(requestId: String): List<X509Certificate>? {
+    override fun retrieveCertificates(requestId: String): CertificateResponse {
         // Poll server to download the signed certificate once request has been approved.
         val conn = URL("$registrationURL/$requestId").openHttpConnection()
         conn.requestMethod = "GET"
+        val maxAge = conn.cacheControl().maxAgeSeconds()
+        // Default poll interval to 10 seconds if not specified by the server, for backward compatibility.
+        val pollInterval = if (maxAge == -1) 10.seconds else maxAge.seconds
 
         return when (conn.responseCode) {
             HTTP_OK -> ZipInputStream(conn.inputStream).use {
@@ -34,9 +40,9 @@ class HTTPNetworkRegistrationService(compatibilityZoneURL: URL) : NetworkRegistr
                 while (it.nextEntry != null) {
                     certificates += factory.generateCertificate(it)
                 }
-                certificates
+                CertificateResponse(pollInterval, certificates)
             }
-            HTTP_NO_CONTENT -> null
+            HTTP_NO_CONTENT -> CertificateResponse(pollInterval, null)
             HTTP_UNAUTHORIZED -> throw CertificateRequestException("Certificate signing request has been rejected: ${conn.errorMessage}")
             else -> throwUnexpectedResponseCode(conn)
         }
@@ -66,3 +72,5 @@ class HTTPNetworkRegistrationService(compatibilityZoneURL: URL) : NetworkRegistr
 
     private val HttpURLConnection.errorMessage: String get() = IOUtils.toString(errorStream, charset)
 }
+
+fun HttpURLConnection.cacheControl(): CacheControl = CacheControl.parse(Headers.of(headerFields.filterKeys { it != null }.mapValues { it.value[0] }))
diff --git a/node/src/main/kotlin/net/corda/node/utilities/registration/NetworkRegistrationHelper.kt b/node/src/main/kotlin/net/corda/node/utilities/registration/NetworkRegistrationHelper.kt
index a940a28a05..287f4b41c9 100644
--- a/node/src/main/kotlin/net/corda/node/utilities/registration/NetworkRegistrationHelper.kt
+++ b/node/src/main/kotlin/net/corda/node/utilities/registration/NetworkRegistrationHelper.kt
@@ -3,7 +3,6 @@ package net.corda.node.utilities.registration
 import net.corda.core.crypto.Crypto
 import net.corda.core.identity.CordaX500Name
 import net.corda.core.internal.*
-import net.corda.core.utilities.seconds
 import net.corda.node.services.config.NodeConfiguration
 import net.corda.nodeapi.internal.crypto.CertificateType
 import net.corda.nodeapi.internal.crypto.X509KeyStore
@@ -28,7 +27,6 @@ class NetworkRegistrationHelper(private val config: NodeConfiguration,
                                 networkRootTrustStorePath: Path,
                                 networkRootTruststorePassword: String) {
     private companion object {
-        val pollInterval = 10.seconds
         const val SELF_SIGNED_PRIVATE_KEY = "Self Signed Private Key"
     }
 
@@ -148,17 +146,18 @@ class NetworkRegistrationHelper(private val config: NodeConfiguration,
      * Poll Certificate Signing Server for approved certificate,
      * enter a slow polling loop if server return null.
      * @param requestId Certificate signing request ID.
-     * @return Map of certificate chain.
+     * @return List of certificate chain.
      */
     private fun pollServerForCertificates(requestId: String): List<X509Certificate> {
         println("Start polling server for certificate signing approval.")
         // Poll server to download the signed certificate once request has been approved.
-        var certificates = certService.retrieveCertificates(requestId)
-        while (certificates == null) {
+        while (true) {
+            val (pollInterval, certificates) = certService.retrieveCertificates(requestId)
+            if (certificates != null) {
+                return certificates
+            }
             Thread.sleep(pollInterval.toMillis())
-            certificates = certService.retrieveCertificates(requestId)
         }
-        return certificates
     }
 
     /**
diff --git a/node/src/main/kotlin/net/corda/node/utilities/registration/NetworkRegistrationService.kt b/node/src/main/kotlin/net/corda/node/utilities/registration/NetworkRegistrationService.kt
index beea4635d5..cafc16dd45 100644
--- a/node/src/main/kotlin/net/corda/node/utilities/registration/NetworkRegistrationService.kt
+++ b/node/src/main/kotlin/net/corda/node/utilities/registration/NetworkRegistrationService.kt
@@ -4,6 +4,7 @@ import net.corda.core.CordaException
 import net.corda.core.serialization.CordaSerializable
 import org.bouncycastle.pkcs.PKCS10CertificationRequest
 import java.security.cert.X509Certificate
+import java.time.Duration
 
 interface NetworkRegistrationService {
     /** Submits a CSR to the signing service and returns an opaque request ID. */
@@ -11,8 +12,10 @@ interface NetworkRegistrationService {
 
     /** Poll Certificate Signing Server for the request and returns a chain of certificates if request has been approved, null otherwise. */
     @Throws(CertificateRequestException::class)
-    fun retrieveCertificates(requestId: String): List<X509Certificate>?
+    fun retrieveCertificates(requestId: String): CertificateResponse
 }
 
+data class CertificateResponse(val pollInterval: Duration, val certificates: List<X509Certificate>?)
+
 @CordaSerializable
 class CertificateRequestException(message: String) : CordaException(message)
diff --git a/node/src/test/kotlin/net/corda/node/utilities/registration/NetworkRegistrationHelperTest.kt b/node/src/test/kotlin/net/corda/node/utilities/registration/NetworkRegistrationHelperTest.kt
index e7e6775a5e..2371ab4437 100644
--- a/node/src/test/kotlin/net/corda/node/utilities/registration/NetworkRegistrationHelperTest.kt
+++ b/node/src/test/kotlin/net/corda/node/utilities/registration/NetworkRegistrationHelperTest.kt
@@ -12,6 +12,7 @@ import net.corda.core.identity.CordaX500Name
 import net.corda.core.internal.createDirectories
 import net.corda.core.internal.div
 import net.corda.core.internal.x500Name
+import net.corda.core.utilities.seconds
 import net.corda.node.services.config.NodeConfiguration
 import net.corda.nodeapi.internal.crypto.CertificateType
 import net.corda.nodeapi.internal.crypto.X509KeyStore
@@ -158,7 +159,7 @@ class NetworkRegistrationHelperTest {
     private fun createRegistrationHelper(response: List<X509Certificate>): NetworkRegistrationHelper {
         val certService = rigorousMock<NetworkRegistrationService>().also {
             doReturn(requestId).whenever(it).submitRequest(any())
-            doReturn(response).whenever(it).retrieveCertificates(eq(requestId))
+            doReturn(CertificateResponse(5.seconds, response)).whenever(it).retrieveCertificates(eq(requestId))
         }
         return NetworkRegistrationHelper(config, certService, config.certificatesDirectory / networkRootTrustStoreFileName, networkRootTrustStorePassword)
     }