diff --git a/includes/cache.inc b/includes/cache.inc
new file mode 100644
index 0000000..3672d72
--- /dev/null
+++ b/includes/cache.inc
@@ -0,0 +1,160 @@
+<?php
+
+/**
+ * @file
+ * cache.inc
+ */
+
+/**
+ * Initializes the JS cache handler.
+ */
+function js_cache_initialize() {
+  global $conf;
+
+  // Collect all the explicitly configured cache bins.
+  $default_key = JsCache::DEFAULT_BIN_KEY;
+  $cache_bin_keys = array_values(array_filter(array_keys($conf), function ($key) {
+    return strpos($key, 'cache_class_') === 0;
+  }));
+  $cache_bin_keys[] = $default_key;
+
+  // Save the current configuration and override it to make sure an instance of
+  // our custom wrapper is instantiated for each configured bin.
+  $cache_conf = array();
+  $default_class = isset($conf[$default_key]) ? $conf[$default_key] : 'DrupalDatabaseCache';
+  foreach ($cache_bin_keys as $bin_key) {
+    $cache_conf[$bin_key] = isset($conf[$bin_key]) ? $conf[$bin_key] : $default_class;
+    $conf[$bin_key] = 'JsCache';
+  }
+
+  // Finally ensure our custom wrappers now which actual cache backend they are
+  // supposed to use.
+  JsCache::setConf($cache_conf);
+}
+
+
+/**
+ * JS custom cache handler.
+ *
+ * This ensures that Drupal is fully bootstrapped if an item cannot be retrieved
+ * from cache. By loading all hook implementations we avoid the risk of having
+ * corrupt cache entries stored during a callback execution.
+ */
+class JsCache implements DrupalCacheInterface {
+
+  const DEFAULT_BIN_KEY = 'cache_default_class';
+
+  /**
+   * The cache bin configuration.
+   *
+   * @var string[]
+   */
+  protected static $conf;
+
+  /**
+   * Flag indicating whether a full bootstrap can be performed.
+   *
+   * @var bool
+   */
+  protected static $fullBootstrap = FALSE;
+
+  /**
+   * The actual cache backend.
+   *
+   * @var DrupalCacheInterface
+   */
+  protected $backend;
+
+  /**
+   * Sets the cache bin configuration.
+   *
+   * @param string[] $conf
+   *   An associative array of cache backend class names keyed by their cache
+   *   bin name.
+   */
+  public static function setConf(array $conf) {
+    static::$conf = $conf;
+  }
+
+  /**
+   * Sets the flag indicating whether a full bootstrap can be performed.
+   *
+   * @param bool $full_bootstrap
+   *   The full bootstrap flag.
+   */
+  public static function setFullBootstrap($full_bootstrap) {
+    static::$fullBootstrap = $full_bootstrap;
+  }
+
+  /**
+   * Constructs a JS cache handler.
+   *
+   * @param string $bin
+   *   The cache bin name.
+   */
+  public function __construct($bin) {
+    if (isset(static::$conf[static::DEFAULT_BIN_KEY])) {
+      $class = isset(static::$conf[$bin]) ? static::$conf[$bin] : static::$conf[static::DEFAULT_BIN_KEY];
+      $this->backend = new $class($bin);
+    }
+    else {
+      throw new LogicException('The JS cache handler was not properly configured');
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function get($cid) {
+    $cache = $this->backend->get($cid);
+    if (!$cache) {
+      $this->doFullBootstrap();
+    }
+    return $cache;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getMultiple(&$cids) {
+    $cache = $this->backend->getMultiple($cids);
+    if ($cids) {
+      $this->doFullBootstrap();
+    }
+    return $cache;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function set($cid, $data, $expire = CACHE_PERMANENT) {
+    $this->backend->set($cid, $data, $expire);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function clear($cid = NULL, $wildcard = FALSE) {
+    $this->backend->clear($cid, $wildcard);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isEmpty() {
+    return $this->backend->isEmpty();
+  }
+
+  /**
+   * Fully bootstraps Drupal.
+   */
+  protected function doFullBootstrap() {
+    if (static::$fullBootstrap) {
+      static::setFullBootstrap(FALSE);
+      if (drupal_get_bootstrap_phase() < DRUPAL_BOOTSTRAP_FULL) {
+        js_bootstrap(DRUPAL_BOOTSTRAP_FULL);
+      }
+    }
+  }
+
+}
diff --git a/includes/callback.inc b/includes/callback.inc
index 1efdf00..75f8d8c 100644
--- a/includes/callback.inc
+++ b/includes/callback.inc
@@ -181,6 +181,12 @@ function js_callback_bootstrap(array &$info) {
         module_invoke($module, 'init');
       }
     }
+
+    // At this point in the execution flow it is safe to perform a full
+    // bootstrap in case of cache misses.
+    if ($info['cache']) {
+      JsCache::setFullBootstrap(TRUE);
+    }
   }
 }
 
diff --git a/js.api.php b/js.api.php
index a4115bf..604370c 100644
--- a/js.api.php
+++ b/js.api.php
@@ -53,9 +53,12 @@
  *     instance, loading an entity when entity cache is cold may result in some
  *     data not being loaded and entity cache being corrupt; saving that entity
  *     in subsequent requests may even lead to data loss, if the cache entry was
- *     not refreshed meanwhile. A possible solution is raising the bootstrap
- *     level to full, although this defeats the purpose of using this module.
- *     An alternative solution is monitoring the code paths triggered by the
+ *     not refreshed meanwhile. By default JS will work around the corrupt cache
+ *     issue automatically by performing a full bootstrap whenever a cache miss
+ *     is detected, however the general issue with APIs performing storage
+ *     writes remains. A possible solution is raising the bootstrap level to
+ *     full, although this defeats the purpose of using this module. An
+ *     alternative solution is monitoring the code paths triggered by the
  *     callback via the "xhprof" integration and make sure all required
  *     dependencies are actually loaded.
  *   - includes: (optional) Load additional files from the /includes directory,
@@ -111,6 +114,8 @@
  *     browser. It is strongly recommended that this is not disabled, otherwise
  *     your site will be susceptible to XSS attacks and be considered
  *     "insecure".
+ *   - cache: (optional) Flag indicating whether a full bootstrap should be
+ *     performed when detecting a cache miss. Defaults to TRUE.
  */
 function hook_js_info() {
   // Simple callback definition:
diff --git a/js.module b/js.module
index 739489b..56bc5e7 100644
--- a/js.module
+++ b/js.module
@@ -488,8 +488,12 @@ function js_execute_request() {
     register_shutdown_function('_js_fatal_error_handler');
   }
 
+  // Initialize the JS cache handler.
+  $memcache = !empty($conf['cache_default_class']) && $conf['cache_default_class'] === 'MemCacheDrupal';
+  module_load_include('inc', 'js', 'includes/cache');
+  js_cache_initialize();
   // Memcache requires an additional bootstrap phase to access variables.
-  if (!empty($conf['cache_default_class']) && $conf['cache_default_class'] === 'MemCacheDrupal') {
+  if ($memcache) {
     js_bootstrap(DRUPAL_BOOTSTRAP_VARIABLES);
   }
 
@@ -800,6 +804,7 @@ function js_get_callback($module = NULL, $callback = NULL, $reset = FALSE) {
             'token' => TRUE,
             'xhprof' => FALSE,
             'xss' => TRUE,
+            'cache' => TRUE,
           );
         }
       }
