diff --git a/core/lib/Drupal/Core/Session/SessionManager.php b/core/lib/Drupal/Core/Session/SessionManager.php
index 79813986786bc1567d495d1cc0ba2f63151c2eea..431959e99510d3b81c91a9457d9bb95d1a563ccc 100644
--- a/core/lib/Drupal/Core/Session/SessionManager.php
+++ b/core/lib/Drupal/Core/Session/SessionManager.php
@@ -216,7 +216,9 @@ public function regenerate($destroy = FALSE, $lifetime = NULL) {
       throw new \InvalidArgumentException('The optional parameters $destroy and $lifetime of SessionManager::regenerate() are not supported currently');
     }
 
-    if ($this->isStarted()) {
+    // Only migrate the session if the session is really started and not only
+    // lazy started.
+    if ($this->started) {
       $old_session_id = $this->getId();
       // Save and close the old session. Call the parent method to avoid issue
       // with session destruction due to the session being considered obsolete.
@@ -340,4 +342,19 @@ protected function migrateStoredSession($old_session_id) {
       ->execute();
   }
 
+  /**
+   * Checks if the session is started.
+   *
+   * Beginning with symfony/http-foundation 3.4.24, the session will no longer
+   * save unless this method returns true. The parent method returns true if
+   * $this->started is true, but we need the session to also save if we lazy
+   * started, so we override isStarted() here.
+   *
+   * @return bool
+   *   True if started, false otherwise
+   */
+  public function isStarted() {
+    return parent::isStarted() || $this->startedLazy;
+  }
+
 }