diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/EntityReferenceEntityFormatter.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/EntityReferenceEntityFormatter.php
index ee19523..6f3ce02 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/EntityReferenceEntityFormatter.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/EntityReferenceEntityFormatter.php
@@ -26,6 +26,13 @@
 class EntityReferenceEntityFormatter extends EntityReferenceFormatterBase implements ContainerFactoryPluginInterface {
 
   /**
+   * The number of times this formatter allows rendering the same entity.
+   *
+   * @var int
+   */
+  const RECURSIVE_RENDER_LIMIT = 20;
+
+  /**
    * The logger factory.
    *
    * @var \Drupal\Core\Logger\LoggerChannelFactoryInterface
@@ -47,7 +54,19 @@ class EntityReferenceEntityFormatter extends EntityReferenceFormatterBase implem
   protected $entityDisplayRepository;
 
   /**
-   * Constructs a StringFormatter instance.
+   * An array of counters for the recursive rendering protection.
+   *
+   * Each counter takes into account all the relevant information about the
+   * field and the referenced entity that is being rendered.
+   *
+   * @see \Drupal\Core\Field\Plugin\Field\FieldFormatter\EntityReferenceEntityFormatter::viewElements()
+   *
+   * @var array
+   */
+  protected static $recursiveRenderDepth = [];
+
+  /**
+   * Constructs a EntityReferenceEntityFormatter instance.
    *
    * @param string $plugin_id
    *   The plugin_id for the formatter.
@@ -141,15 +160,35 @@ public function viewElements(FieldItemListInterface $items, $langcode) {
     $elements = array();
 
     foreach ($this->getEntitiesToView($items, $langcode) as $delta => $entity) {
-      // Protect ourselves from recursive rendering.
-      static $depth = 0;
-      $depth++;
-      if ($depth > 20) {
-        $this->loggerFactory->get('entity')->error('Recursive rendering detected when rendering entity @entity_type @entity_id. Aborting rendering.', array('@entity_type' => $entity->getEntityTypeId(), '@entity_id' => $entity->id()));
-        return $elements;
-      }
-
       if ($entity->id()) {
+        // Due to render caching and delayed calls, the viewElements() method
+        // will be called later in the rendering process through a '#pre_render'
+        // callback, so we need to generate a counter that takes into account
+        // all the relevant information about this field and the referenced
+        // entity that is being rendered.
+        $recursive_render_id = $items->getFieldDefinition()->getTargetEntityTypeId()
+          . $items->getFieldDefinition()->getTargetBundle()
+          . $items->getName()
+          . $entity->id();
+
+        if (isset(static::$recursiveRenderDepth[$recursive_render_id])) {
+          static::$recursiveRenderDepth[$recursive_render_id]++;
+        }
+        else {
+          static::$recursiveRenderDepth[$recursive_render_id] = 1;
+        }
+
+        // Protect ourselves from recursive rendering.
+        if (static::$recursiveRenderDepth[$recursive_render_id] > static::RECURSIVE_RENDER_LIMIT) {
+          $this->loggerFactory->get('entity')->error('Recursive rendering detected when rendering entity %entity_type: %entity_id, using the %field_name field on the %bundle_name bundle. Aborting rendering.', [
+            '%entity_type' => $entity->getEntityTypeId(),
+            '%entity_id' => $entity->id(),
+            '%field_name' => $items->getName(),
+            '%bundle_name' => $items->getFieldDefinition()->getTargetBundle(),
+          ]);
+          return $elements;
+        }
+
         $view_builder = $this->entityTypeManager->getViewBuilder($entity->getEntityTypeId());
         $elements[$delta] = $view_builder->view($entity, $view_mode, $entity->language()->getId());
 
@@ -164,7 +203,6 @@ public function viewElements(FieldItemListInterface $items, $langcode) {
         // This is an "auto_create" item.
         $elements[$delta] = array('#markup' => $entity->label());
       }
-      $depth = 0;
     }
 
     return $elements;
diff --git a/core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceFormatterTest.php b/core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceFormatterTest.php
index a5bab76..4894a11 100644
--- a/core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceFormatterTest.php
+++ b/core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceFormatterTest.php
@@ -5,6 +5,7 @@
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Cache\CacheableMetadata;
 use Drupal\Core\Field\FieldStorageDefinitionInterface;
+use Drupal\Core\Field\Plugin\Field\FieldFormatter\EntityReferenceEntityFormatter;
 use Drupal\field\Entity\FieldConfig;
 use Drupal\field\Entity\FieldStorageConfig;
 use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
@@ -205,6 +206,68 @@ public function testEntityFormatter() {
   }
 
   /**
+   * Tests the recursive rendering protection of the entity formatter.
+   */
+  public function testEntityFormatterRecursiveRendering() {
+    /** @var \Drupal\Core\Render\RendererInterface $renderer */
+    $renderer = $this->container->get('renderer');
+    $formatter = 'entity_reference_entity_view';
+    $view_builder = $this->entityManager->getViewBuilder($this->entityType);
+
+    // Set the default view mode to use the 'entity_reference_entity_view'
+    // formatter.
+    entity_get_display($this->entityType, $this->bundle, 'default')
+      ->setComponent($this->fieldName, [
+        'type' => $formatter,
+      ])
+      ->save();
+
+    $referencing_entity_1 = entity_create($this->entityType, ['name' => $this->randomMachineName()]);
+    $referencing_entity_1->save();
+
+    // Create a self-reference.
+    $referencing_entity_1->{$this->fieldName}->entity = $referencing_entity_1;
+    $referencing_entity_1->save();
+
+    // Check that the recursive rendering stops after it reaches the specified
+    // limit.
+    $build = $view_builder->view($referencing_entity_1, 'default');
+    $output = $renderer->renderRoot($build);
+
+    // The title of entity_test entities is printed twice by default, so we have
+    // to multiply the formatter's recursive rendering protection limit by 2.
+    // Additionally, we have to take into account 2 additional occurrences of
+    // the entity title because we're rendering the full entity, not just the
+    // reference field.
+    $expected_occurrences = EntityReferenceEntityFormatter::RECURSIVE_RENDER_LIMIT * 2 + 2;
+    $actual_occurrences = substr_count($output, $referencing_entity_1->name->value);
+    $this->assertEqual($actual_occurrences, $expected_occurrences);
+
+    // Repeat the process with another entity in order to check that the
+    // 'recursive_render_id' counter is generated properly.
+    $referencing_entity_2 = entity_create($this->entityType, ['name' => $this->randomMachineName()]);
+    $referencing_entity_2->save();
+    $referencing_entity_2->{$this->fieldName}->entity = $referencing_entity_2;
+    $referencing_entity_2->save();
+
+    $build = $view_builder->view($referencing_entity_2, 'default');
+    $output = $renderer->renderRoot($build);
+
+    $actual_occurrences = substr_count($output, $referencing_entity_2->name->value);
+    $this->assertEqual($actual_occurrences, $expected_occurrences);
+
+    // Now render both entities at the same time and check again.
+    $build = $view_builder->viewMultiple([$referencing_entity_1, $referencing_entity_2], 'default');
+    $output = $renderer->renderRoot($build);
+
+    $actual_occurrences = substr_count($output, $referencing_entity_1->name->value);
+    $this->assertEqual($actual_occurrences, $expected_occurrences);
+
+    $actual_occurrences = substr_count($output, $referencing_entity_2->name->value);
+    $this->assertEqual($actual_occurrences, $expected_occurrences);
+  }
+
+  /**
    * Tests the label formatter.
    */
   public function testLabelFormatter() {
