 big_pipe.module                            |  2 ++
 big_pipe.services.yml                      |  2 +-
 src/Render/Placeholder/BigPipeStrategy.php | 54 ++++++++++++++++++++++++------
 3 files changed, 47 insertions(+), 11 deletions(-)

diff --git a/big_pipe.module b/big_pipe.module
index f2615e6..c9790dc 100644
--- a/big_pipe.module
+++ b/big_pipe.module
@@ -50,6 +50,8 @@ function big_pipe_form_after_build($form, FormStateInterface $form_state) {
 function big_pipe_form_set_js_check($form, FormStateInterface $form_state) {
   $current_user = \Drupal::currentUser();
 
+  // @todo Remove this, the big_pipe_has_js flag must be set on $_SESSION
+  // regardless of being logged in, see https://www.drupal.org/node/2603046#comment-10502380.
   if ($current_user->isAuthenticated()) {
     $_SESSION['big_pipe_has_js'] = $form_state->getValue('big_pipe_has_js') == 1;
   }
diff --git a/big_pipe.services.yml b/big_pipe.services.yml
index d93b9c7..b8ff9d4 100644
--- a/big_pipe.services.yml
+++ b/big_pipe.services.yml
@@ -6,9 +6,9 @@ services:
     arguments: ['@big_pipe']
   placeholder_strategy.big_pipe:
     class: Drupal\big_pipe\Render\Placeholder\BigPipeStrategy
+    arguments: ['@session_configuration', '@request_stack']
     tags:
       - { name: placeholder_strategy, priority: 0 }
-    arguments: ['@current_user']
   big_pipe:
     class: Drupal\big_pipe\Render\BigPipe
     arguments: ['@renderer', '@session', '@request_stack', '@http_kernel', '@event_dispatcher']
diff --git a/src/Render/Placeholder/BigPipeStrategy.php b/src/Render/Placeholder/BigPipeStrategy.php
index b672c6c..6dc5506 100644
--- a/src/Render/Placeholder/BigPipeStrategy.php
+++ b/src/Render/Placeholder/BigPipeStrategy.php
@@ -10,11 +10,23 @@ namespace Drupal\big_pipe\Render\Placeholder;
 use Drupal\Component\Utility\Html;
 use Drupal\Component\Utility\UrlHelper;
 use Drupal\Core\Render\Placeholder\PlaceholderStrategyInterface;
-use Drupal\Core\Session\AccountInterface;
+use Drupal\Core\Session\SessionConfigurationInterface;
+use Symfony\Component\HttpFoundation\RequestStack;
 
 /**
  * Defines the BigPipe placeholder strategy, to send HTML in chunks.
  *
+ * First: the BigPipe placeholder strategy only activates if the current request
+ * is associated with a session. Without a session, it is assumed this response
+ * is not actually dynamic: if none of the placeholders show session-dependent
+ * information, then none of the placeholders are uncacheable or poorly
+ * cacheable, which means the Page Cache (for anonymous users) can deal with it.
+ * In other words: BigPipe works for all authenticated users and for anonymous
+ * users that have a session (typical example: a shopping cart).
+ *
+ * (This is the default, and other modules can subclass this placeholder
+ * strategy to have different rules for enabling BigPipe.)
+ *
  * The BigPipe placeholder strategy actually consists of two substrategies,
  * depending on whether the current session is in a browser with JavaScript
  * enabled or not:
@@ -52,31 +64,53 @@ use Drupal\Core\Session\AccountInterface;
 class BigPipeStrategy implements PlaceholderStrategyInterface {
 
   /**
-   * The current user.
+   * The session configuration.
    *
-   * @var \Drupal\Core\Session\AccountInterface
+   * @var \Drupal\Core\Session\SessionConfigurationInterface
    */
-  protected $currentUser;
+  protected $sessionConfiguration;
+
+  /**
+   * The request stack.
+   *
+   * @var \Symfony\Component\HttpFoundation\RequestStack
+   */
+  protected $requestStack;
 
   /**
    * Constructs a new BigPipeStrategy class.
    *
-   * @param \Drupal\Core\Session\AccountInterface $current_user
-   *   The current user.
+   * @param \Drupal\Core\Session\SessionConfigurationInterface $session_configuration
+   *   The session configuration.
+   * @param \Symfony\Component\HttpFoundation\RequestStack
+   *   The request stack.
    */
-  public function __construct(AccountInterface $current_user) {
-    $this->currentUser = $current_user;
+  public function __construct(SessionConfigurationInterface $session_configuration, RequestStack $request_stack) {
+    $this->sessionConfiguration = $session_configuration;
+    $this->requestStack = $request_stack;
   }
 
   /**
    * {@inheritdoc}
    */
   public function processPlaceholders(array $placeholders) {
-    // @todo Remove in https://www.drupal.org/node/2603046.
-    if (!$this->currentUser->isAuthenticated()) {
+    if (!$this->sessionConfiguration->hasSession($this->requestStack->getCurrentRequest())) {
       return [];
     }
 
+    return $this->doProcessPlaceholders($placeholders);
+  }
+
+  /**
+   * Transforms placeholders to BigPipe placeholders, either no-JS or JS.
+   *
+   * @param array $placeholders
+   *  The placeholders to process.
+   *
+   * @return array
+   *  The BigPipe placeholders.
+   */
+  protected function doProcessPlaceholders(array $placeholders) {
     $overridden_placeholders = [];
     foreach ($placeholders as $placeholder => $placeholder_elements) {
       // BigPipe uses JavaScript and the DOM to find the placeholder to replace.
