diff --git a/composer.json b/composer.json
index d4d94cf177f1080ec83b2c6d042446c498a4527f..9bab20ec4450df68d12c50b7377d3d4d47394e2d 100644
--- a/composer.json
+++ b/composer.json
@@ -45,7 +45,8 @@
         "piwik/device-detector": "~2.0",
         "piwik/decompress": "~0.1.1",
         "piwik/network": "~0.1.0",
-        "mnapoli/php-di": "5.0.x-dev"
+        "mnapoli/php-di": "5.0.x-dev",
+        "piwik/cache": "~0.2"
     },
     "require-dev": {
         "aws/aws-sdk-php": "2.7.1",
diff --git a/composer.lock b/composer.lock
index fdddc728f8c39eacad888d88c7da51c704215cbe..f4fbd7f67ed184e31afa95eae12de8569fb3c2dc 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
         "This file is @generated automatically"
     ],
-    "hash": "92499fc432a629fefcd5c1b912e44d9c",
+    "hash": "993a7439f15dd4d11b2684f6e35b944d",
     "packages": [
         {
             "name": "container-interop/container-interop",
@@ -432,6 +432,53 @@
             ],
             "time": "2013-11-11 18:29:08"
         },
+        {
+            "name": "piwik/cache",
+            "version": "0.2.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/piwik/component-cache.git",
+                "reference": "1cbe0012f703b5462e87520ebcf76bdca89026e8"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/piwik/component-cache/zipball/1cbe0012f703b5462e87520ebcf76bdca89026e8",
+                "reference": "1cbe0012f703b5462e87520ebcf76bdca89026e8",
+                "shasum": ""
+            },
+            "require": {
+                "doctrine/cache": "~1.3",
+                "php": ">=5.3.2"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~4.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Piwik\\Cache\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "LGPL-3.0"
+            ],
+            "authors": [
+                {
+                    "name": "The Piwik Team",
+                    "email": "hello@piwik.org",
+                    "homepage": "http://piwik.org/the-piwik-team/"
+                }
+            ],
+            "description": "PHP caching library based on Doctrine cache",
+            "keywords": [
+                "array",
+                "cache",
+                "file",
+                "redis"
+            ],
+            "time": "2014-12-16 01:47:11"
+        },
         {
             "name": "piwik/decompress",
             "version": "0.1.1",
diff --git a/config/global.ini.php b/config/global.ini.php
index 559ba5987ef725289a3a98f849299e80f02e176c..0692f8b9b8485b487b6917ec6a2088be567e08b4 100644
--- a/config/global.ini.php
+++ b/config/global.ini.php
@@ -78,6 +78,31 @@ log_only_when_debug_parameter = 0
 ; if configured to log in a file, log entries will be made to this file
 logger_file_path = tmp/logs/piwik.log
 
+[Cache]
+; available backends are 'file', 'array', 'null', 'redis', 'chained'
+; 'array' will cache data only during one request
+; 'null' will not cache anything at all
+; 'file' will cache on the filesystem
+; 'redis' will cache on a Redis server, use this if you are running Piwik with multiple servers. Further configuration in [RedisCache] is needed
+; 'chained' will chain multiple cache backends. Further configuration in [ChainedCache] is needed
+backend = chained
+
+[ChainedCache]
+; The chained cache will always try to read from the fastest backend first (the first listed one) to avoid requesting
+; the same cache entry from the slowest backend multiple times in one request.
+backends[] = array
+backends[] = file
+
+[RedisCache]
+; Redis server configuration.
+host = "127.0.0.1"
+port = 6379
+timeout = 0.0
+password = ""
+database = 14
+; In case you are using queued tracking: Make sure to configure a different database! Otherwise queued requests might
+; be flushed
+
 [Debug]
 ; if set to 1, the archiving process will always be triggered, even if the archive has already been computed
 ; this is useful when making changes to the archiving code so we can force the archiving process
diff --git a/config/global.php b/config/global.php
index 7dc6daa18fb84369d196c05d4497c50df4b2b234..29559349b763bbfedb845687917330d27aa8f5d4 100644
--- a/config/global.php
+++ b/config/global.php
@@ -1,6 +1,8 @@
 <?php
 
 use Interop\Container\ContainerInterface;
+use Piwik\Cache\Eager;
+use Piwik\SettingsServer;
 
 return array(
 
@@ -20,4 +22,56 @@ return array(
         return $root . '/tmp' . $instanceId;
     }),
 
+    'path.cache' => DI\factory(function (ContainerInterface $c) {
+        $root = $c->get('path.tmp');
+
+        return $root . '/cache/tracker/';
+    }),
+
+    'cache.backend' => DI\factory(function (ContainerInterface $c) {
+        if (defined('PIWIK_TEST_MODE') && PIWIK_TEST_MODE) { // todo replace this with isTest() instead of isCli()
+            $backend = 'file';
+        } elseif (\Piwik\Development::isEnabled()) {
+            $backend = 'null';
+        } else {
+            $backend = $c->get('old_config.Cache.backend');
+        }
+
+        return $backend;
+    }),
+    'Piwik\Cache\Lazy' => DI\object(),
+    'Piwik\Cache\Transient' => DI\object(),
+    'Piwik\Cache\Eager' => DI\factory(function (ContainerInterface $c) {
+
+        $backend = $c->get('Piwik\Cache\Backend');
+
+        if (defined('PIWIK_TEST_MODE') && PIWIK_TEST_MODE) {
+            $cacheId = 'eagercache-test-';
+        } else {
+            $cacheId = 'eagercache-' . str_replace(array('.', '-'), '', \Piwik\Version::VERSION) . '-';
+        }
+
+        if (SettingsServer::isTrackerApiRequest()) {
+            $eventToPersist = 'Tracker.end';
+            $cacheId .= 'tracker';
+        } else {
+            $eventToPersist = 'Request.dispatch.end';
+            $cacheId .= 'ui';
+        }
+
+        $cache = new Eager($backend, $cacheId);
+        \Piwik\Piwik::addAction($eventToPersist, function () use ($cache) {
+            $cache->persistCacheIfNeeded(43200);
+        });
+
+        return $cache;
+    }),
+    'Piwik\Cache\Backend' => DI\factory(function (ContainerInterface $c) {
+
+        $type    = $c->get('cache.backend');
+        $backend = \Piwik\Cache::buildBackend($type);
+
+        return $backend;
+    }),
+
 );
diff --git a/core/Cache.php b/core/Cache.php
new file mode 100644
index 0000000000000000000000000000000000000000..b90be8d27b9021acf4a57f5f98ed0db51ffa6c1e
--- /dev/null
+++ b/core/Cache.php
@@ -0,0 +1,117 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik;
+
+use Piwik\Cache\Backend;
+use Piwik\Container\StaticContainer;
+
+class Cache
+{
+
+    /**
+     * This can be considered as the default cache to use in case you don't know which one to pick. It does not support
+     * the caching of any objects though. Only boolean, numbers, strings and arrays are supported. Whenever you request
+     * an entry from the cache it will fetch the entry. Cache entries might be persisted but not necessarily. It
+     * depends on the configured backend.
+     *
+     * @return Cache\Lazy
+     */
+    public static function getLazyCache()
+    {
+        return StaticContainer::getContainer()->get('Piwik\Cache\Lazy');
+    }
+
+    /**
+     * This class is used to cache any data during one request. It won't be persisted between requests and it can
+     * cache all kind of data, even objects or resources. This cache is very fast.
+     *
+     * @return Cache\Transient
+     */
+    public static function getTransientCache()
+    {
+        return StaticContainer::getContainer()->get('Piwik\Cache\Transient');
+    }
+
+    /**
+     * This cache stores all its cache entries under one "cache" entry in a configurable backend.
+     *
+     * This comes handy for things that you need very often, nearly in every request. For example plugin metadata, the
+     * list of tracker plugins, the list of available languages, ...
+     * Instead of having to read eg. a hundred cache entries from files (or any other backend) it only loads one cache
+     * entry which contains the hundred keys. Should be used only for things that you need very often and only for
+     * cache entries that are not too large to keep loading and parsing the single cache entry fast.
+     * All cache entries it contains have the same life time. For fast performance it won't validate any cache ids.
+     * It is not possible to cache any objects using this cache.
+     *
+     * @return Cache\Eager
+     */
+    public static function getEagerCache()
+    {
+        return StaticContainer::getContainer()->get('Piwik\Cache\Eager');
+    }
+
+    public static function flushAll()
+    {
+        self::getLazyCache()->flushAll();
+        self::getTransientCache()->flushAll();
+        self::getEagerCache()->flushAll();
+    }
+
+    /**
+     * @param $type
+     * @return Cache\Backend
+     */
+    public static function buildBackend($type)
+    {
+        $factory = new Cache\Backend\Factory();
+        $options = self::getOptions($type);
+
+        $backend = $factory->buildBackend($type, $options);
+
+        return $backend;
+    }
+
+    private static function getOptions($type)
+    {
+        $options = self::getBackendOptions($type);
+
+        switch ($type) {
+            case 'file':
+
+                $options = array('directory' => StaticContainer::getContainer()->get('path.cache'));
+                break;
+
+            case 'chained':
+
+                foreach ($options['backends'] as $backend) {
+                    $options[$backend] = self::getOptions($backend);
+                }
+
+                break;
+
+            case 'redis':
+
+                if (!empty($options['timeout'])) {
+                    $options['timeout'] = (float)Common::forceDotAsSeparatorForDecimalPoint($options['timeout']);
+                }
+
+                break;
+        }
+
+        return $options;
+    }
+
+    private static function getBackendOptions($backend)
+    {
+        $key = ucfirst($backend) . 'Cache';
+        $options = Config::getInstance()->$key;
+
+        return $options;
+    }
+}
diff --git a/core/Cache/CacheDecorator.php b/core/Cache/CacheDecorator.php
deleted file mode 100644
index f35154ba727f977858bbb9d7247c3f6dc70ee189..0000000000000000000000000000000000000000
--- a/core/Cache/CacheDecorator.php
+++ /dev/null
@@ -1,54 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik\Cache;
-
-use Piwik\Tracker;
-use Piwik\Translate;
-
-/**
- * Caching class used for static caching.
- */
-class CacheDecorator implements CacheInterface
-{
-    /**
-     * @var StaticCache
-     */
-    protected $staticCache;
-
-    public function __construct(CacheInterface $cache)
-    {
-        $this->staticCache = $cache;
-    }
-
-    public function get()
-    {
-        return $this->staticCache->get();
-    }
-
-    public function has()
-    {
-        return $this->staticCache->has();
-    }
-
-    public function setCacheKey($cacheKey)
-    {
-        $this->staticCache->setCacheKey($cacheKey);
-    }
-
-    public function getCacheKey()
-    {
-        return $this->staticCache->getCacheKey();
-    }
-
-    public function set($content)
-    {
-        $this->staticCache->set($content);
-    }
-
-}
diff --git a/core/Cache/CacheInterface.php b/core/Cache/CacheInterface.php
deleted file mode 100644
index 65039e5436f2b7197e56f022910e843bdc2d9e25..0000000000000000000000000000000000000000
--- a/core/Cache/CacheInterface.php
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik\Cache;
-
-use Piwik\Tracker;
-use Piwik\Translate;
-
-/**
- * Caching class used for static caching.
- */
-interface CacheInterface
-{
-    public function get();
-
-    public function has();
-
-    public function setCacheKey($cacheKey);
-
-    public function getCacheKey();
-
-    public function set($content);
-
-}
diff --git a/core/Cache/LanguageAwareStaticCache.php b/core/Cache/LanguageAwareStaticCache.php
deleted file mode 100644
index 62b4773282b0a086b61696af063ea3d5bc73f006..0000000000000000000000000000000000000000
--- a/core/Cache/LanguageAwareStaticCache.php
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik\Cache;
-
-use Piwik\Translate;
-
-/**
- * Caching class used for static caching which is language aware. It'll cache the given content depending on the
- * current loaded language. This prevents you from having to invalidate the cache during tests in case the loaded
- * language changes etc.
- *
- * TODO convert this to a decorator... see {@link StaticCache}
- */
-class LanguageAwareStaticCache extends StaticCache
-{
-    protected function completeKey($cacheKey)
-    {
-        return $cacheKey . Translate::getLanguageLoaded();
-    }
-}
diff --git a/core/Cache/PersistentCache.php b/core/Cache/PersistentCache.php
deleted file mode 100644
index 5a98621a4c651110dde7c18dc95c73590bb305ae..0000000000000000000000000000000000000000
--- a/core/Cache/PersistentCache.php
+++ /dev/null
@@ -1,159 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik\Cache;
-
-use Piwik\CacheFile;
-use Piwik\Development;
-use Piwik\Piwik;
-use Piwik\SettingsServer;
-use Piwik\Version;
-
-/**
- * Caching class that persists all cached values between requests. Meaning whatever you cache will be stored on the
- * file system. It differs from other caches such as {@link CacheFile} that it does not create a file for each cacheKey.
- * Reading and writing new values does not cause multiple reads / writes on the file system and is therefore faster.
- * The cache won't be invalidated after any time by default but when the tracker cache is cleared. This is usually the
- * case when a new plugin is installed or an existing plugin or the core is updated.
- * You should be careful when caching any data since we won't modify the cache key. So if your data depends on which
- * plugins are activated or should not be available to each user than make sure to include unique names in the cache
- * key such as the names of all loaded plugin names.
- * If development mode is enabled in the config this cache acts as a {@link StaticCache}. Meaning it won't persist any
- * data between requests.
- */
-class PersistentCache
-{
-    /**
-     * @var CacheFile
-     */
-    private static $storage = null;
-    private static $content = null;
-    private static $isDirty = false;
-
-    private $cacheKey;
-
-    /**
-     * Initializes the cache.
-     * @param string $cacheKey
-     */
-    public function __construct($cacheKey)
-    {
-        $this->cacheKey = $cacheKey;
-
-        if (is_null(self::$content)) {
-            self::$content = array();
-            self::populateCache();
-        }
-    }
-
-    /**
-     * Overwrites a previously set cache key. Useful if you want to reuse the same instance for different cache keys
-     * for performance reasons.
-     * @param string $cacheKey
-     */
-    public function setCacheKey($cacheKey)
-    {
-        $this->cacheKey = $cacheKey;
-    }
-
-    /**
-     * Get the content related to the current cache key. Make sure to call the method {@link has()} to verify whether
-     * there is actually any content set under this cache key.
-     * @return mixed
-     */
-    public function get()
-    {
-        return self::$content[$this->cacheKey];
-    }
-
-    /**
-     * Check whether any content was actually stored for the current cache key.
-     * @return bool
-     */
-    public function has()
-    {
-        return array_key_exists($this->cacheKey, self::$content);
-    }
-
-    /**
-     * Set (overwrite) any content related to the current set cache key.
-     * @param $content
-     */
-    public function set($content)
-    {
-        self::$content[$this->cacheKey] = $content;
-        self::$isDirty = true;
-    }
-
-    private static function populateCache()
-    {
-        if (Development::isEnabled()) {
-            return;
-        }
-
-        if (SettingsServer::isTrackerApiRequest()) {
-            $eventToPersist = 'Tracker.end';
-            $mode           = '-tracker';
-        } else {
-            $eventToPersist = 'Request.dispatch.end';
-            $mode           = '-ui';
-        }
-
-        $cache = self::getStorage()->get(self::getCacheFilename() . $mode);
-
-        if (is_array($cache)) {
-            self::$content = $cache;
-        }
-
-        Piwik::addAction($eventToPersist, array(__CLASS__, 'persistCache'));
-    }
-
-    private static function getCacheFilename()
-    {
-        return 'StaticCache-' . str_replace(array('.', '-'), '', Version::VERSION);
-    }
-
-    /**
-     * @ignore
-     */
-    public static function persistCache()
-    {
-        if (self::$isDirty) {
-            if (SettingsServer::isTrackerApiRequest()) {
-                $mode = '-tracker';
-            } else {
-                $mode = '-ui';
-            }
-
-            self::getStorage()->set(self::getCacheFilename() . $mode, self::$content);
-        }
-    }
-
-    /**
-     * @ignore
-     */
-    public static function _reset()
-    {
-        self::$content = array();
-    }
-
-    /**
-     * @return CacheFile
-     */
-    private static function getStorage()
-    {
-        if (is_null(self::$storage)) {
-            self::$storage = new CacheFile('tracker', 43200);
-            self::$storage->addOnDeleteCallback(function () {
-                PersistentCache::_reset();
-            });
-        }
-
-        return self::$storage;
-    }
-}
diff --git a/core/Cache/PluginAwareStaticCache.php b/core/Cache/PluginAwareStaticCache.php
deleted file mode 100644
index 1bc3a25bd5159ac042f0dde135cffff0928de571..0000000000000000000000000000000000000000
--- a/core/Cache/PluginAwareStaticCache.php
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik\Cache;
-
-use Piwik\Plugin\Manager as PluginManager;
-use Piwik\Translate;
-
-/**
- * Caching class used for static caching which is plugin aware. It'll cache the given content depending on the plugins
- * that are installed. This prevents you from having to invalidate the cache during tests in case the loaded plugins
- * changes etc. The key is language aware as well.
- *
- * TODO convert this to a decorator... see {@link StaticCache}
- */
-class PluginAwareStaticCache extends StaticCache
-{
-    protected function completeKey($cacheKey)
-    {
-        $pluginManager = PluginManager::getInstance();
-        $pluginNames   = $pluginManager->getLoadedPluginsName();
-        $cacheKey      = $cacheKey . md5(implode('', $pluginNames)) . Translate::getLanguageLoaded();
-
-        return $cacheKey;
-    }
-}
diff --git a/core/Cache/StaticCache.php b/core/Cache/StaticCache.php
deleted file mode 100644
index 0c102e18d39143312dd3c56150d5af8827b47f7e..0000000000000000000000000000000000000000
--- a/core/Cache/StaticCache.php
+++ /dev/null
@@ -1,94 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik\Cache;
-
-/**
- * Caching class used for static caching. Any content that is set here won't be cached between requests. If you do want
- * to persist any content between requests have a look at {@link PersistentCache}
- *
- * TODO the default static cache should actually not be language aware. Especially since we would end up in classes like
- * LanguageAwareStaticCache, PluginAwareStaticCache, PluginAwareLanguageAwareStaticCache, PluginAwareXYZStaticCache,...
- * once we have dependency injection we should "build" all the caches we need removing duplicated code and extend the
- * static cache by using decorators which "enrich" the cache key depending on their awareness.
- */
-class StaticCache
-{
-    protected static $staticCache = array();
-
-    private $cacheKey;
-
-    /**
-     * Initializes the cache.
-     * @param string $cacheKey
-     */
-    public function __construct($cacheKey)
-    {
-        $this->setCacheKey($cacheKey);
-    }
-
-    /**
-     * Overwrites a previously set cache key. Useful if you want to reuse the same instance for different cache keys
-     * for performance reasons.
-     * @param string $cacheKey
-     */
-    public function setCacheKey($cacheKey)
-    {
-        $this->cacheKey = $this->completeKey($cacheKey);
-    }
-
-    /**
-     * Get the content related to the current cache key. Make sure to call the method {@link has()} to verify whether
-     * there is actually any content set under this cache key.
-     * @return mixed
-     */
-    public function get()
-    {
-        return self::$staticCache[$this->cacheKey];
-    }
-
-    /**
-     * Check whether any content was actually stored for the current cache key.
-     * @return bool
-     */
-    public function has()
-    {
-        return array_key_exists($this->cacheKey, self::$staticCache);
-    }
-
-    /**
-     * Reset the stored content of the current cache key.
-     */
-    public function clear()
-    {
-        unset(self::$staticCache[$this->cacheKey]);
-    }
-
-    /**
-     * Reset the stored content of the current cache key.
-     * @ignore
-     */
-    public static function clearAll()
-    {
-        self::$staticCache = array();
-    }
-
-    /**
-     * Set (overwrite) any content related to the current set cache key.
-     * @param $content
-     */
-    public function set($content)
-    {
-        self::$staticCache[$this->cacheKey] = $content;
-    }
-
-    protected function completeKey($cacheKey)
-    {
-        return $cacheKey;
-    }
-}
\ No newline at end of file
diff --git a/core/CacheFile.php b/core/CacheFile.php
deleted file mode 100644
index b8ec14c57560d78122a76889a422da4717cd02d5..0000000000000000000000000000000000000000
--- a/core/CacheFile.php
+++ /dev/null
@@ -1,237 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-namespace Piwik;
-
-use Exception;
-use Piwik\Container\StaticContainer;
-
-/**
- * This class is used to cache data on the filesystem.
- *
- * It is for example used by the Tracker process to cache various settings and websites attributes in tmp/cache/tracker/*
- *
- */
-class CacheFile
-{
-    // for testing purposes since tests run on both CLI/FPM (changes in CLI can't invalidate
-    // opcache in FPM, so we have to invalidate before reading)
-    public static $invalidateOpCacheBeforeRead = false;
-
-    /**
-     * @var string
-     */
-    private $cachePath;
-
-    /**
-     * Minimum enforced TTL in seconds
-     */
-    const MINIMUM_TTL = 60;
-
-    /**
-     * @var \Callable[]
-     */
-    private static $onDeleteCallback = array();
-
-    /**
-     * @param string $directory directory to use
-     * @param int $timeToLiveInSeconds TTL
-     */
-    public function __construct($directory, $timeToLiveInSeconds = 300)
-    {
-        $this->cachePath = StaticContainer::getContainer()->get('path.tmp') . '/cache/' . $directory . '/';
-
-        if ($timeToLiveInSeconds < self::MINIMUM_TTL) {
-            $timeToLiveInSeconds = self::MINIMUM_TTL;
-        }
-        $this->ttl = $timeToLiveInSeconds;
-    }
-
-    /**
-     * Function to fetch a cache entry
-     *
-     * @param string $id The cache entry ID
-     * @return array|bool  False on error, or array the cache content
-     */
-    public function get($id)
-    {
-        if (empty($id)) {
-            return false;
-        }
-
-        $id = $this->cleanupId($id);
-
-        $cache_complete = false;
-        $content        = '';
-        $expires_on     = false;
-
-        // We are assuming that most of the time cache will exists
-        $cacheFilePath = $this->cachePath . $id . '.php';
-        if (self::$invalidateOpCacheBeforeRead) {
-            $this->opCacheInvalidate($cacheFilePath);
-        }
-
-        $ok = @include($cacheFilePath);
-
-        if ($ok && $cache_complete == true) {
-
-            if (empty($expires_on)
-                || $expires_on < time()
-            ) {
-                return false;
-            }
-
-            return $content;
-        }
-
-        return false;
-    }
-
-    private function getExpiresTime()
-    {
-        return time() + $this->ttl;
-    }
-
-    protected function cleanupId($id)
-    {
-        if (!Filesystem::isValidFilename($id)) {
-            throw new Exception("Invalid cache ID request $id");
-        }
-
-        return $id;
-    }
-
-    /**
-     * A function to store content a cache entry.
-     *
-     * @param string $id The cache entry ID
-     * @param array $content The cache content
-     * @throws \Exception
-     * @return bool  True if the entry was succesfully stored
-     */
-    public function set($id, $content)
-    {
-        if (empty($id)) {
-            return false;
-        }
-
-        if (!is_dir($this->cachePath)) {
-            Filesystem::mkdir($this->cachePath);
-        }
-
-        if (!is_writable($this->cachePath)) {
-            return false;
-        }
-
-        $id = $this->cleanupId($id);
-        $id = $this->cachePath . $id . '.php';
-
-        if (is_object($content)) {
-            throw new \Exception('You cannot use the CacheFile to cache an object, only arrays, strings and numbers.');
-        }
-
-        $cache_literal = $this->buildCacheLiteral($content);
-
-        // Write cache to a temp file, then rename it, overwriting the old cache
-        // On *nix systems this should guarantee atomicity
-        $tmp_filename = tempnam($this->cachePath, 'tmp_');
-        @chmod($tmp_filename, 0640);
-        if ($fp = @fopen($tmp_filename, 'wb')) {
-            @fwrite($fp, $cache_literal, strlen($cache_literal));
-            @fclose($fp);
-
-            if (!@rename($tmp_filename, $id)) {
-                // On some systems rename() doesn't overwrite destination
-                @unlink($id);
-                if (!@rename($tmp_filename, $id)) {
-                    // Make sure that no temporary file is left over
-                    // if the destination is not writable
-                    @unlink($tmp_filename);
-                }
-            }
-
-            $this->opCacheInvalidate($id);
-
-            return true;
-        }
-
-        return false;
-    }
-
-    /**
-     * A function to delete a single cache entry
-     *
-     * @param string $id The cache entry ID
-     * @return bool  True if the entry was succesfully deleted
-     */
-    public function delete($id)
-    {
-        if (empty($id)) {
-            return false;
-        }
-
-        $id = $this->cleanupId($id);
-
-        $filename = $this->cachePath . $id . '.php';
-
-        if (file_exists($filename)) {
-            $this->opCacheInvalidate($filename);
-            @unlink($filename);
-            return true;
-        }
-
-        return false;
-    }
-
-    public function addOnDeleteCallback($onDeleteCallback)
-    {
-        self::$onDeleteCallback[] = $onDeleteCallback;
-    }
-
-    /**
-     * A function to delete all cache entries in the directory
-     */
-    public function deleteAll()
-    {
-        $self = $this;
-        $beforeUnlink = function ($path) use ($self) {
-            $self->opCacheInvalidate($path);
-        };
-
-        Filesystem::unlinkRecursive($this->cachePath, $deleteRootToo = false, $beforeUnlink);
-
-        if (!empty(self::$onDeleteCallback)) {
-            foreach (self::$onDeleteCallback as $callback) {
-                $callback();
-            }
-        }
-    }
-
-    public function opCacheInvalidate($filepath)
-    {
-        if (is_file($filepath)) {
-            if (function_exists('opcache_invalidate')) {
-                @opcache_invalidate($filepath, $force = true);
-            }
-            if (function_exists('apc_delete_file')) {
-                @apc_delete_file($filepath);
-            }
-        }
-    }
-
-    private function buildCacheLiteral($content)
-    {
-        $cache_literal  = "<" . "?php\n";
-        $cache_literal .= "$" . "content   = " . var_export($content, true) . ";\n";
-        $cache_literal .= "$" . "expires_on   = " . $this->getExpiresTime() . ";\n";
-        $cache_literal .= "$" . "cache_complete   = true;\n";
-        $cache_literal .= "?" . ">";
-
-        return $cache_literal;
-    }
-}
diff --git a/core/CacheId.php b/core/CacheId.php
new file mode 100644
index 0000000000000000000000000000000000000000..e445424009c9faed96ce54a0167788e62de8a034
--- /dev/null
+++ b/core/CacheId.php
@@ -0,0 +1,30 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik;
+
+use Piwik\Translate;
+use Piwik\Plugin\Manager;
+
+class CacheId
+{
+    public static function languageAware($cacheId)
+    {
+        return $cacheId . '-' . Translate::getLanguageLoaded();
+    }
+
+    public static function pluginAware($cacheId)
+    {
+        $pluginManager = Manager::getInstance();
+        $pluginNames   = $pluginManager->getLoadedPluginsName();
+        $cacheId       = $cacheId . '-' . md5(implode('', $pluginNames));
+        $cacheId       = self::languageAware($cacheId);
+
+        return $cacheId;
+    }
+}
diff --git a/core/Columns/Updater.php b/core/Columns/Updater.php
index 6c42ba0dff63f801aff531a9a584aa4696a5c131..4272f46f566c88ac161106515371068bac6153fb 100644
--- a/core/Columns/Updater.php
+++ b/core/Columns/Updater.php
@@ -14,14 +14,16 @@ use Piwik\Plugin\Dimension\VisitDimension;
 use Piwik\Plugin\Dimension\ConversionDimension;
 use Piwik\Db;
 use Piwik\Updater as PiwikUpdater;
-use Piwik\Cache\PersistentCache;
 use Piwik\Filesystem;
+use Piwik\Cache as PiwikCache;
 
 /**
  * Class that handles dimension updates
  */
 class Updater extends \Piwik\Updates
 {
+    private static $cacheId = 'AllDimensionModifyTime';
+
     /**
      * @var Updater
      */
@@ -315,15 +317,22 @@ class Updater extends \Piwik\Updates
     private static function cacheCurrentDimensionFileChanges()
     {
         $changes = self::getCurrentDimensionFileChanges();
-        $persistentCache = new PersistentCache('AllDimensionModifyTime');
-        $persistentCache->set($changes);
+
+        $cache = self::buildCache();
+        $cache->save(self::$cacheId, $changes);
+    }
+
+    private static function buildCache()
+    {
+        return PiwikCache::getEagerCache();
     }
 
     private static function getCachedDimensionFileChanges()
     {
-        $persistentCache = new PersistentCache('AllDimensionModifyTime');
-        if ($persistentCache->has()) {
-            return $persistentCache->get();
+        $cache = self::buildCache();
+
+        if ($cache->contains(self::$cacheId)) {
+            return $cache->fetch(self::$cacheId);
         }
 
         return array();
diff --git a/core/Container/StaticContainer.php b/core/Container/StaticContainer.php
index b46f01e1ca77a1f5f8d1ce2dacb960b048a047e4..4e09d2bdb72d590fc400ac51475c7484d661f9c5 100644
--- a/core/Container/StaticContainer.php
+++ b/core/Container/StaticContainer.php
@@ -39,6 +39,11 @@ class StaticContainer
         return self::$container;
     }
 
+    public static function clearContainer()
+    {
+        self::$container = null;
+    }
+
     /**
      * @link http://php-di.org/doc/container-configuration.html
      */
diff --git a/core/DeviceDetectorCache.php b/core/DeviceDetectorCache.php
index ba65b82c9f639be3f99b44d4c31d61596d925182..c337b1b0a4e13371d56d2508b68108846ccebb3b 100644
--- a/core/DeviceDetectorCache.php
+++ b/core/DeviceDetectorCache.php
@@ -8,6 +8,7 @@
  */
 namespace Piwik;
 
+use Piwik\Cache as PiwikCache;
 use Exception;
 
 /**
@@ -17,10 +18,19 @@ use Exception;
  *
  * Static caching speeds up multiple detections in one request, which is the case when sending bulk requests
  */
-class DeviceDetectorCache extends CacheFile implements \DeviceDetector\Cache\CacheInterface
+class DeviceDetectorCache implements \DeviceDetector\Cache\CacheInterface
 {
     protected static $staticCache = array();
 
+    private $cache;
+    private $ttl;
+
+    public function __construct($ttl = 300)
+    {
+        $this->ttl   = (int) $ttl;
+        $this->cache = PiwikCache::getLazyCache();
+    }
+
     /**
      * Function to fetch a cache entry
      *
@@ -33,13 +43,11 @@ class DeviceDetectorCache extends CacheFile implements \DeviceDetector\Cache\Cac
             return false;
         }
 
-        $id = $this->cleanupId($id);
-
         if (array_key_exists($id, self::$staticCache)) {
             return self::$staticCache[$id];
         }
 
-        return parent::get($id);
+        return $this->cache->fetch($id);
     }
 
     /**
@@ -56,10 +64,9 @@ class DeviceDetectorCache extends CacheFile implements \DeviceDetector\Cache\Cac
             return false;
         }
 
-        $id = $this->cleanupId($id);
-
         self::$staticCache[$id] = $content;
 
-        return parent::set($id, $content);
+        return $this->cache->save($id, $content, $this->ttl);
     }
+
 }
diff --git a/core/DeviceDetectorFactory.php b/core/DeviceDetectorFactory.php
index c61da87a1407010e6739cca0e122516f81fdd752..c7962a96f056560e400301807745cb8e4505cc8b 100644
--- a/core/DeviceDetectorFactory.php
+++ b/core/DeviceDetectorFactory.php
@@ -28,7 +28,7 @@ class DeviceDetectorFactory
 
         $deviceDetector = new DeviceDetector($userAgent);
         $deviceDetector->discardBotInformation();
-        $deviceDetector->setCache(new DeviceDetectorCache('tracker', 86400));
+        $deviceDetector->setCache(new DeviceDetectorCache(86400));
         $deviceDetector->parse();
 
         self::$deviceDetectorInstances[$userAgent] = $deviceDetector;
diff --git a/core/Filesystem.php b/core/Filesystem.php
index 125c47bfda7192799a2c6dcdbf03713604a32c94..05e659a4bb7499da98a2c9c05d2e747085123c01 100644
--- a/core/Filesystem.php
+++ b/core/Filesystem.php
@@ -11,6 +11,7 @@ namespace Piwik;
 use Exception;
 use Piwik\Container\StaticContainer;
 use Piwik\Tracker\Cache;
+use Piwik\Cache as PiwikCache;
 
 /**
  * Contains helper functions that deal with the filesystem.
@@ -27,6 +28,7 @@ class Filesystem
         AssetManager::getInstance()->removeMergedAssets($pluginName);
         View::clearCompiledTemplates();
         Cache::deleteTrackerCache();
+        PiwikCache::flushAll();
         self::clearPhpCaches();
     }
 
diff --git a/core/Metrics.php b/core/Metrics.php
index 009fa361514ab05d44a590fc1260de79b0dc52f1..e76e8dd5e92cb245b25911faec5c7672b9f9b42c 100644
--- a/core/Metrics.php
+++ b/core/Metrics.php
@@ -8,8 +8,7 @@
  */
 namespace Piwik;
 
-use Piwik\Cache\LanguageAwareStaticCache;
-use Piwik\Cache\PluginAwareStaticCache;
+use Piwik\Cache as PiwikCache;
 use Piwik\Metrics\Formatter;
 
 require_once PIWIK_INCLUDE_PATH . "/core/Piwik.php";
@@ -250,10 +249,11 @@ class Metrics
 
     public static function getDefaultMetricTranslations()
     {
-        $cache = new PluginAwareStaticCache('DefaultMetricTranslations');
+        $cacheId = CacheId::pluginAware('DefaultMetricTranslations');
+        $cache   = PiwikCache::getTransientCache();
 
-        if ($cache->has()) {
-            return $cache->get();
+        if ($cache->contains($cacheId)) {
+            return $cache->fetch($cacheId);
         }
 
         $translations = array(
@@ -302,17 +302,18 @@ class Metrics
 
         $translations = array_map(array('\\Piwik\\Piwik','translate'), $translations);
 
-        $cache->set($translations);
+        $cache->save($cacheId, $translations);
 
         return $translations;
     }
 
     public static function getDefaultMetrics()
     {
-        $cache = new LanguageAwareStaticCache('DefaultMetrics');
+        $cacheId = CacheId::languageAware('DefaultMetrics');
+        $cache   = PiwikCache::getTransientCache();
 
-        if ($cache->has()) {
-            return $cache->get();
+        if ($cache->contains($cacheId)) {
+            return $cache->fetch($cacheId);
         }
 
         $translations = array(
@@ -323,17 +324,18 @@ class Metrics
         );
         $translations = array_map(array('\\Piwik\\Piwik','translate'), $translations);
 
-        $cache->set($translations);
+        $cache->save($cacheId, $translations);
 
         return $translations;
     }
 
     public static function getDefaultProcessedMetrics()
     {
-        $cache = new LanguageAwareStaticCache('DefaultProcessedMetrics');
+        $cacheId = CacheId::languageAware('DefaultProcessedMetrics');
+        $cache   = PiwikCache::getTransientCache();
 
-        if ($cache->has()) {
-            return $cache->get();
+        if ($cache->contains($cacheId)) {
+            return $cache->fetch($cacheId);
         }
 
         $translations = array(
@@ -345,7 +347,7 @@ class Metrics
         );
         $translations = array_map(array('\\Piwik\\Piwik','translate'), $translations);
 
-        $cache->set($translations);
+        $cache->save($cacheId, $translations);
 
         return $translations;
     }
@@ -383,10 +385,11 @@ class Metrics
 
     public static function getDefaultMetricsDocumentation()
     {
-        $cache = new PluginAwareStaticCache('DefaultMetricsDocumentation');
+        $cacheId = CacheId::pluginAware('DefaultMetricsDocumentation');
+        $cache   = PiwikCache::getTransientCache();
 
-        if ($cache->has()) {
-            return $cache->get();
+        if ($cache->contains($cacheId)) {
+            return $cache->fetch($cacheId);
         }
 
         $translations = array(
@@ -412,7 +415,7 @@ class Metrics
 
         $translations = array_map(array('\\Piwik\\Piwik','translate'), $translations);
 
-        $cache->set($translations);
+        $cache->save($cacheId, $translations);
 
         return $translations;
     }
diff --git a/core/Plugin.php b/core/Plugin.php
index f30c3ed23a2283cb096a4c84d43d9b4ac85f3169..fdef9f5dc8bbf8a1546fe0a5ccfd66fbb50a83a9 100644
--- a/core/Plugin.php
+++ b/core/Plugin.php
@@ -8,7 +8,6 @@
  */
 namespace Piwik;
 
-use Piwik\Cache\PersistentCache;
 use Piwik\Plugin\Dependency;
 use Piwik\Plugin\MetadataLoader;
 
@@ -108,10 +107,10 @@ class Plugin
 
     /**
      * As the cache is used quite often we avoid having to create instances all the time. We reuse it which is not
-     * perfect but efficient. If the cache is used we need to make sure to call setCacheKey() before usage as there
+     * perfect but efficient. If the cache is used we need to make sure to call setId() before usage as there
      * is maybe a different key set since last usage.
      *
-     * @var PersistentCache
+     * @var \Piwik\Cache\Eager
      */
     private $cache;
 
@@ -131,12 +130,12 @@ class Plugin
         }
         $this->pluginName = $pluginName;
 
-        $cache = new PersistentCache('Plugin' . $pluginName . 'Metadata');
+        $cacheId = 'Plugin' . $pluginName . 'Metadata';
+        $cache = Cache::getEagerCache();
 
-        if ($cache->has()) {
-            $this->pluginInformation = $cache->get();
+        if ($cache->contains($cacheId)) {
+            $this->pluginInformation = $cache->fetch($cacheId);
         } else {
-
             $metadataLoader = new MetadataLoader($pluginName);
             $this->pluginInformation = $metadataLoader->load();
 
@@ -144,14 +143,14 @@ class Plugin
                 throw new \Exception('Plugin ' . $pluginName . ' has defined the method getInformation() and as well as having a plugin.json file. Please delete the getInformation() method from the plugin class. Alternatively, you may delete the plugin directory from plugins/' . $pluginName);
             }
 
-            $cache->set($this->pluginInformation);
+            $cache->save($cacheId, $this->pluginInformation);
         }
     }
 
     private function createCacheIfNeeded()
     {
         if (is_null($this->cache)) {
-            $this->cache = new PersistentCache('Plugin' . $this->pluginName);
+            $this->cache = Cache::getEagerCache();
         }
     }
 
@@ -321,12 +320,12 @@ class Plugin
     {
         $this->createCacheIfNeeded();
 
-        $this->cache->setCacheKey('Plugin' . $this->pluginName . $componentName . $expectedSubclass);
+        $cacheId = 'Plugin' . $this->pluginName . $componentName . $expectedSubclass;
 
         $componentFile = sprintf('%s/plugins/%s/%s.php', PIWIK_INCLUDE_PATH, $this->pluginName, $componentName);
 
-        if ($this->cache->has()) {
-            $klassName = $this->cache->get();
+        if ($this->cache->contains($cacheId)) {
+            $klassName = $this->cache->fetch($cacheId);
 
             if (empty($klassName)) {
                 return; // might by "false" in case has no menu, widget, ...
@@ -337,7 +336,7 @@ class Plugin
             }
 
         } else {
-            $this->cache->set(false); // prevent from trying to load over and over again for instance if there is no Menu for a plugin
+            $this->cache->save($cacheId, false); // prevent from trying to load over and over again for instance if there is no Menu for a plugin
 
             if (!file_exists($componentFile)) {
                 return;
@@ -357,7 +356,7 @@ class Plugin
                 return;
             }
 
-            $this->cache->set($klassName);
+            $this->cache->save($cacheId, $klassName);
         }
 
         return new $klassName;
@@ -367,10 +366,10 @@ class Plugin
     {
         $this->createCacheIfNeeded();
 
-        $this->cache->setCacheKey('Plugin' . $this->pluginName . $directoryWithinPlugin . $expectedSubclass);
+        $cacheId = 'Plugin' . $this->pluginName . $directoryWithinPlugin . $expectedSubclass;
 
-        if ($this->cache->has()) {
-            $components = $this->cache->get();
+        if ($this->cache->contains($cacheId)) {
+            $components = $this->cache->fetch($cacheId);
 
             if ($this->includeComponents($components)) {
                 return $components;
@@ -381,7 +380,7 @@ class Plugin
 
         $components = $this->doFindMultipleComponents($directoryWithinPlugin, $expectedSubclass);
 
-        $this->cache->set($components);
+        $this->cache->save($cacheId, $components);
 
         return $components;
     }
diff --git a/core/Plugin/Dimension/ActionDimension.php b/core/Plugin/Dimension/ActionDimension.php
index bc09b01fc398ace7a1e55e20ae1077d41865f180..f0daaf547c84577905bb4b2c9e000ef6224f4292 100644
--- a/core/Plugin/Dimension/ActionDimension.php
+++ b/core/Plugin/Dimension/ActionDimension.php
@@ -8,7 +8,8 @@
  */
 namespace Piwik\Plugin\Dimension;
 
-use Piwik\Cache\PluginAwareStaticCache;
+use Piwik\CacheId;
+use Piwik\Cache as PiwikCache;
 use Piwik\Columns\Dimension;
 use Piwik\Plugin\Manager as PluginManager;
 use Piwik\Plugin\Segment;
@@ -212,9 +213,10 @@ abstract class ActionDimension extends Dimension
      */
     public static function getAllDimensions()
     {
-        $cache = new PluginAwareStaticCache('ActionDimensions');
+        $cacheId = CacheId::pluginAware('ActionDimensions');
+        $cache   = PiwikCache::getTransientCache();
 
-        if (!$cache->has()) {
+        if (!$cache->contains($cacheId)) {
 
             $plugins   = PluginManager::getInstance()->getPluginsLoadedAndActivated();
             $instances = array();
@@ -225,10 +227,10 @@ abstract class ActionDimension extends Dimension
                 }
             }
 
-            $cache->set($instances);
+            $cache->save($cacheId, $instances);
         }
 
-        return $cache->get();
+        return $cache->fetch($cacheId);
     }
 
     /**
diff --git a/core/Plugin/Dimension/ConversionDimension.php b/core/Plugin/Dimension/ConversionDimension.php
index 7cf2a813c0ed2114e3933b7e3c4f9846b2b74ad2..34a800611193ff5689e26a190ff4d6f1e8929cbd 100644
--- a/core/Plugin/Dimension/ConversionDimension.php
+++ b/core/Plugin/Dimension/ConversionDimension.php
@@ -8,7 +8,8 @@
  */
 namespace Piwik\Plugin\Dimension;
 
-use Piwik\Cache\PluginAwareStaticCache;
+use Piwik\CacheId;
+use Piwik\Cache as PiwikCache;
 use Piwik\Columns\Dimension;
 use Piwik\Plugin\Manager as PluginManager;
 use Piwik\Common;
@@ -155,9 +156,10 @@ abstract class ConversionDimension extends Dimension
      */
     public static function getAllDimensions()
     {
-        $cache = new PluginAwareStaticCache('ConversionDimensions');
+        $cacheId = CacheId::pluginAware('ConversionDimensions');
+        $cache   = PiwikCache::getTransientCache();
 
-        if (!$cache->has()) {
+        if (!$cache->contains($cacheId)) {
 
             $plugins   = PluginManager::getInstance()->getPluginsLoadedAndActivated();
             $instances = array();
@@ -168,10 +170,10 @@ abstract class ConversionDimension extends Dimension
                 }
             }
 
-            $cache->set($instances);
+            $cache->save($cacheId, $instances);
         }
 
-        return $cache->get();
+        return $cache->fetch($cacheId);
     }
 
     /**
diff --git a/core/Plugin/Dimension/VisitDimension.php b/core/Plugin/Dimension/VisitDimension.php
index b9aa3a9b2aa4235afe5f04b8eeba99e0e4b7025a..97dfd6f57b2e31a6e0906d2bf680edea3d415b24 100644
--- a/core/Plugin/Dimension/VisitDimension.php
+++ b/core/Plugin/Dimension/VisitDimension.php
@@ -8,7 +8,8 @@
  */
 namespace Piwik\Plugin\Dimension;
 
-use Piwik\Cache\PluginAwareStaticCache;
+use Piwik\CacheId;
+use Piwik\Cache as PiwikCache;
 use Piwik\Columns\Dimension;
 use Piwik\Common;
 use Piwik\Db;
@@ -294,9 +295,10 @@ abstract class VisitDimension extends Dimension
      */
     public static function getAllDimensions()
     {
-        $cache = new PluginAwareStaticCache('VisitDimensions');
+        $cacheId = CacheId::pluginAware('VisitDimensions');
+        $cache   = PiwikCache::getTransientCache();
 
-        if (!$cache->has()) {
+        if (!$cache->contains($cacheId)) {
 
             $plugins   = PluginManager::getInstance()->getPluginsLoadedAndActivated();
             $instances = array();
@@ -309,10 +311,10 @@ abstract class VisitDimension extends Dimension
 
             usort($instances, array('self', 'sortByRequiredFields'));
 
-            $cache->set($instances);
+            $cache->save($cacheId, $instances);
         }
 
-        return $cache->get();
+        return $cache->fetch($cacheId);
     }
 
     /**
diff --git a/core/Plugin/Manager.php b/core/Plugin/Manager.php
index a85784f6d46b9caf509d0fa5ddf7a9e498b0f909..bca24d8b5ad676e9fc56dc933473ae5b8e8a0138 100644
--- a/core/Plugin/Manager.php
+++ b/core/Plugin/Manager.php
@@ -9,8 +9,7 @@
 
 namespace Piwik\Plugin;
 
-use Piwik\Cache\PersistentCache;
-use Piwik\CacheFile;
+use Piwik\Cache;
 use Piwik\Columns\Dimension;
 use Piwik\Common;
 use Piwik\Config as PiwikConfig;
@@ -119,10 +118,11 @@ class Manager extends Singleton
      */
     public function loadTrackerPlugins()
     {
-        $cache = new PersistentCache('PluginsTracker');
+        $cacheId = 'PluginsTracker';
+        $cache = Cache::getEagerCache();
 
-        if ($cache->has()) {
-            $pluginsTracker = $cache->get();
+        if ($cache->contains($cacheId)) {
+            $pluginsTracker = $cache->fetch($cacheId);
         } else {
 
             $this->unloadPlugins();
@@ -137,7 +137,7 @@ class Manager extends Singleton
             }
 
             if (!empty($pluginsTracker)) {
-                $cache->set($pluginsTracker);
+                $cache->save($cacheId, $pluginsTracker);
             }
         }
 
@@ -697,7 +697,6 @@ class Manager extends Singleton
             $language = Translate::getLanguageToLoad();
         }
 
-        $cache    = new CacheFile('tracker', 43200); // ttl=12hours
         $cacheKey = 'PluginTranslations';
 
         if (!empty($language)) {
@@ -709,11 +708,12 @@ class Manager extends Singleton
             $cacheKey .= '-' . md5(implode('', $this->getLoadedPluginsName()));
         }
 
-        $translations = $cache->get($cacheKey);
+        $cache = Cache::getLazyCache();
+        $translations = $cache->fetch($cacheKey);
 
         if (!empty($translations) &&
             is_array($translations) &&
-            !Development::isEnabled()) {
+            !Development::isEnabled()) { // TODO remove this one here once we have environments in DI
 
             Translate::mergeTranslationArray($translations);
             return;
@@ -734,7 +734,7 @@ class Manager extends Singleton
             }
         }
 
-        $cache->set($cacheKey, $translations);
+        $cache->save($cacheKey, $translations, 43200); // ttl=12hours
     }
 
     /**
diff --git a/core/Plugin/Report.php b/core/Plugin/Report.php
index 1824b6774f1f946151620d5f69a37f2e5a7367a6..af61a33a0a45f5a45f8b67d205c3a67b7eb69fb9 100644
--- a/core/Plugin/Report.php
+++ b/core/Plugin/Report.php
@@ -10,11 +10,12 @@ namespace Piwik\Plugin;
 
 use Piwik\API\Proxy;
 use Piwik\API\Request;
-use Piwik\Cache\LanguageAwareStaticCache;
+use Piwik\CacheId;
 use Piwik\Columns\Dimension;
 use Piwik\DataTable;
 use Piwik\Menu\MenuReporting;
 use Piwik\Metrics;
+use Piwik\Cache as PiwikCache;
 use Piwik\Piwik;
 use Piwik\Plugin\Manager as PluginManager;
 use Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable;
@@ -735,9 +736,10 @@ class Report
     public static function getAllReports()
     {
         $reports = self::getAllReportClasses();
-        $cache   = new LanguageAwareStaticCache('Reports' . implode('', $reports));
+        $cacheId = CacheId::languageAware('Reports' . md5(implode('', $reports)));
+        $cache   = PiwikCache::getTransientCache();
 
-        if (!$cache->has()) {
+        if (!$cache->contains($cacheId)) {
             $instances = array();
 
             foreach ($reports as $report) {
@@ -746,10 +748,10 @@ class Report
 
             usort($instances, array('self', 'sort'));
 
-            $cache->set($instances);
+            $cache->save($cacheId, $instances);
         }
 
-        return $cache->get();
+        return $cache->fetch($cacheId);
     }
 
     /**
@@ -785,10 +787,10 @@ class Report
 
         foreach ($metricsToTranslate as $metric) {
             if ($metric instanceof Metric) {
-                $metricName = $metric->getName();
+                $metricName  = $metric->getName();
                 $translation = $metric->getTranslatedName();
             } else {
-                $metricName = $metric;
+                $metricName  = $metric;
                 $translation = @$translations[$metric];
             }
 
diff --git a/core/Tracker/Cache.php b/core/Tracker/Cache.php
index b8f0413c63cc686e6fb541f1425f41f3b5a72b24..3fa360986e34523c3670f01c10209a80e047b9fd 100644
--- a/core/Tracker/Cache.php
+++ b/core/Tracker/Cache.php
@@ -10,7 +10,7 @@ namespace Piwik\Tracker;
 
 use Piwik\Access;
 use Piwik\ArchiveProcessor\Rules;
-use Piwik\CacheFile;
+use Piwik\Cache as PiwikCache;
 use Piwik\Common;
 use Piwik\Config;
 use Piwik\Option;
@@ -23,19 +23,29 @@ use Piwik\Tracker;
  */
 class Cache
 {
+    private static $cacheIdGeneral = 'general';
+
     /**
      * Public for tests only
-     * @var CacheFile
+     * @var \Piwik\Cache\Lazy
      */
-    public static $trackerCache = null;
+    public static $cache;
 
-    protected static function getInstance()
+    /**
+     * @return \Piwik\Cache\Lazy
+     */
+    private static function getCache()
     {
-        if (is_null(self::$trackerCache)) {
-            $ttl = Config::getInstance()->Tracker['tracker_cache_file_ttl'];
-            self::$trackerCache = new CacheFile('tracker', $ttl);
+        if (is_null(self::$cache)) {
+            self::$cache = PiwikCache::getLazyCache();
         }
-        return self::$trackerCache;
+
+        return self::$cache;
+    }
+
+    private static function getTtl()
+    {
+        return Config::getInstance()->Tracker['tracker_cache_file_ttl'];
     }
 
     /**
@@ -55,8 +65,9 @@ class Cache
             return array();
         }
 
-        $cache        = self::getInstance();
-        $cacheContent = $cache->get($idSite);
+        $cache = self::getCache();
+        $cacheId = $idSite;
+        $cacheContent = $cache->fetch($cacheId);
 
         if (false !== $cacheContent) {
             return $cacheContent;
@@ -91,7 +102,7 @@ class Cache
         // if nothing is returned from the plugins, we don't save the content
         // this is not expected: all websites are expected to have at least one URL
         if (!empty($content)) {
-            $cache->set($idSite, $content);
+            $cache->save($cacheId, $content, self::getTtl());
         }
 
         return $content;
@@ -102,7 +113,7 @@ class Cache
      */
     public static function clearCacheGeneral()
     {
-        self::getInstance()->delete('general');
+        self::getCache()->delete(self::$cacheIdGeneral);
     }
 
     /**
@@ -113,10 +124,8 @@ class Cache
      */
     public static function getCacheGeneral()
     {
-        $cache   = self::getInstance();
-        $cacheId = 'general';
-
-        $cacheContent = $cache->get($cacheId);
+        $cache = self::getCache();
+        $cacheContent = $cache->fetch(self::$cacheIdGeneral);
 
         if (false !== $cacheContent) {
             return $cacheContent;
@@ -162,11 +171,9 @@ class Cache
      */
     public static function setCacheGeneral($value)
     {
-        $cache   = self::getInstance();
-        $cacheId = 'general';
-        $cache->set($cacheId, $value);
+        $cache = self::getCache();
 
-        return true;
+        return $cache->save(self::$cacheIdGeneral, $value, self::getTtl());
     }
 
     /**
@@ -193,8 +200,7 @@ class Cache
      */
     public static function deleteCacheWebsiteAttributes($idSite)
     {
-        $idSite = (int)$idSite;
-        self::getInstance()->delete($idSite);
+        self::getCache()->delete((int) $idSite);
     }
 
     /**
@@ -202,6 +208,6 @@ class Cache
      */
     public static function deleteTrackerCache()
     {
-        self::getInstance()->deleteAll();
+        self::getCache()->flushAll();
     }
 }
diff --git a/core/Tracker/SettingsStorage.php b/core/Tracker/SettingsStorage.php
index 2e3ac5e17d2b90f0c3d8e3d3293866bf4dde2e29..7ffb3de8727e44f3524bd9c48e433609e3de854f 100644
--- a/core/Tracker/SettingsStorage.php
+++ b/core/Tracker/SettingsStorage.php
@@ -9,9 +9,9 @@
 
 namespace Piwik\Tracker;
 
-use Piwik\Cache\PersistentCache;
 use Piwik\Settings\Storage;
 use Piwik\Tracker;
+use Piwik\Cache as PiwikCache;
 
 /**
  * Loads settings from tracker cache instead of database. If not yet present in tracker cache will cache it.
@@ -20,14 +20,15 @@ class SettingsStorage extends Storage
 {
     protected function loadSettings()
     {
+        $cacheId = $this->getOptionKey();
         $cache = $this->getCache();
 
-        if ($cache->has()) {
-            $settings = $cache->get();
+        if ($cache->contains($cacheId)) {
+            $settings = $cache->fetch($cacheId);
         } else {
             $settings = parent::loadSettings();
 
-            $cache->set($settings);
+            $cache->save($cacheId, $settings);
         }
 
         return $settings;
@@ -41,13 +42,18 @@ class SettingsStorage extends Storage
 
     private function getCache()
     {
-        return new PersistentCache($this->getOptionKey());
+        return self::buildCache($this->getOptionKey());
     }
 
     public static function clearCache()
     {
         Cache::deleteTrackerCache();
-        PersistentCache::_reset();
+        self::buildCache()->flushAll();
+    }
+
+    private static function buildCache()
+    {
+        return PiwikCache::getEagerCache();
     }
 
 }
diff --git a/core/WidgetsList.php b/core/WidgetsList.php
index 943dfceb68a2879b54693ae2d97137cb82a07c41..c474061606d1a1140f258ebdf57c7672a7783408 100644
--- a/core/WidgetsList.php
+++ b/core/WidgetsList.php
@@ -8,7 +8,7 @@
  */
 namespace Piwik;
 
-use Piwik\Cache\PluginAwareStaticCache;
+use Piwik\Cache as PiwikCache;
 use Piwik\Plugin\Report;
 use Piwik\Plugin\Widgets;
 
@@ -63,9 +63,11 @@ class WidgetsList extends Singleton
      */
     public static function get()
     {
-        $cache = self::getCacheForCompleteList();
-        if (!self::$listCacheToBeInvalidated && $cache->has()) {
-            return $cache->get();
+        $cache   = self::getCacheForCompleteList();
+        $cacheId = self::getCacheId();
+
+        if (!self::$listCacheToBeInvalidated && $cache->contains($cacheId)) {
+            return $cache->fetch($cacheId);
         }
 
         self::addWidgets();
@@ -83,7 +85,7 @@ class WidgetsList extends Singleton
             $widgets[$category] = $v;
         }
 
-        $cache->set($widgets);
+        $cache->save($cacheId, $widgets);
         self::$listCacheToBeInvalidated = false;
 
         return $widgets;
@@ -270,11 +272,16 @@ class WidgetsList extends Singleton
     {
         self::$widgets    = array();
         self::$hookCalled = false;
-        self::getCacheForCompleteList()->clear();
+        self::getCacheForCompleteList()->delete(self::getCacheId());
+    }
+
+    private static function getCacheId()
+    {
+        return CacheId::pluginAware('WidgetsList');
     }
 
     private static function getCacheForCompleteList()
     {
-        return new PluginAwareStaticCache('WidgetsList');
+        return PiwikCache::getTransientCache();
     }
 }
diff --git a/plugins/API/Menu.php b/plugins/API/Menu.php
index b01c686ac0432ad6c5f142aaa553779ac2e70a9f..a0f71ddf542ef7cb2d9a7c1b82a80eddc05a228b 100644
--- a/plugins/API/Menu.php
+++ b/plugins/API/Menu.php
@@ -43,7 +43,7 @@ class Menu extends \Piwik\Plugin\Menu
         }
 
         $ua = new OperatingSystem($_SERVER['HTTP_USER_AGENT']);
-        $ua->setCache(new DeviceDetectorCache('tracker', 86400));
+        $ua->setCache(new DeviceDetectorCache(86400));
         $parsedOS = $ua->parse();
 
         if (!empty($parsedOS['short_name']) && in_array($parsedOS['short_name'], array(self::DD_SHORT_NAME_ANDROID, self::DD_SHORT_NAME_IOS))) {
diff --git a/plugins/API/ProcessedReport.php b/plugins/API/ProcessedReport.php
index a5ba529658c72cfe379f3f4e60543a57d62a075a..bd1a885f4d93fd9fd211d30e116ca109d64d59dd 100644
--- a/plugins/API/ProcessedReport.php
+++ b/plugins/API/ProcessedReport.php
@@ -11,7 +11,8 @@ namespace Piwik\Plugins\API;
 use Exception;
 use Piwik\API\Request;
 use Piwik\Archive\DataTableFactory;
-use Piwik\Cache\PluginAwareStaticCache;
+use Piwik\CacheId;
+use Piwik\Cache as PiwikCache;
 use Piwik\Common;
 use Piwik\DataTable;
 use Piwik\DataTable\Row;
@@ -154,10 +155,11 @@ class ProcessedReport
         // as they cache key contains a lot of information there would be an even better cache result by caching parts of
         // this huge method separately but that makes it also more complicated. leaving it like this for now.
         $key   = $this->buildReportMetadataCacheKey($idSites, $period, $date, $hideMetricsDoc, $showSubtableReports);
-        $cache = new PluginAwareStaticCache($key);
+        $key   = CacheId::pluginAware($key);
+        $cache = PiwikCache::getTransientCache();
 
-        if ($cache->has()) {
-            return $cache->get();
+        if ($cache->contains($key)) {
+            return $cache->fetch($key);
         }
 
         $parameters = array('idSites' => $idSites, 'period' => $period, 'date' => $date);
@@ -332,7 +334,7 @@ class ProcessedReport
         }
 
         $actualReports = array_values($availableReports);
-        $cache->set($actualReports);
+        $cache->save($key, $actualReports);
 
         return $actualReports; // make sure array has contiguous key values
     }
diff --git a/plugins/CorePluginsAdmin/MarketplaceApiClient.php b/plugins/CorePluginsAdmin/MarketplaceApiClient.php
index 346b15770f743b7a4ddc3a91c54a5690178262a0..6472da3deac67322ebfaf8bac8642974ffa45116 100644
--- a/plugins/CorePluginsAdmin/MarketplaceApiClient.php
+++ b/plugins/CorePluginsAdmin/MarketplaceApiClient.php
@@ -8,7 +8,7 @@
  */
 namespace Piwik\Plugins\CorePluginsAdmin;
 
-use Piwik\CacheFile;
+use Piwik\Cache;
 use Piwik\Http;
 use Piwik\Version;
 
@@ -22,20 +22,10 @@ class MarketplaceApiClient
 
     private $domain = 'http://plugins.piwik.org';
 
-    /**
-     * @var CacheFile
-     */
-    private $cache = null;
-
-    public function __construct()
-    {
-        $this->cache = new CacheFile('marketplace', self::CACHE_TIMEOUT_IN_SECONDS);
-    }
-
     public static function clearAllCacheEntries()
     {
-        $cache = new CacheFile('marketplace');
-        $cache->deleteAll();
+        $cache = Cache::getLazyCache();
+        $cache->flushAll();
     }
 
     public function getPluginInfo($name)
@@ -137,7 +127,10 @@ class MarketplaceApiClient
     {
         ksort($params);
         $query = http_build_query($params);
-        $result = $this->getCachedResult($action, $query);
+
+        $cacheId = $this->getCacheKey($action, $query);
+        $cache  = $this->buildCache();
+        $result = $cache->fetch($cacheId);
 
         if (false === $result) {
             $endpoint = $this->domain . '/api/1.0/';
@@ -155,29 +148,20 @@ class MarketplaceApiClient
                 throw new MarketplaceApiException($result['error']);
             }
 
-            $this->cacheResult($action, $query, $result);
+            $cache->save($cacheId, $result, self::CACHE_TIMEOUT_IN_SECONDS);
         }
 
         return $result;
     }
 
-    private function getCachedResult($action, $query)
-    {
-        $cacheKey = $this->getCacheKey($action, $query);
-
-        return $this->cache->get($cacheKey);
-    }
-
-    private function cacheResult($action, $query, $result)
+    private function buildCache()
     {
-        $cacheKey = $this->getCacheKey($action, $query);
-
-        $this->cache->set($cacheKey, $result);
+        return Cache::getLazyCache();
     }
 
     private function getCacheKey($action, $query)
     {
-        return sprintf('api.1.0.%s.%s', str_replace('/', '.', $action), md5($query));
+        return sprintf('marketplace.api.1.0.%s.%s', str_replace('/', '.', $action), md5($query));
     }
 
     /**
diff --git a/plugins/CustomAlerts b/plugins/CustomAlerts
index e886aa43f4c248bf6aaeeef05885f4acdf190a82..8d6dd8428317c24e997f335f27f1d3fb522c1935 160000
--- a/plugins/CustomAlerts
+++ b/plugins/CustomAlerts
@@ -1 +1 @@
-Subproject commit e886aa43f4c248bf6aaeeef05885f4acdf190a82
+Subproject commit 8d6dd8428317c24e997f335f27f1d3fb522c1935
diff --git a/plugins/Goals/API.php b/plugins/Goals/API.php
index acd99d9a8272ac0e382e60b5d1537d9a35cf4c54..1349c50e962e8289495de942344ce44077f28108 100644
--- a/plugins/Goals/API.php
+++ b/plugins/Goals/API.php
@@ -10,7 +10,8 @@ namespace Piwik\Plugins\Goals;
 
 use Exception;
 use Piwik\Archive;
-use Piwik\Cache\PluginAwareStaticCache;
+use Piwik\CacheId;
+use Piwik\Cache as PiwikCache;
 use Piwik\Common;
 use Piwik\DataTable;
 use Piwik\Db;
@@ -55,8 +56,9 @@ class API extends \Piwik\Plugin\API
      */
     public function getGoals($idSite)
     {
-        $cache = $this->getGoalsInfoStaticCache($idSite);
-        if (!$cache->has()) {
+        $cacheId = self::getCacheId($idSite);
+        $cache = $this->getGoalsInfoStaticCache();
+        if (!$cache->contains($cacheId)) {
             $idSite = Site::getIdSitesFromIdSitesString($idSite);
 
             if (empty($idSite)) {
@@ -77,9 +79,10 @@ class API extends \Piwik\Plugin\API
                 $cleanedGoals[$goal['idgoal']] = $goal;
             }
 
-            $cache->set($cleanedGoals);
+            $cache->save($cacheId, $cleanedGoals);
         }
-        return $cache->get();
+
+        return $cache->fetch($cacheId);
     }
 
     /**
@@ -119,7 +122,7 @@ class API extends \Piwik\Plugin\API
 
         $idGoal = $this->getModel()->createGoalForSite($idSite, $goal);
 
-        $this->getGoalsInfoStaticCache($idSite)->clear();
+        $this->getGoalsInfoStaticCache()->delete(self::getCacheId($idSite));
 
         Cache::regenerateCacheWebsiteAttributes($idSite);
         return $idGoal;
@@ -166,7 +169,7 @@ class API extends \Piwik\Plugin\API
             'revenue'         => $revenue,
         ));
 
-        $this->getGoalsInfoStaticCache($idSite)->clear();
+        $this->getGoalsInfoStaticCache()->delete(self::getCacheId($idSite));
 
         Cache::regenerateCacheWebsiteAttributes($idSite);
     }
@@ -206,7 +209,7 @@ class API extends \Piwik\Plugin\API
         $this->getModel()->deleteGoal($idSite, $idGoal);
         $this->getModel()->deleteGoalConversions($idSite, $idGoal);
 
-        $this->getGoalsInfoStaticCache($idSite)->clear();
+        $this->getGoalsInfoStaticCache()->delete(self::getCacheId($idSite));
 
         Cache::regenerateCacheWebsiteAttributes($idSite);
     }
@@ -567,8 +570,14 @@ class API extends \Piwik\Plugin\API
         }
     }
 
-    private function getGoalsInfoStaticCache($idSite)
+
+    private function getCacheId($idSite)
+    {
+        return CacheId::pluginAware('Goals.getGoals.' . $idSite);
+    }
+
+    private function getGoalsInfoStaticCache()
     {
-        return new PluginAwareStaticCache("Goals.getGoals.$idSite");
+        return PiwikCache::getTransientCache();
     }
 }
diff --git a/plugins/Insights/tests/Integration/ApiTest.php b/plugins/Insights/tests/Integration/ApiTest.php
index dfa76dcde17c245034c2966a971c087cfed09aa9..6eeac84700809ee2fabf189284b88cbf47c3035a 100644
--- a/plugins/Insights/tests/Integration/ApiTest.php
+++ b/plugins/Insights/tests/Integration/ApiTest.php
@@ -8,8 +8,7 @@
 
 namespace Piwik\Plugins\Insights\tests;
 use Piwik\API\Request as ApiRequest;
-use Piwik\Cache\PluginAwareStaticCache;
-use Piwik\Cache\StaticCache;
+use Piwik\Cache as PiwikCache;
 use Piwik\DataTable;
 use Piwik\DataTable\Row;
 use Piwik\Plugins\Insights\API;
@@ -40,8 +39,7 @@ class ApiTest extends SystemTestCase
     {
         parent::setUp();
 
-        StaticCache::clearAll();
-        PluginAwareStaticCache::clearAll();
+        PiwikCache::flushAll();
 
         Translate::reloadLanguage('en');
         $this->api = API::getInstance();
diff --git a/plugins/LanguagesManager/API.php b/plugins/LanguagesManager/API.php
index 2c8d74978a316d9144f8c829e418b5cd17e7ab6f..f3f50ad57fb7d627e79d352ba6bbbe728b56351e 100644
--- a/plugins/LanguagesManager/API.php
+++ b/plugins/LanguagesManager/API.php
@@ -9,10 +9,10 @@
  */
 namespace Piwik\Plugins\LanguagesManager;
 
-use Piwik\Cache\PersistentCache;
 use Piwik\Db;
 use Piwik\Filesystem;
 use Piwik\Piwik;
+use Piwik\Cache as PiwikCache;
 use Piwik\Plugin\Manager as PluginManager;
 
 /**
@@ -272,10 +272,11 @@ class API extends \Piwik\Plugin\API
             return;
         }
 
-        $cache = new PersistentCache('availableLanguages');
+        $cacheId = 'availableLanguages';
+        $cache = PiwikCache::getEagerCache();
 
-        if ($cache->has()) {
-            $languagesInfo = $cache->get();
+        if ($cache->contains($cacheId)) {
+            $languagesInfo = $cache->fetch($cacheId);
         } else {
             $filenames = $this->getAvailableLanguages();
             $languagesInfo = array();
@@ -289,7 +290,7 @@ class API extends \Piwik\Plugin\API
                 );
             }
 
-            $cache->set($languagesInfo);
+            $cache->save($cacheId, $languagesInfo);
         }
 
         $this->availableLanguageNames = $languagesInfo;
diff --git a/plugins/SitesManager/SiteUrls.php b/plugins/SitesManager/SiteUrls.php
index b859085d921c810749c08a04c0c046a2bd4ce10e..a1fac67a89e349c96238935d409177f3a3eeb020 100644
--- a/plugins/SitesManager/SiteUrls.php
+++ b/plugins/SitesManager/SiteUrls.php
@@ -8,26 +8,25 @@
  */
 namespace Piwik\Plugins\SitesManager;
 
-use Piwik\CacheFile;
-use Piwik\Development;
+use Piwik\Cache;
 
 class SiteUrls
 {
-    private static $allUrlsCacheKey = 'allSiteUrlsPerSite';
+    private static $cacheId = 'allSiteUrlsPerSite';
 
     public static function clearSitesCache()
     {
-        self::getCache()->delete(self::$allUrlsCacheKey);
+        self::getCache()->delete(self::$cacheId);
     }
 
     public function getAllCachedSiteUrls()
     {
         $cache    = $this->getCache();
-        $siteUrls = $cache->get(self::$allUrlsCacheKey);
+        $siteUrls = $cache->fetch(self::$cacheId);
 
-        if (empty($siteUrls) || Development::isEnabled()) {
+        if (empty($siteUrls)) {
             $siteUrls = $this->getAllSiteUrls();
-            $cache->set(self::$allUrlsCacheKey, $siteUrls);
+            $cache->save(self::$cacheId, $siteUrls, 1800);
         }
 
         return $siteUrls;
@@ -53,6 +52,6 @@ class SiteUrls
 
     private static function getCache()
     {
-        return new CacheFile('tracker', 1800);
+        return Cache::getLazyCache();
     }
 }
diff --git a/plugins/SitesManager/tests/Integration/SiteUrlsTest.php b/plugins/SitesManager/tests/Integration/SiteUrlsTest.php
index 4614f7cecea2a186c547403c3d1cff62c2728d1d..f9362ae2f4b32bab59f4fef058ecc81dc3f3d4b5 100644
--- a/plugins/SitesManager/tests/Integration/SiteUrlsTest.php
+++ b/plugins/SitesManager/tests/Integration/SiteUrlsTest.php
@@ -7,7 +7,7 @@
  */
 
 namespace Piwik\Plugins\SitesManager\tests\Integration;
-use Piwik\CacheFile;
+use Piwik\Cache;
 use Piwik\Plugins\SitesManager\API;
 use Piwik\Plugins\SitesManager\SiteUrls;
 use Piwik\Tests\Framework\TestCase\IntegrationTestCase;
@@ -111,8 +111,8 @@ class SiteUrlsTest extends IntegrationTestCase
     public function testGetAllCachedSiteUrls_ShouldReadFromTheCacheFile()
     {
         $urlsToFake = array(1 => 'Whatever');
-        $cache      = new CacheFile('tracker', 600);
-        $cache->set('allSiteUrlsPerSite', $urlsToFake);
+        $cache      = $this->buildCache();
+        $cache->save('allSiteUrlsPerSite', $urlsToFake, 600);
 
         $actual = $this->siteUrls->getAllCachedSiteUrls();
 
@@ -138,9 +138,14 @@ class SiteUrlsTest extends IntegrationTestCase
 
     private function assertValueInCache($value)
     {
-        $cache    = new CacheFile('tracker', 600);
-        $siteUrls = $cache->get('allSiteUrlsPerSite');
+        $cache    = $this->buildCache();
+        $siteUrls = $cache->fetch('allSiteUrlsPerSite');
 
         $this->assertEquals($value, $siteUrls);
     }
+
+    private function buildCache()
+    {
+        return Cache::getLazyCache();
+    }
 }
diff --git a/tests/LocalTracker.php b/tests/LocalTracker.php
index a86d3a565cc4b01ba428e378e1bb227738ba3699..98ef3e65019c37b93dbb2b50f0338c9de5dc46b2 100755
--- a/tests/LocalTracker.php
+++ b/tests/LocalTracker.php
@@ -40,7 +40,7 @@ class Piwik_LocalTracker extends PiwikTracker
         }
 
         // unset cached values
-        Cache::$trackerCache = null;
+        Cache::$cache = null;
 
         // save some values
         $plugins = Config::getInstance()->Plugins['Plugins'];
diff --git a/tests/PHPUnit/Framework/Fixture.php b/tests/PHPUnit/Framework/Fixture.php
index a2d6a6327a819ad67dd9f186d933debd74fa7a4e..4f7aac46fb6db773eb07d8f0e73350ba864d5b85 100644
--- a/tests/PHPUnit/Framework/Fixture.php
+++ b/tests/PHPUnit/Framework/Fixture.php
@@ -8,8 +8,8 @@
 namespace Piwik\Tests\Framework;
 
 use Piwik\Access;
-use Piwik\Cache\StaticCache;
-use Piwik\CacheFile;
+use Piwik\Cache\Backend\File;
+use Piwik\Cache as PiwikCache;
 use Piwik\Common;
 use Piwik\Config;
 use Piwik\DataAccess\ArchiveTableCreator;
@@ -224,7 +224,7 @@ class Fixture extends \PHPUnit_Framework_Assert
         FakeAccess::$superUserLogin = 'superUserLogin';
 
         SettingsPiwik::$cachedKnownSegmentsToArchive = null;
-        CacheFile::$invalidateOpCacheBeforeRead = true;
+        File::$invalidateOpCacheBeforeRead = true;
 
         if ($this->configureComponents) {
             IPAnonymizer::deactivate();
@@ -244,7 +244,7 @@ class Fixture extends \PHPUnit_Framework_Assert
         $this->getTestEnvironment()->executeSetupTestEnvHook();
         Piwik_TestingEnvironment::addSendMailHook();
 
-        StaticCache::clearAll();
+        PiwikCache::getTransientCache()->flushAll();
 
         if ($this->overwriteExisting
             || !$this->isFixtureSetUp()
@@ -304,6 +304,8 @@ class Fixture extends \PHPUnit_Framework_Assert
         Option::clearCache();
         Site::clearCache();
         Cache::deleteTrackerCache();
+        PiwikCache::getTransientCache()->flushAll();
+        PiwikCache::getEagerCache()->flushAll();
         Config::getInstance()->clear();
         ArchiveTableCreator::clear();
         \Piwik\Plugins\ScheduledReports\API::$cache = array();
diff --git a/tests/PHPUnit/Framework/TestCase/IntegrationTestCase.php b/tests/PHPUnit/Framework/TestCase/IntegrationTestCase.php
index becfac3a1871a6263fe742dfe55501fcb6b59935..2a782b67c3e68b1cb5f47f3d3360a86db15322bc 100644
--- a/tests/PHPUnit/Framework/TestCase/IntegrationTestCase.php
+++ b/tests/PHPUnit/Framework/TestCase/IntegrationTestCase.php
@@ -8,10 +8,10 @@
 
 namespace Piwik\Tests\Framework\TestCase;
 
-use Piwik\Cache\StaticCache;
 use Piwik\Config;
 use Piwik\Db;
 use Piwik\Tests\Framework\Fixture;
+use Piwik\Cache as PiwikCache;
 
 /**
  * Tests extending IntegrationTestCase are much slower to run: the setUp will
@@ -78,7 +78,8 @@ abstract class IntegrationTestCase extends SystemTestCase
             self::restoreDbTables(self::$tableData);
         }
 
-        StaticCache::clearAll();
+        PiwikCache::getEagerCache()->flushAll();
+        PiwikCache::getTransientCache()->flushAll();
     }
 
     /**
@@ -86,8 +87,6 @@ abstract class IntegrationTestCase extends SystemTestCase
      */
     public function tearDown()
     {
-        StaticCache::clearAll();
-
         self::$fixture->clearInMemoryCaches();
 
         parent::tearDown();
diff --git a/tests/PHPUnit/Integration/CacheIdTest.php b/tests/PHPUnit/Integration/CacheIdTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..ebdfd9c0351e170b9f40c430ac96361e3fe93808
--- /dev/null
+++ b/tests/PHPUnit/Integration/CacheIdTest.php
@@ -0,0 +1,45 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+namespace Piwik\Tests\Integration;
+
+use Piwik\CacheId;
+use Piwik\Tests\Framework\TestCase\IntegrationTestCase;
+use Piwik\Translate;
+
+/**
+ * @group Cache
+ * @group CacheId
+ */
+class CacheIdTest extends IntegrationTestCase
+{
+    public function setUp()
+    {
+        Translate::loadEnglishTranslation();
+    }
+
+    public function tearDown()
+    {
+        Translate::unloadEnglishTranslation();
+    }
+
+    public function test_languageAware_shouldAppendTheLoadedLanguage()
+    {
+        $result = CacheId::languageAware('myrandomkey');
+
+        $this->assertEquals('myrandomkey-en', $result);
+    }
+
+    public function test_pluginAware_shouldAppendLoadedPluginsAndLanguage()
+    {
+        $result = CacheId::pluginAware('myrandomkey');
+
+        // if this test fails most likely there is a new plugin loaded and you simple have to update the cache id.
+        $this->assertEquals('myrandomkey-8f88a1dea9163e86178e69a1293ec084-en', $result);
+    }
+}
diff --git a/tests/PHPUnit/Integration/CacheTest.php b/tests/PHPUnit/Integration/CacheTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..083e54fd0c05cd9440d2e1ffff1cec0dec30f988
--- /dev/null
+++ b/tests/PHPUnit/Integration/CacheTest.php
@@ -0,0 +1,112 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+namespace Piwik\Tests\Integration;
+
+use Piwik\Cache;
+use Piwik\Container\StaticContainer;
+use Piwik\Piwik;
+use Piwik\Tests\Framework\TestCase\IntegrationTestCase;
+use Piwik\Translate;
+
+/**
+ * @group Cache
+ */
+class CacheTest extends IntegrationTestCase
+{
+    public function setUp()
+    {
+    }
+
+    public function tearDown()
+    {
+    }
+
+    public function test_getLazyCache_shouldCreateAnInstanceOfLazy()
+    {
+        $cache = Cache::getLazyCache();
+
+        $this->assertTrue($cache instanceof Cache\Lazy);
+    }
+
+    public function test_getLazyCache_shouldAlwaysReturnTheSameInstance()
+    {
+        $cache1 = Cache::getLazyCache();
+        $cache2 = Cache::getLazyCache();
+
+        $this->assertSame($cache1, $cache2);
+    }
+
+    public function test_getEagerCache_shouldCreateAnInstanceOfEager()
+    {
+        $cache = Cache::getEagerCache();
+
+        $this->assertTrue($cache instanceof Cache\Eager);
+    }
+
+    public function test_getEagerCache_shouldAlwaysReturnTheSameInstance()
+    {
+        $cache1 = Cache::getEagerCache();
+        $cache2 = Cache::getEagerCache();
+
+        $this->assertSame($cache1, $cache2);
+    }
+
+    public function test_getEagerCache_shouldPersistOnceEventWasTriggered()
+    {
+        StaticContainer::clearContainer();
+        $storageId = 'eagercache-test-ui';
+        $cache = Cache::getEagerCache();
+        $cache->save('test', 'mycontent'); // make sure something was changed, otherwise it won't save anything
+
+        /** @var \Piwik\Cache\Backend $backend */
+        $backend = StaticContainer::getContainer()->get('Piwik\Cache\Backend');
+        $this->assertFalse($backend->doContains($storageId));
+
+        Piwik::postEvent('Request.dispatch.end'); // should trigger save
+
+        $this->assertTrue($backend->doContains($storageId));
+    }
+
+    public function test_getTransientCache_shouldCreateAnInstanceOfTransient()
+    {
+        $cache = Cache::getTransientCache();
+
+        $this->assertTrue($cache instanceof Cache\Transient);
+    }
+
+    public function test_getTransientCache_shouldAlwaysReturnTheSameInstance()
+    {
+        $cache1 = Cache::getTransientCache();
+        $cache2 = Cache::getTransientCache();
+
+        $this->assertSame($cache1, $cache2);
+    }
+
+    public function test_flushAll_shouldActuallyFlushAllCaches()
+    {
+        $cache1 = Cache::getTransientCache();
+        $cache2 = Cache::getLazyCache();
+        $cache3 = Cache::getEagerCache();
+
+        $cache1->save('test1', 'content');
+        $cache2->save('test2', 'content');
+        $cache3->save('test3', 'content');
+
+        $this->assertTrue($cache1->contains('test1'));
+        $this->assertTrue($cache2->contains('test2'));
+        $this->assertTrue($cache3->contains('test3'));
+
+        Cache::flushAll();
+
+        $this->assertFalse($cache1->contains('test1'));
+        $this->assertFalse($cache2->contains('test2'));
+        $this->assertFalse($cache3->contains('test3'));
+    }
+
+}
diff --git a/tests/PHPUnit/Integration/Plugin/ManagerTest.php b/tests/PHPUnit/Integration/Plugin/ManagerTest.php
index 3b6265b4a52943b0f6dbd96d35372758ff07c147..e9bd4ad801a9b3818a218450bd9dfaf1d7d210e3 100644
--- a/tests/PHPUnit/Integration/Plugin/ManagerTest.php
+++ b/tests/PHPUnit/Integration/Plugin/ManagerTest.php
@@ -8,10 +8,10 @@
 
 namespace Piwik\Tests\Integration\Plugin;
 
-use Piwik\Cache\PersistentCache;
 use Piwik\Db;
 use Piwik\Plugin;
 use Piwik\Settings\Storage;
+use Piwik\Cache as PiwikCache;
 use Piwik\Tests\Integration\Settings\IntegrationTestCase;
 
 /**
@@ -20,6 +20,8 @@ use Piwik\Tests\Integration\Settings\IntegrationTestCase;
  */
 class ManagerTest extends IntegrationTestCase
 {
+    private $trackerCacheId = 'PluginsTracker';
+
     /**
      * @var Plugin\Manager
      */
@@ -43,18 +45,18 @@ class ManagerTest extends IntegrationTestCase
     public function test_loadTrackerPlugins_shouldCacheListOfPlugins()
     {
         $cache = $this->getCacheForTrackerPlugins();
-        $this->assertFalse($cache->has());
+        $this->assertFalse($cache->contains($this->trackerCacheId));
 
         $pluginsToLoad = $this->manager->loadTrackerPlugins();
 
-        $this->assertTrue($cache->has());
-        $this->assertEquals($pluginsToLoad, $cache->get());
+        $this->assertTrue($cache->contains($this->trackerCacheId));
+        $this->assertEquals($pluginsToLoad, $cache->fetch($this->trackerCacheId));
     }
 
     public function test_loadTrackerPlugins_shouldBeAbleToLoadPluginsCorrectWhenItIsCached()
     {
         $pluginsToLoad = array('CoreHome', 'UserSettings', 'Login', 'CoreAdminHome');
-        $this->getCacheForTrackerPlugins()->set($pluginsToLoad);
+        $this->getCacheForTrackerPlugins()->save($this->trackerCacheId, $pluginsToLoad);
 
         $pluginsToLoad = $this->manager->loadTrackerPlugins();
 
@@ -65,7 +67,7 @@ class ManagerTest extends IntegrationTestCase
     public function test_loadTrackerPlugins_shouldUnloadAllPlugins_IfThereAreNoneToLoad()
     {
         $pluginsToLoad = array();
-        $this->getCacheForTrackerPlugins()->set($pluginsToLoad);
+        $this->getCacheForTrackerPlugins()->save($this->trackerCacheId, $pluginsToLoad);
 
         $pluginsToLoad = $this->manager->loadTrackerPlugins();
 
@@ -75,7 +77,7 @@ class ManagerTest extends IntegrationTestCase
 
     private function getCacheForTrackerPlugins()
     {
-        return new PersistentCache('PluginsTracker');
+        return PiwikCache::getEagerCache();
     }
 
     private function assertOnlyTrackerPluginsAreLoaded($expectedPluginNamesLoaded)
diff --git a/tests/PHPUnit/Integration/Tracker/SettingsStorageTest.php b/tests/PHPUnit/Integration/Tracker/SettingsStorageTest.php
index 0aa2a49627d515abc255ad48641309610d594afe..dd17e673143bbeae7ce34cb272248933e0b74223 100644
--- a/tests/PHPUnit/Integration/Tracker/SettingsStorageTest.php
+++ b/tests/PHPUnit/Integration/Tracker/SettingsStorageTest.php
@@ -8,8 +8,7 @@
 
 namespace Piwik\Tests\Integration\Tracker;
 
-use Piwik\Cache\PersistentCache;
-use Piwik\Option;
+use Piwik\Cache as PiwikCache;
 use Piwik\Settings\Storage;
 use Piwik\Tests\Integration\Settings\StorageTest;
 use Piwik\Tracker\Cache;
@@ -43,11 +42,16 @@ class SettingsStorageTest extends StorageTest
     {
         $this->setSettingValueInCache('my0815RandomName');
 
-        $this->assertTrue($this->getCache()->has());
+        $this->assertTrue($this->hasCache());
 
         SettingsStorage::clearCache();
 
-        $this->assertFalse($this->getCache()->has());
+        $this->assertFalse($this->hasCache());
+    }
+
+    private function hasCache()
+    {
+        return $this->getCache()->contains($this->storage->getOptionKey());
     }
 
     public function test_storageShouldNotCastAnyCachedValue()
@@ -62,12 +66,12 @@ class SettingsStorageTest extends StorageTest
         $this->storage->setValue($this->setting, 5);
         $this->storage->save();
 
-        $this->assertFalse($this->getCache()->has());
+        $this->assertFalse($this->hasCache());
         $this->assertNotFalse($this->getValueFromOptionTable()); // make sure saved in db
 
         $storage = $this->buildStorage();
         $this->assertEquals(5, $storage->getValue($this->setting));
-        $this->assertTrue($this->getCache()->has());
+        $this->assertTrue($this->hasCache());
     }
 
     public function test_storageCreateACacheEntryIfNoCacheExistsYet()
@@ -77,7 +81,7 @@ class SettingsStorageTest extends StorageTest
 
         $this->setSettingValueAndMakeSureCacheGetsCreated('myVal');
 
-        $cache = $this->getCache()->get();
+        $cache = $this->getCache()->fetch($this->storage->getOptionKey());
 
         $this->assertEquals(array(
             $this->setting->getKey() => 'myVal'
@@ -91,13 +95,13 @@ class SettingsStorageTest extends StorageTest
 
     private function getCache()
     {
-        return new PersistentCache($this->storage->getOptionKey());
+        return PiwikCache::getEagerCache();
     }
 
     private function setSettingValueInCache($value)
     {
         $cache = $this->getCache();
-        $cache->set(array(
+        $cache->save($this->storage->getOptionKey(), array(
             $this->setting->getKey() => $value
         ));
     }
diff --git a/tests/PHPUnit/Integration/Tracker/VisitTest.php b/tests/PHPUnit/Integration/Tracker/VisitTest.php
index ce5f4baf8a32aa38e474223ffe89932fa04fe727..2764e4a2aa9941166d8b3d1832445ae6f4e8af5c 100644
--- a/tests/PHPUnit/Integration/Tracker/VisitTest.php
+++ b/tests/PHPUnit/Integration/Tracker/VisitTest.php
@@ -9,7 +9,8 @@
 namespace Piwik\Tests\Integration\Tracker;
 
 use Piwik\Access;
-use Piwik\Cache\PluginAwareStaticCache;
+use Piwik\Cache;
+use Piwik\CacheId;
 use Piwik\Date;
 use Piwik\Network\IPUtils;
 use Piwik\Plugin\Manager;
@@ -334,8 +335,8 @@ class VisitTest extends IntegrationTestCase
             $dimensions[] = $dim;
         }
 
-        $cache = new PluginAwareStaticCache('VisitDimensions');
-        $cache->set($dimensions);
+        $cache = Cache::getTransientCache();
+        $cache->save(CacheId::pluginAware('VisitDimensions'), $dimensions);
     }
 }
 
diff --git a/tests/PHPUnit/TestingEnvironment.php b/tests/PHPUnit/TestingEnvironment.php
index 3378f99444c6f245ef1ad0ded0a14bf23d432e66..9f31dfd0ed46f1a575fadd4b28594a11ace46495 100644
--- a/tests/PHPUnit/TestingEnvironment.php
+++ b/tests/PHPUnit/TestingEnvironment.php
@@ -145,7 +145,7 @@ class Piwik_TestingEnvironment
             $testingEnvironment->configFileGlobal, $testingEnvironment->configFileLocal, $testingEnvironment->configFileCommon
         ));
 
-        \Piwik\CacheFile::$invalidateOpCacheBeforeRead = true;
+        \Piwik\Cache\Backend\File::$invalidateOpCacheBeforeRead = true;
 
         Piwik::addAction('Access.createAccessSingleton', function($access) use ($testingEnvironment) {
             if (!$testingEnvironment->testUseRegularAuth) {