diff --git a/blockcache_alter.install b/blockcache_alter.install
index ecb410e..33f97ef 100644
--- a/blockcache_alter.install
+++ b/blockcache_alter.install
@@ -46,4 +46,11 @@ function blockcache_alter_schema() {
   );
 
   return $schema;
-}
\ No newline at end of file
+}
+
+/**
+ * Implements hook_uninstall().
+ */
+function blockcache_alter_uninstall() {
+  variable_del('blockcache_alter_render_cache_fallback');
+}
diff --git a/blockcache_alter.module b/blockcache_alter.module
index 17c62f4..ec42eb6 100644
--- a/blockcache_alter.module
+++ b/blockcache_alter.module
@@ -52,6 +52,19 @@ function blockcache_alter_form_alter(&$form, $form_state, $form_id) {
     // Add own submit handler.
     $form['#submit'][] = 'blockcache_alter_save_settings';
   }
+
+  // Show a render cache fallback option when block caching is not possible.
+  if ($form_id == 'system_performance_settings') {
+    if ($form['caching']['block_cache']['#disabled']) {
+      $form['caching']['blockcache_alter_render_cache_fallback'] = array(
+        '#type' => 'checkbox',
+        '#title' => t('Cache blocks using render cache'),
+        '#default_value' => variable_get('blockcache_alter_render_cache_fallback', FALSE),
+        '#description' => t('Cache blocks even when content access restrictions are in place. If checked, you are responsible for ensuring content access restrictions are not violated by your block cache configurations.'),
+        '#weight' => 0,
+      );
+    }
+  }
 }
 
 /**
@@ -95,10 +108,7 @@ function blockcache_alter_save_settings($form, &$form_state) {
  */
 function blockcache_alter_block_info_alter(&$blocks, $theme, $code_blocks) {
 
-  $blockcache_alter = db_select('blockcache_alter', 'b')
-    ->fields('b', array('bid', 'module', 'cache'))
-    ->execute()
-    ->fetchAll();
+  $blockcache_alter = blockcache_alter_load_cache_configurations();
 
   foreach ($blockcache_alter as $bca) {
     if (array_key_exists($bca->module, $blocks)) {
@@ -110,3 +120,90 @@ function blockcache_alter_block_info_alter(&$blocks, $theme, $code_blocks) {
     }
   }
 }
+
+
+/**
+ * Implements hook_block_view_alter().
+ */
+function blockcache_alter_block_view_alter(&$data, $block) {
+  // Check if render cache fallback is enabled.
+  if (variable_get('blockcache_alter_render_cache_fallback', FALSE)) {
+    // This can only apply to blocks that are render arrays.
+    if (isset($data['content']) && is_array($data['content'])) {
+      $blockcache_alter = blockcache_alter_load_cache_configurations();
+      $fake_bid = $block->module . '-' . $block->delta . '-' . $block->theme;
+      if (isset($blockcache_alter[$fake_bid])) {
+        $block->cache = $blockcache_alter[$fake_bid]->cache;
+      }
+
+      // Set the block render array to cache based on our settings.
+      if ($cid = blockcache_alter_block_get_cache_id($block)) {
+        $data['content']['#cache'] = array(
+          'cid' => $cid,
+          'bin' => 'cache_block',
+        );
+      }
+    }
+  }
+}
+
+/**
+ * Loads block cache alter cache configurations.
+ *
+ * @return array|bool
+ *   An array of block cache configurations as read from the database, keyed by
+ *   block module and block delta.
+ */
+function blockcache_alter_load_cache_configurations() {
+  $blockcache_alter = &drupal_static(__FUNCTION__, FALSE);
+
+  if ($blockcache_alter === FALSE) {
+    $blockcache_alter = array();
+    $results = db_select('blockcache_alter', 'bca')
+      ->fields('bca');
+    $results->join('block', 'b', 'bca.bid = %alias.bid');
+    $results->fields('b', array('theme'));
+    $results = $results->execute()
+      ->fetchAll();
+
+    foreach ($results as $block) {
+      $fake_bid = $block->module . '-' . $block->delta . '-' . $block->theme;
+      $blockcache_alter[$fake_bid] = $block;
+    }
+  }
+
+  return $blockcache_alter;
+}
+
+/**
+ * Returns a block cache ID given a block object.
+ *
+ * @param $block
+ *   A block object, as expected by _block_get_cache_id().
+ *
+ * @return string
+ *   The correct cache ID for the given block.
+ */
+function blockcache_alter_block_get_cache_id($block) {
+  global $conf;
+
+  // The _block_get_cache_id() function assumes that block cache is enabled,
+  // so we have to work around that here.
+  $original_value = isset($conf['block_cache']) ? $conf['block_cache'] : FALSE;
+  $conf['block_cache'] = TRUE;
+
+  // Get the block cache ID as returned by core.
+  if ($cid = _block_get_cache_id($block)) {
+    $cid = 'bca:' . $cid;
+  }
+
+  // Reset the block cache setting.
+  $conf['block_cache'] = $original_value;
+
+  // If render cache fallback is on, append a bool for contextual link access.
+  if ($cid && variable_get('blockcache_alter_render_cache_fallback', FALSE)) {
+    $cid .= ':cl.' . (int) user_access('access contextual links');
+  }
+
+  return $cid ? $cid : NULL;
+}
