diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index fa5caee..113ca84 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -80,17 +80,6 @@
 const COMMENT_OPEN = 2;
 
 /**
- * The time cutoff for comments marked as read for entity types other node.
- *
- * Comments changed before this time are always marked as read.
- * Comments changed after this time may be marked new, updated, or read,
- * depending on their state for the current user. Defaults to 30 days ago.
- *
- * @todo Remove when http://drupal.org/node/1029708 lands.
- */
-define('COMMENT_NEW_LIMIT', REQUEST_TIME - 30 * 24 * 60 * 60);
-
-/**
  * Implements hook_help().
  */
 function comment_help($path, $arg) {
@@ -1162,31 +1151,18 @@ function comment_load($cid, $reset = FALSE) {
  *   Entity type of the entity to which the comments are attached.
  * @param string $field_name
  *   (optional) The field_name to count comments for. Defaults to NULL.
- * @param $timestamp
- *   Time to count from (defaults to time of last user access
- *   to node).
+ * @param int $timestamp
+ *   (optional) Time to count from (defaults to time at which the current user
+ *   last viewed the entity).
  *
- * @return
+ * @return int|false
  *   The number of new comments or FALSE if the user is not logged in.
  */
 function comment_num_new($entity_id, $entity_type, $field_name = NULL, $timestamp = 0) {
   if (\Drupal::currentUser()->isAuthenticated() && \Drupal::moduleHandler()->moduleExists('history')) {
     // Retrieve the timestamp at which the current user last viewed this entity.
     if (!$timestamp) {
-      if ($entity_type == 'node') {
-        $timestamp = history_read($entity_id);
-      }
-      else {
-        $function = $entity_type . '_last_viewed';
-        if (function_exists($function)) {
-          $timestamp = $function($entity_id);
-        }
-        else {
-          // Default to 30 days ago.
-          // @todo Remove once http://drupal.org/node/1029708 lands.
-          $timestamp = COMMENT_NEW_LIMIT;
-        }
-      }
+      $timestamp = \Drupal::service('history.manager')->read($entity_type, array($entity_id));
     }
     $timestamp = ($timestamp > HISTORY_READ_LIMIT ? $timestamp : HISTORY_READ_LIMIT);
 
@@ -1208,7 +1184,6 @@ function comment_num_new($entity_id, $entity_type, $field_name = NULL, $timestam
   else {
     return FALSE;
   }
-
 }
 
 /**
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentLinksTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentLinksTest.php
index c529ab9..45c2953 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/CommentLinksTest.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentLinksTest.php
@@ -154,6 +154,10 @@ function setEnvironment(array $info) {
         ));
         $comment->save();
         $this->comment = $comment;
+
+        // comment_num_new() relies on history_read(), so ensure that no one has
+        // seen the node of this comment.
+        \Drupal::service('history.manager')->deleteByEntity($this->node);
       }
       else {
         $cids = db_query("SELECT cid FROM {comment}")->fetchCol();
diff --git a/core/modules/forum/forum.services.yml b/core/modules/forum/forum.services.yml
index f27ffc0..7a0f704 100644
--- a/core/modules/forum/forum.services.yml
+++ b/core/modules/forum/forum.services.yml
@@ -1,7 +1,8 @@
 services:
   forum_manager:
     class: Drupal\forum\ForumManager
-    arguments: ['@config.factory', '@entity.manager', '@database', '@field.info', '@string_translation']
+    # The history.manager service is optional to allow upgrade path.
+    arguments: ['@config.factory', '@entity.manager', '@database', '@field.info', '@string_translation', '@?history.manager']
   forum.breadcrumb:
     class: Drupal\forum\ForumBreadcrumbBuilder
     arguments: ['@entity.manager', '@config.factory', '@forum_manager']
diff --git a/core/modules/forum/lib/Drupal/forum/ForumManager.php b/core/modules/forum/lib/Drupal/forum/ForumManager.php
index cdf9a5e..2feeb01 100644
--- a/core/modules/forum/lib/Drupal/forum/ForumManager.php
+++ b/core/modules/forum/lib/Drupal/forum/ForumManager.php
@@ -12,6 +12,7 @@
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\StringTranslation\TranslationInterface;
 use Drupal\field\FieldInfo;
+use Drupal\history\HistoryManagerInterface;
 use Drupal\node\NodeInterface;
 
 /**
@@ -110,6 +111,13 @@ class ForumManager implements ForumManagerInterface {
   protected $translationManager;
 
   /**
+   * The history manager service.
+   *
+   * @var \Drupal\history\HistoryManagerInterface
+   */
+  protected $historyManager;
+
+  /**
    * Constructs the forum manager service.
    *
    * @param \Drupal\Core\Config\ConfigFactory $config_factory
@@ -122,13 +130,16 @@ class ForumManager implements ForumManagerInterface {
    *   The field info service.
    * @param \Drupal\Core\StringTranslation\TranslationInterface $translation_manager
    *   The translation manager service.
+   * @param \Drupal\history\HistoryManagerInterface $history_manager
+   *   The history manager service.
    */
-  public function __construct(ConfigFactory $config_factory, EntityManagerInterface $entity_manager, Connection $connection, FieldInfo $field_info, TranslationInterface $translation_manager) {
+  public function __construct(ConfigFactory $config_factory, EntityManagerInterface $entity_manager, Connection $connection, FieldInfo $field_info, TranslationInterface $translation_manager, HistoryManagerInterface $history_manager = NULL) {
     $this->configFactory = $config_factory;
     $this->entityManager = $entity_manager;
     $this->connection = $connection;
     $this->fieldInfo = $field_info;
     $this->translationManager = $translation_manager;
+    $this->historyManager = $history_manager;
   }
 
   /**
@@ -329,16 +340,19 @@ protected function numberNew($nid, $timestamp) {
   protected function lastVisit($nid) {
     $user = \Drupal::currentUser();
 
+    if (isset($this->history[$nid])) {
+      return $this->history[$nid];
+    }
+
+    if (isset($this->historyManager)) {
+      // History manager service could not be available.
+      $this->history[$nid] = $this->historyManager->read('node', array($nid));
+    }
     if (empty($this->history[$nid])) {
-      $result = $this->connection->select('history', 'h')
-        ->fields('h', array('nid', 'timestamp'))
-        ->condition('uid', $user->id())
-        ->execute();
-      foreach ($result as $t) {
-        $this->history[$t->nid] = $t->timestamp > HISTORY_READ_LIMIT ? $t->timestamp : HISTORY_READ_LIMIT;
-      }
+      $this->history[$nid] = HISTORY_READ_LIMIT;
     }
-    return isset($this->history[$nid]) ? $this->history[$nid] : HISTORY_READ_LIMIT;
+
+    return $this->history[$nid];
   }
 
   /**
@@ -498,7 +512,7 @@ public function checkNodeType(NodeInterface $node) {
   public function unreadTopics($term, $uid) {
     $query = $this->connection->select('node_field_data', 'n');
     $query->join('forum', 'f', 'n.vid = f.vid AND f.tid = :tid', array(':tid' => $term));
-    $query->leftJoin('history', 'h', 'n.nid = h.nid AND h.uid = :uid', array(':uid' => $uid));
+    $query->leftJoin('history', 'h', "n.nid = h.entity_id AND h.entity_type = 'node' AND h.uid = :uid", array(':uid' => $uid));
     $query->addExpression('COUNT(n.nid)', 'count');
     return $query
       ->condition('status', 1)
@@ -506,7 +520,7 @@ public function unreadTopics($term, $uid) {
       //   field language and just fall back to the default language.
       ->condition('n.default_langcode', 1)
       ->condition('n.created', HISTORY_READ_LIMIT, '>')
-      ->isNull('h.nid')
+      ->isNull('h.entity_id')
       ->addTag('node_access')
       ->execute()
       ->fetchField();
diff --git a/core/modules/history/history.install b/core/modules/history/history.install
index dcfd871..482ac9f 100644
--- a/core/modules/history/history.install
+++ b/core/modules/history/history.install
@@ -10,16 +10,23 @@
  */
 function history_schema() {
   $schema['history'] = array(
-    'description' => 'A record of which {users} have read which {node}s.',
+    'description' => 'A record of which {users} have read which {entities}s.',
     'fields' => array(
       'uid' => array(
-        'description' => 'The {users}.uid that read the {node} nid.',
+        'description' => 'The {users}.uid that read the {history}.entity_id entity.',
         'type' => 'int',
         'not null' => TRUE,
         'default' => 0,
       ),
-      'nid' => array(
-        'description' => 'The {node}.nid that was read.',
+      'entity_type' => array(
+        'description' => 'The type of the entity that was read.',
+        'type' => 'varchar',
+        'not null' => TRUE,
+        'default' => 'node',
+        'length' => 255,
+      ),
+      'entity_id' => array(
+        'description' => 'The ID of the entity that was read.',
         'type' => 'int',
         'not null' => TRUE,
         'default' => 0,
@@ -31,11 +38,19 @@ function history_schema() {
         'default' => 0,
       ),
     ),
-    'primary key' => array('uid', 'nid'),
+    'primary key' => array(
+      'uid',
+      'entity_id',
+      array('entity_type', 32),
+    ),
     'indexes' => array(
-      'nid' => array('nid'),
+      'history_entity' => array(
+        'entity_id',
+        array('entity_type', 32),
+      ),
     ),
   );
 
   return $schema;
 }
+
diff --git a/core/modules/history/history.module b/core/modules/history/history.module
index 8aeb74e..303b879 100644
--- a/core/modules/history/history.module
+++ b/core/modules/history/history.module
@@ -10,6 +10,7 @@
  */
 
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Session\AccountInterface;
 use Drupal\entity\Entity\EntityDisplay;
 
 /**
@@ -41,9 +42,11 @@ function history_help($path, $arg) {
  * @return int
  *   If a node has been previously viewed by the user, the timestamp in seconds
  *   of when the last view occurred; otherwise, zero.
+ *
+ * @deprecated Use \Drupal\history\HistoryManager::read() instead.
  */
 function history_read($nid) {
-  $history = history_read_multiple(array($nid));
+  $history = \Drupal::service('history.manager')->read('node', array($nid));
   return $history[$nid];
 }
 
@@ -57,75 +60,33 @@ function history_read($nid) {
  *   Array of timestamps keyed by node ID. If a node has been previously viewed
  *   by the user, the timestamp in seconds of when the last view occurred;
  *   otherwise, zero.
+ *
+ * @deprecated Use \Drupal\history\HistoryManager::read() instead.
  */
 function history_read_multiple($nids) {
-  $history = &drupal_static(__FUNCTION__, array());
-
-  $return = array();
-
-  $nodes_to_read = array();
-  foreach ($nids as $nid) {
-    if (isset($history[$nid])) {
-      $return[$nid] = $history[$nid];
-    }
-    else {
-      // Initialize value if current user has not viewed the node.
-      $nodes_to_read[$nid] = 0;
-    }
-  }
-
-  if (empty($nodes_to_read)) {
-    return $return;
-  }
-
-  $result = db_query('SELECT nid, timestamp FROM {history} WHERE uid = :uid AND nid IN(:nids)', array(
-    ':uid' => \Drupal::currentUser()->id(),
-    ':nids' => array_keys($nodes_to_read),
-  ));
-  foreach ($result as $row) {
-    $nodes_to_read[$row->nid] = (int) $row->timestamp;
-  }
-  $history += $nodes_to_read;
-
-  return $return + $nodes_to_read;
+  return \Drupal::service('history.manager')->read('node', $nids);
 }
 
 /**
  * Updates 'last viewed' timestamp of the specified entity for the current user.
  *
- * @param $nid
+ * @param int $nid
  *   The node ID that has been read.
- * @param $account
+ * @param \Drupal\Core\Session\AccountInterface $account
  *   (optional) The user account to update the history for. Defaults to the
  *   current user.
+ *
+ * @deprecated Use \Drupal\history\HistoryManager::write() instead.
  */
-function history_write($nid, $account = NULL) {
-
-  if (!isset($account)) {
-    $account = \Drupal::currentUser();
-  }
-
-  if ($account->isAuthenticated()) {
-    db_merge('history')
-      ->key(array(
-        'uid' => $account->id(),
-        'nid' => $nid,
-      ))
-      ->fields(array('timestamp' => REQUEST_TIME))
-      ->execute();
-    // Update static cache.
-    $history = &drupal_static('history_read_multiple', array());
-    $history[$nid] = REQUEST_TIME;
-  }
+function history_write($nid, AccountInterface $account = NULL) {
+  \Drupal::service('history.manager')->write('node', $nid, $account);
 }
 
 /**
  * Implements hook_cron().
  */
 function history_cron() {
-  db_delete('history')
-    ->condition('timestamp', HISTORY_READ_LIMIT, '<')
-    ->execute();
+  \Drupal::service('history.manager')->purge();
 }
 
 /**
@@ -156,9 +117,7 @@ function history_node_view_alter(&$build, EntityInterface $node, EntityDisplay $
  * Implements hook_node_delete().
  */
 function history_node_delete(EntityInterface $node) {
-  db_delete('history')
-    ->condition('nid', $node->id())
-    ->execute();
+  \Drupal::service('history.manager')->deleteByEntity($node);
 }
 
 /**
@@ -167,9 +126,7 @@ function history_node_delete(EntityInterface $node) {
 function history_user_cancel($edit, $account, $method) {
   switch ($method) {
     case 'user_cancel_reassign':
-      db_delete('history')
-        ->condition('uid', $account->id())
-        ->execute();
+      \Drupal::service('history.manager')->deleteByUser($account);
       break;
   }
 }
@@ -178,9 +135,7 @@ function history_user_cancel($edit, $account, $method) {
  * Implements hook_user_delete().
  */
 function history_user_delete($account) {
-  db_delete('history')
-    ->condition('uid', $account->id())
-    ->execute();
+  \Drupal::service('history.manager')->deleteByUser($account);
 }
 
 /**
diff --git a/core/modules/history/history.services.yml b/core/modules/history/history.services.yml
new file mode 100644
index 0000000..49285ec
--- /dev/null
+++ b/core/modules/history/history.services.yml
@@ -0,0 +1,4 @@
+services:
+  history.manager:
+    class: Drupal\history\HistoryManager
+    arguments: ['@database']
diff --git a/core/modules/history/history.views.inc b/core/modules/history/history.views.inc
index 50e12aa..571d7f3 100644
--- a/core/modules/history/history.views.inc
+++ b/core/modules/history/history.views.inc
@@ -22,8 +22,9 @@ function history_views_data() {
     'node' => array(
       'table' => 'history',
       'left_field' => 'nid',
-      'field' => 'nid',
+      'field' => 'entity_id',
       'extra' => array(
+        array('field' => 'entity_type', 'value' => 'node'),
         array('field' => 'uid', 'value' => '***CURRENT_USER***', 'numeric' => TRUE),
       ),
     ),
diff --git a/core/modules/history/lib/Drupal/history/Controller/HistoryController.php b/core/modules/history/lib/Drupal/history/Controller/HistoryController.php
index b605e6e..fc9e243 100644
--- a/core/modules/history/lib/Drupal/history/Controller/HistoryController.php
+++ b/core/modules/history/lib/Drupal/history/Controller/HistoryController.php
@@ -7,6 +7,9 @@
 
 namespace Drupal\history\Controller;
 
+use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
+use Drupal\history\HistoryManagerInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\JsonResponse;
 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
@@ -17,7 +20,33 @@
 /**
  * Returns responses for History module routes.
  */
-class HistoryController extends ControllerBase {
+class HistoryController extends ControllerBase implements ContainerInjectionInterface {
+
+  /**
+   * The history manager service.
+   *
+   * @var \Drupal\history\HistoryManagerInterface
+   */
+  protected $historyManager;
+
+  /**
+   * Constructs a HistoryController.
+   *
+   * @param \Drupal\history\HistoryManagerInterface $history_manager
+   *   The history manager service.
+   */
+  public function __construct(HistoryManagerInterface $history_manager) {
+    $this->historyManager = $history_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('history.manager')
+    );
+  }
 
   /**
    * Returns a set of nodes' last read timestamps.
@@ -25,7 +54,7 @@ class HistoryController extends ControllerBase {
    * @param \Symfony\Component\HttpFoundation\Request $request
    *   The request of the page.
    *
-   * @return Symfony\Component\HttpFoundation\JsonResponse
+   * @return \Symfony\Component\HttpFoundation\JsonResponse
    *   The JSON response.
    */
   public function getNodeReadTimestamps(Request $request) {
@@ -37,7 +66,7 @@ public function getNodeReadTimestamps(Request $request) {
     if (!isset($nids)) {
       throw new NotFoundHttpException();
     }
-    return new JsonResponse(history_read_multiple($nids));
+    return new JsonResponse($this->historyManager->read('node', $nids));
   }
 
   /**
@@ -54,9 +83,10 @@ public function readNode(Request $request, NodeInterface $node) {
     }
 
     // Update the history table, stating that this user viewed this node.
-    history_write($node->id());
+    $this->historyManager->write('node', $node->id());
 
-    return new JsonResponse((int)history_read($node->id()));
+    $history = $this->historyManager->read('node', array($node->id()));
+    return new JsonResponse($history[$node->id()]);
   }
 
 }
diff --git a/core/modules/history/lib/Drupal/history/HistoryManager.php b/core/modules/history/lib/Drupal/history/HistoryManager.php
new file mode 100644
index 0000000..7e0fd29
--- /dev/null
+++ b/core/modules/history/lib/Drupal/history/HistoryManager.php
@@ -0,0 +1,144 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\history\HistoryManager.
+ */
+
+namespace Drupal\history;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Session\AccountInterface;
+
+/**
+ * Provides history manager service.
+ */
+class HistoryManager implements HistoryManagerInterface {
+
+  /**
+   * Array of history keyed by entity type and entity id.
+   *
+   * @var array
+   */
+  protected $history = array();
+
+  /**
+   * Database connection
+   *
+   * @var \Drupal\Core\Database\Connection
+   */
+  protected $connection;
+
+  /**
+   * Constructs the history manager service.
+   *
+   * @param \Drupal\Core\Database\Connection $connection
+   *   The current database connection.
+   */
+  public function __construct(Connection $connection) {
+    $this->connection = $connection;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function read($entity_type, $entity_ids) {
+    $return = array();
+
+    $entities_to_read = array();
+    foreach ($entity_ids as $entity_id) {
+      if (isset($this->history[$entity_type][$entity_id])) {
+        $return[$entity_id] = $this->history[$entity_type][$entity_id];
+      }
+      else {
+        $entities_to_read[$entity_id] = 0;
+      }
+    }
+
+    if (empty($entities_to_read)) {
+      return $return;
+    }
+
+    $result = $this->connection->select('history', 'h')
+      ->fields('h', array('entity_id', 'timestamp'))
+      ->condition('uid', \Drupal::currentUser()->id())
+      ->condition('entity_type', $entity_type)
+      ->condition('entity_id', array_keys($entities_to_read), 'IN')
+      ->execute();
+
+    foreach ($result as $row) {
+      $entities_to_read[$row->entity_id] = (int) $row->timestamp;
+    }
+    if (!isset($this->history[$entity_type])) {
+      $this->history[$entity_type] = array();
+    }
+    $this->history[$entity_type] += $entities_to_read;
+
+    return $return + $entities_to_read;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function write($entity_type, $entity_id, AccountInterface $account = NULL) {
+    if (!isset($account)) {
+      $account = \Drupal::currentUser();
+    }
+
+    if ($account->isAuthenticated()) {
+      $this->connection->merge('history')
+        ->key(array(
+          'uid' => $account->id(),
+          'entity_id' => $entity_id,
+          'entity_type' => $entity_type,
+        ))
+        ->fields(array('timestamp' => REQUEST_TIME))
+        ->execute();
+      // Update cached value.
+      $this->history[$entity_type][$entity_id] = REQUEST_TIME;
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function purge() {
+    $this->connection->delete('history')
+      ->condition('timestamp', HISTORY_READ_LIMIT, '<')
+      ->execute();
+    // Clean static cache.
+    $this->resetCache();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function deleteByUser(AccountInterface $account) {
+    $this->connection->delete('history')
+      ->condition('uid', $account->id())
+      ->execute();
+    // Clean static cache.
+    $this->resetCache();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function deleteByEntity(EntityInterface $entity) {
+    $this->connection->delete('history')
+      ->condition('entity_id', $entity->id())
+      ->condition('entity_type', $entity->entityType())
+      ->execute();
+    // Clean static cache.
+    unset($this->history[$entity->entityType()][$entity->id()]);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function resetCache() {
+    $this->history = array();
+  }
+
+}
diff --git a/core/modules/history/lib/Drupal/history/HistoryManagerInterface.php b/core/modules/history/lib/Drupal/history/HistoryManagerInterface.php
new file mode 100644
index 0000000..7430c13
--- /dev/null
+++ b/core/modules/history/lib/Drupal/history/HistoryManagerInterface.php
@@ -0,0 +1,72 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\history\HistoryManagerInterface.
+ */
+
+namespace Drupal\history;
+
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Session\AccountInterface;
+
+/**
+ * Provides history manager interface.
+ */
+interface HistoryManagerInterface {
+
+  /**
+   * Retrieves the timestamp for the current user's last view of the entities.
+   *
+   * @param string $entity_type
+   *   The entity type.
+   * @param array $entity_ids
+   *   The entity IDs.
+   *
+   * @return array
+   *   Array of timestamps keyed by entity ID. If a entity has been previously
+   *   viewed by the user, the timestamp in seconds of when the last view
+   *   occurred; otherwise, zero.
+   */
+  public function read($entity_type, $entity_ids);
+
+  /**
+   * Updates 'last viewed' timestamp of the entity for the current user.
+   *
+   * @param string $entity_type
+   *   The entity type.
+   * @param int $entity_id
+   *   The entity ID that has been read.
+   * @param \Drupal\Core\Session\AccountInterface $account
+   *   (optional) The user account to update the history for. Defaults to the
+   *   current user.
+   */
+  public function write($entity_type, $entity_id, AccountInterface $account = NULL);
+
+  /**
+   * Purges outdated history.
+   */
+  public function purge();
+
+  /**
+   * Deletes history of the user account.
+   *
+   * @param \Drupal\Core\Session\AccountInterface $account
+   *   The user account to purge history
+   */
+  public function deleteByUser(AccountInterface $account);
+
+  /**
+   * Deletes history for the given entity.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The entity that history should be deleted.
+   */
+  public function deleteByEntity(EntityInterface $entity);
+
+  /**
+   * Resets the static cache.
+   */
+  public function resetCache();
+
+}
diff --git a/core/modules/history/lib/Drupal/history/Tests/Views/HistoryTimestampTest.php b/core/modules/history/lib/Drupal/history/Tests/Views/HistoryTimestampTest.php
index 182174c..6eaca65 100644
--- a/core/modules/history/lib/Drupal/history/Tests/Views/HistoryTimestampTest.php
+++ b/core/modules/history/lib/Drupal/history/Tests/Views/HistoryTimestampTest.php
@@ -54,14 +54,16 @@ public function testHandlers() {
     db_insert('history')
       ->fields(array(
         'uid' => $account->id(),
-        'nid' => $nodes[0]->id(),
+        'entity_id' => $nodes[0]->id(),
+        'entity_type' => 'node',
         'timestamp' => REQUEST_TIME - 100,
       ))->execute();
 
     db_insert('history')
       ->fields(array(
         'uid' => $account->id(),
-        'nid' => $nodes[1]->id(),
+        'entity_id' => $nodes[1]->id(),
+        'entity_type' => 'node',
         'timestamp' => REQUEST_TIME + 100,
       ))->execute();
 
diff --git a/core/modules/node/node.install b/core/modules/node/node.install
index b240ecc..2a8b104 100644
--- a/core/modules/node/node.install
+++ b/core/modules/node/node.install
@@ -720,9 +720,39 @@ function node_update_8011() {
 }
 
 /**
- * Enable History module.
+ * Convert {history} table to new format and enable History module.
  */
 function node_update_8012() {
+  // @todo replace with proper migrate implementation.
+  // Drop all keys to properly rename constraints.
+  db_drop_primary_key('history');
+  db_drop_index('history', 'nid');
+  // Add new column and fill with 'node' entity type.
+  db_add_field('history', 'entity_type', array(
+    'description' => 'The type of the entity that was read.',
+    'type' => 'varchar',
+    'not null' => TRUE,
+    'initial' => 'node',
+    'length' => 255,
+  ));
+  // Rename the field.
+  db_change_field('history', 'nid', 'entity_id', array(
+    'description' => 'The ID of the entity that was read.',
+    'type' => 'int',
+    'not null' => TRUE,
+    'default' => 0,
+  ));
+  // Create new indexes.
+  db_add_primary_key('history', array(
+    'uid',
+    'entity_id',
+    array('entity_type', 32),
+  ));
+  db_add_index('history', 'history_entity', array(
+    'entity_id',
+    array('entity_type', 32),
+  ));
+
   // Enable the history module without re-installing the schema.
   \Drupal::moduleHandler()->install(array('history'));
 }
