diff --git a/includes/common.inc b/includes/common.inc
index 20b0648c77f7b2600d0caaeff61ebdb35cbddcdc..d04f938eae535c6c0931066b68c97ae8b82a69b1 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -6575,6 +6575,19 @@ function entity_path($entity_type, $entity) {
     return $info['path callback']($entity);
   }
 }
+/**
+ * Invokes entity insert/update hooks.
+ *
+ * @param $op
+ *   One of 'insert' or 'update'.
+ * @param $entity_type
+ *   The entity type; e.g. 'node' or 'user'.
+ * @param $entity
+ *   The entity object being operated on.
+ */
+function entity_invoke($op, $entity_type, $entity) {
+  module_invoke_all('entity_' . $op, $entity, $entity_type);
+}
 
 /**
  * Performs one or more XML-RPC request(s).
diff --git a/includes/file.inc b/includes/file.inc
index ccac9cabcbeb6116b07020e09295f07a4cae3346..b03e9d4d9762f754adeaae1346a37f7dcf5fe7a9 100644
--- a/includes/file.inc
+++ b/includes/file.inc
@@ -512,11 +512,13 @@ function file_save(stdClass $file) {
     drupal_write_record('file', $file);
     // Inform modules about the newly added file.
     module_invoke_all('file_insert', $file);
+    entity_invoke('insert', 'file', $file);
   }
   else {
     drupal_write_record('file', $file, 'fid');
     // Inform modules that the file has been updated.
     module_invoke_all('file_update', $file);
+    entity_invoke('update', 'file', $file);
   }
 
   return $file;
diff --git a/modules/comment/comment.module b/modules/comment/comment.module
index 664d2aca8c43711e27ea314def47d7c00b09b1f8..97d862f73ab97bb4472610e3d84529e45ca2a21a 100644
--- a/modules/comment/comment.module
+++ b/modules/comment/comment.module
@@ -1370,6 +1370,7 @@ function comment_save($comment) {
       field_attach_update('comment', $comment);
       // Allow modules to respond to the updating of a comment.
       module_invoke_all('comment_update', $comment);
+      entity_invoke('update', 'comment', $comment);
       // Add an entry to the watchdog log.
       watchdog('content', 'Comment: updated %subject.', array('%subject' => $comment->subject), WATCHDOG_NOTICE, l(t('view'), 'comment/' . $comment->cid, array('fragment' => 'comment-' . $comment->cid)));
     }
@@ -1453,6 +1454,7 @@ function comment_save($comment) {
 
       // Tell the other modules a new comment has been submitted.
       module_invoke_all('comment_insert', $comment);
+      entity_invoke('insert', 'comment', $comment);
       // Add an entry to the watchdog log.
       watchdog('content', 'Comment: added %subject.', array('%subject' => $comment->subject), WATCHDOG_NOTICE, l(t('view'), 'comment/' . $comment->cid, array('fragment' => 'comment-' . $comment->cid)));
     }
diff --git a/modules/node/node.module b/modules/node/node.module
index c454bd7fcc0e3735a1ef8b71ef02297c96edf082..58a26474909d0a584a12afbfa11602a3ec46180f 100644
--- a/modules/node/node.module
+++ b/modules/node/node.module
@@ -1049,6 +1049,7 @@ function node_save($node) {
     $function('node', $node);
 
     module_invoke_all('node_' . $op, $node);
+    entity_invoke($op, 'node', $node);
 
     // Update the node access table for this node.
     node_access_acquire_grants($node);
diff --git a/modules/system/system.api.php b/modules/system/system.api.php
index 2563728f08be8c5b922e3549b9f90dd800f5f988..78cc24e2af577c95c57823cc0523112051c9e436 100644
--- a/modules/system/system.api.php
+++ b/modules/system/system.api.php
@@ -220,6 +220,32 @@ function hook_entity_load($entities, $type) {
   }
 }
 
+/**
+ * Act on entities when inserted.
+ *
+ * Generic insert hook called for all entity types via entity_invoke().
+ *
+ * @param $entity
+ *   The entity object.
+ * @param $type
+ *   The type of entity being inserted (i.e. node, user, comment).
+ */
+function hook_entity_insert($entity, $type) {
+}
+
+/**
+ * Act on entities when updated.
+ *
+ * Generic update hook called for all entity types via entity_invoke().
+ *
+ * @param $entity
+ *   The entity object.
+ * @param $type
+ *   The type of entity being updated (i.e. node, user, comment).
+ */
+function hook_entity_update($entity, $type) {
+}
+
 /**
  * Define administrative paths.
  *
diff --git a/modules/taxonomy/taxonomy.module b/modules/taxonomy/taxonomy.module
index 8e70c5a848e6d73be8d383861ba652620afa8d64..a5dda375b9c8e1e17c2ab8f83a1d2899df62b345 100644
--- a/modules/taxonomy/taxonomy.module
+++ b/modules/taxonomy/taxonomy.module
@@ -338,12 +338,14 @@ function taxonomy_vocabulary_save($vocabulary) {
   if (!empty($vocabulary->vid) && !empty($vocabulary->name)) {
     $status = drupal_write_record('taxonomy_vocabulary', $vocabulary, 'vid');
     module_invoke_all('taxonomy_vocabulary_update', $vocabulary);
+    entity_invoke('update', 'taxonomy_vocabulary', $vocabulary);
   }
   elseif (empty($vocabulary->vid)) {
     $status = drupal_write_record('taxonomy_vocabulary', $vocabulary);
     field_attach_create_bundle('taxonomy_term', $vocabulary->machine_name);
     taxonomy_vocabulary_create_field($vocabulary);
     module_invoke_all('taxonomy_vocabulary_insert', $vocabulary);
+    entity_invoke('insert', 'taxonomy_vocabulary', $vocabulary);
   }
 
   cache_clear_all();
@@ -470,11 +472,13 @@ function taxonomy_term_save($term) {
     $status = drupal_write_record('taxonomy_term_data', $term, 'tid');
     field_attach_update('taxonomy_term', $term);
     module_invoke_all('taxonomy_term_update', $term);
+    entity_invoke('update', 'taxonomy_term', $term);
   }
   else {
     $status = drupal_write_record('taxonomy_term_data', $term);
     field_attach_insert('taxonomy_term', $term);
     module_invoke_all('taxonomy_term_insert', $term);
+    entity_invoke('insert', 'taxonomy_term', $term);
   }
 
   db_delete('taxonomy_term_hierarchy')
diff --git a/modules/user/user.module b/modules/user/user.module
index ba935046cffb39f1b4e2be935685a4b81cdbefac..dca04f216b65c49ee7e9b945a768719f5584fc57 100644
--- a/modules/user/user.module
+++ b/modules/user/user.module
@@ -483,6 +483,7 @@ function user_save($account, $edit = array(), $category = 'account') {
       }
 
       user_module_invoke('update', $edit, $user, $category);
+      entity_invoke('update', 'user', $user);
     }
     else {
       // Allow 'uid' to be set by the caller. There is no danger of writing an
@@ -515,6 +516,7 @@ function user_save($account, $edit = array(), $category = 'account') {
       field_attach_insert('user', $object);
 
       user_module_invoke('insert', $edit, $user, $category);
+      entity_invoke('insert', 'user', $user);
 
       // Note, we wait with saving the data column to prevent module-handled
       // fields from being saved there.