diff --git a/core/includes/form.inc b/core/includes/form.inc
index 3c88b1e..c853950 100644
--- a/core/includes/form.inc
+++ b/core/includes/form.inc
@@ -504,9 +504,10 @@ function form_get_cache($form_build_id, &$form_state) {
 
     global $user;
     if ((isset($form['#cache_token']) && drupal_valid_token($form['#cache_token'])) || (!isset($form['#cache_token']) && !$user->uid)) {
-      if ($cached = cache('form')->get('form_state_' . $form_build_id)) {
+      $stored_form_state = drupal_container()->get('keyvalue.expirable')->get('form_state')->get($form_build_id);
+      if ($stored_form_state) {
         // Re-populate $form_state for subsequent rebuilds.
-        $form_state = $cached->data + $form_state;
+        $form_state = $stored_form_state + $form_state;
 
         // If the original form is contained in include files, load the files.
         // @see form_load_include()
@@ -543,7 +544,7 @@ function form_set_cache($form_build_id, $form, $form_state) {
 
   // Cache form state.
   if ($data = array_diff_key($form_state, array_flip(form_state_keys_no_cache()))) {
-    cache('form')->set('form_state_' . $form_build_id, $data, REQUEST_TIME + $expire);
+    drupal_container()->get('keyvalue.expirable')->get('form_state')->setWithExpire($form_build_id, $data, $expire);
   }
 }
 
@@ -882,7 +883,7 @@ function drupal_process_form($form_id, &$form, &$form_state) {
       $config = config('system.performance');
       if (!$config->get('cache.page.enabled') && !empty($form_state['values']['form_build_id'])) {
         cache('form')->delete('form_' . $form_state['values']['form_build_id']);
-        cache('form')->delete('form_state_' . $form_state['values']['form_build_id']);
+        drupal_container()->get('keyvalue.expirable')->get('form_state')->delete($form_state['values']['form_build_id']);
       }
 
       // If batches were set in the submit handlers, we process them now,
diff --git a/core/lib/Drupal/Core/CoreBundle.php b/core/lib/Drupal/Core/CoreBundle.php
index e1147ac..0d87ba2 100644
--- a/core/lib/Drupal/Core/CoreBundle.php
+++ b/core/lib/Drupal/Core/CoreBundle.php
@@ -12,6 +12,7 @@
 use Drupal\Core\DependencyInjection\Compiler\RegisterMatchersPass;
 use Drupal\Core\DependencyInjection\Compiler\RegisterNestedMatchersPass;
 use Drupal\Core\DependencyInjection\Compiler\RegisterSerializationClassesPass;
+use Drupal\Core\DependencyInjection\Compiler\RegisterServicesForTerminationPass;
 use Symfony\Component\DependencyInjection\ContainerBuilder;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\DependencyInjection\Reference;
@@ -92,6 +93,15 @@ public function build(ContainerBuilder $container) {
     // Register the EntityManager.
     $container->register('plugin.manager.entity', 'Drupal\Core\Entity\EntityManager');
 
+    // Register the expirable KeyValueStore factory.
+    $container
+      ->register('keyvalue.expirable', 'Drupal\Core\KeyValueStore\KeyValueExpirableFactory')
+      ->addArgument(new Reference('service_container'));
+    $container
+      ->register('keyvalue.expirable.database', 'Drupal\Core\KeyValueStore\KeyValueDatabaseExpirableFactory')
+      ->addArgument(new Reference('database'))
+      ->addTag('needs_termination');
+
     // The 'request' scope and service enable services to depend on the Request
     // object and get reconstructed when the request object changes (e.g.,
     // during a subrequest).
@@ -236,6 +246,10 @@ public function build(ContainerBuilder $container) {
     $container->register('flood', 'Drupal\Core\Flood\DatabaseBackend')
       ->addArgument(new Reference('database'));
 
+    $container->register('service_terminator', 'Drupal\Core\ServiceTerminator')
+      ->addArgument(new Reference('service_container'))
+      ->addTag('event_subscriber');
+
     $container->addCompilerPass(new RegisterMatchersPass());
     $container->addCompilerPass(new RegisterNestedMatchersPass());
     // Add a compiler pass for registering event subscribers.
@@ -245,6 +259,8 @@ public function build(ContainerBuilder $container) {
     // Add a compiler pass for registering event subscribers.
     $container->addCompilerPass(new RegisterKernelListenersPass(), PassConfig::TYPE_AFTER_REMOVING);
     $container->addCompilerPass(new RegisterAccessChecksPass());
+    // Add a compiler pass for registering services needing termination.
+    $container->addCompilerPass(new RegisterServicesForTerminationPass());
   }
 
 }
diff --git a/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterServicesForTerminationPass.php b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterServicesForTerminationPass.php
new file mode 100644
index 0000000..7480fa5
--- /dev/null
+++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterServicesForTerminationPass.php
@@ -0,0 +1,44 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\DependencyInjection\Compiler\RegisterServicesForTerminationPass.
+ */
+
+namespace Drupal\Core\DependencyInjection\Compiler;
+
+use InvalidArgumentException;
+use ReflectionClass;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+
+/**
+ * Registers needs_termination tagged services with service_terminator.
+ */
+class RegisterServicesForTerminationPass implements CompilerPassInterface {
+
+  /**
+   * Implements CompilerPassInterface::process().
+   */
+  public function process(ContainerBuilder $container) {
+    if (!$container->hasDefinition('service_terminator')) {
+      return;
+    }
+
+    $definition = $container->getDefinition('service_terminator');
+
+    foreach ($container->findTaggedServiceIds('needs_termination') as $id => $attributes) {
+
+      // We must assume that the class value has been correcly filled, even if
+      // the service is created by a factory.
+      $class = $container->getDefinition($id)->getClass();
+
+      $refClass = new ReflectionClass($class);
+      $interface = 'Drupal\Core\TerminationInterface';
+      if (!$refClass->implementsInterface($interface)) {
+        throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface));
+      }
+      $definition->addMethodCall('registerService', array($id));
+    }
+  }
+}
diff --git a/core/lib/Drupal/Core/KeyValueStore/DatabaseStorageExpirable.php b/core/lib/Drupal/Core/KeyValueStore/DatabaseStorageExpirable.php
index e989470..6280849 100644
--- a/core/lib/Drupal/Core/KeyValueStore/DatabaseStorageExpirable.php
+++ b/core/lib/Drupal/Core/KeyValueStore/DatabaseStorageExpirable.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Core\KeyValueStore;
 
+use Drupal\Core\TerminationInterface;
 use Drupal\Core\Database\Connection;
 use Drupal\Core\Database\Query\Merge;
 
@@ -16,7 +17,7 @@
  * This key/value store implementation uses the database to store key/value
  * data with an expire date.
  */
-class DatabaseStorageExpirable extends DatabaseStorage implements KeyValueStoreExpirableInterface {
+class DatabaseStorageExpirable extends DatabaseStorage implements KeyValueStoreExpirableInterface, TerminationInterface {
 
   /**
    * The connection object for this storage.
@@ -56,15 +57,6 @@ public function __construct($collection, Connection $connection, $table = 'key_v
   }
 
   /**
-   * Performs garbage collection as needed when destructing the storage object.
-   */
-  public function __destruct() {
-    if ($this->needsGarbageCollection) {
-      $this->garbageCollection();
-    }
-  }
-
-  /**
    * Implements Drupal\Core\KeyValueStore\KeyValueStoreInterface::getMultiple().
    */
   public function getMultiple(array $keys) {
@@ -158,4 +150,13 @@ protected function garbageCollection() {
       ->execute();
   }
 
+  /**
+   * Implements Drupal\Core\TerminationInterface::terminate().
+   */
+  public function terminate() {
+    if ($this->needsGarbageCollection && $this->connection->schema()->tableExists($this->table)) {
+      $this->garbageCollection();
+    }
+  }
+
 }
diff --git a/core/lib/Drupal/Core/KeyValueStore/KeyValueDatabaseExpirableFactory.php b/core/lib/Drupal/Core/KeyValueStore/KeyValueDatabaseExpirableFactory.php
index 08e673e..bed576e 100644
--- a/core/lib/Drupal/Core/KeyValueStore/KeyValueDatabaseExpirableFactory.php
+++ b/core/lib/Drupal/Core/KeyValueStore/KeyValueDatabaseExpirableFactory.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Core\KeyValueStore;
 
+use Drupal\Core\TerminationInterface;
 use Drupal\Core\Database\Connection;
 use Drupal\Core\Database\Database;
 use Drupal\Core\KeyValueStore\KeyValueDatabaseFactory;
@@ -14,7 +15,14 @@
 /**
  * Defines the key/value store factory for the database backend.
  */
-class KeyValueDatabaseExpirableFactory extends KeyValueDatabaseFactory {
+class KeyValueDatabaseExpirableFactory extends KeyValueDatabaseFactory implements TerminationInterface {
+
+  /**
+   * Holds references to each instantiation so they can be terminated.
+   *
+   * @var array
+   */
+  protected $storages;
 
   /**
    * Constructs a new key/value expirable database storage object for a given
@@ -28,6 +36,17 @@ class KeyValueDatabaseExpirableFactory extends KeyValueDatabaseFactory {
    *   A key/value store implementation for the given $collection.
    */
   public function get($collection) {
-    return new DatabaseStorageExpirable($collection, $this->connection);
+    $storage = new DatabaseStorageExpirable($collection, $this->connection);
+    $this->storages[] = $storage;
+    return $storage;
+  }
+
+  /**
+   * Implements Drupal\Core\TerminationInterface::terminate().
+   */
+  public function terminate() {
+    foreach ($this->storages as $storage) {
+      $storage->terminate();
+    }
   }
 }
diff --git a/core/lib/Drupal/Core/ServiceTerminator.php b/core/lib/Drupal/Core/ServiceTerminator.php
new file mode 100644
index 0000000..74ea845
--- /dev/null
+++ b/core/lib/Drupal/Core/ServiceTerminator.php
@@ -0,0 +1,77 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\ServiceTerminator.
+ */
+
+namespace Drupal\Core;
+
+use Symfony\Component\HttpKernel\KernelEvents;
+use Symfony\Component\HttpKernel\Event\PostResponseEvent;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * This terminates iniated services tagged with needs_termination.
+ */
+class ServiceTerminator implements EventSubscriberInterface {
+
+  /**
+   * Holds an array of service ID's that will require termination.
+   *
+   * @var array
+   */
+  protected $services;
+
+  /**
+   * Constructs a ServiceTerminator.
+   *
+   * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
+   *   The container object.
+   */
+  function __construct(ContainerInterface $container) {
+    $this->container = $container;
+  }
+
+  /**
+   * Registers a a service for termination.
+   *
+   * Calls to this method are set up in
+   * RegisterServicesForTerminationPass::terminate().
+   *
+   * @param string $id
+   *   Name of the service.
+   */
+  public function registerService($id) {
+    $this->services[] = $id;
+  }
+
+  /**
+   * Invoked by the terminate kernel event.
+   *
+   * @param \Symfony\Component\HttpKernel\Event\PostResponseEvent $event
+   *   The event object.
+   */
+  public function onKernelTerminate(PostResponseEvent $event) {
+    foreach ($this->services as $id) {
+      // Check if the service was initialized during this request, termination
+      // is not necessary if the service was not used.
+      if ($this->container->initialized($id)) {
+        $service = $this->container->get($id);
+        $service->terminate();
+      }
+    }
+  }
+
+  /**
+   * Registers the methods in this class that should be listeners.
+   *
+   * @return array
+   *   An array of event listener definitions.
+   */
+  static function getSubscribedEvents() {
+    $events[KernelEvents::TERMINATE][] = array('onKernelTerminate', 100);
+    return $events;
+  }
+}
diff --git a/core/lib/Drupal/Core/TerminationInterface.php b/core/lib/Drupal/Core/TerminationInterface.php
new file mode 100644
index 0000000..e68edc4
--- /dev/null
+++ b/core/lib/Drupal/Core/TerminationInterface.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\TerminationInterface.
+ */
+
+namespace Drupal\Core;
+
+/**
+ * The interface for services needing explicit termination.
+ */
+interface TerminationInterface {
+
+  /**
+   * Performs termination operations.
+   */
+  public function terminate();
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/KeyValueStore/GarbageCollectionTest.php b/core/modules/system/lib/Drupal/system/Tests/KeyValueStore/GarbageCollectionTest.php
index 6334382..925c928 100644
--- a/core/modules/system/lib/Drupal/system/Tests/KeyValueStore/GarbageCollectionTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/KeyValueStore/GarbageCollectionTest.php
@@ -65,7 +65,7 @@ public function testGarbageCollection() {
     // Perform a new set operation and then manually unset the object to
     // trigger garbage collection.
     $store->setWithExpire('autumn', 'winter', rand(500, 1000000));
-    unset($store);
+    $store->terminate();
 
     // Query the database and confirm that the stale records were deleted.
     $result = db_query(
diff --git a/core/modules/system/lib/Drupal/system/Tests/ServiceTerminator/ServiceTerminatorTest.php b/core/modules/system/lib/Drupal/system/Tests/ServiceTerminator/ServiceTerminatorTest.php
new file mode 100644
index 0000000..954b810
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/ServiceTerminator/ServiceTerminatorTest.php
@@ -0,0 +1,53 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\system\Tests\ServiceTerminator\ServiceTerminatorTest.
+ */
+
+namespace Drupal\system\Tests\ServiceTerminator;
+
+use Drupal\simpletest\DrupalUnitTestBase;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\Event\PostResponseEvent;
+
+/**
+ * Tests the service terminator service.
+ */
+class ServiceTerminatorTest extends DrupalUnitTestBase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Service terminator',
+      'description' => 'Tests that services are correctly terminated.',
+      'group' => 'Service Terminator',
+    );
+  }
+
+  /**
+   * Verifies that services are correctly terminated.
+   */
+  public function testTermination() {
+    // Enable the test module to add it to the container.
+    $this->enableModules(array('bundle_test'));
+
+    // The service has not been terminated yet.
+    $this->assertNull(state()->get('bundle_test.terminated'));
+
+    // Get the service terminator.
+    $service_terminator = $this->container->get('service_terminator');
+
+    // Simulate a shutdown. The test class has not been called, so it should not
+    // be terminated.
+    $response = new Response();
+    $event = new PostResponseEvent($this->container->get('kernel'), $this->container->get('request'), $response);
+    $service_terminator->onKernelTerminate($event);
+    $this->assertNull(state()->get('bundle_test.terminated'));
+
+    // Now call the class and then terminate again.
+    $this->container->get('bundle_test_class');
+    $service_terminator->onKernelTerminate($event);
+    $this->assertTrue(state()->get('bundle_test.terminated'));
+  }
+
+}
diff --git a/core/modules/system/tests/modules/bundle_test/lib/Drupal/bundle_test/BundleTestBundle.php b/core/modules/system/tests/modules/bundle_test/lib/Drupal/bundle_test/BundleTestBundle.php
index 21a62d5..6e9a4a4 100644
--- a/core/modules/system/tests/modules/bundle_test/lib/Drupal/bundle_test/BundleTestBundle.php
+++ b/core/modules/system/tests/modules/bundle_test/lib/Drupal/bundle_test/BundleTestBundle.php
@@ -19,7 +19,8 @@ class BundleTestBundle extends Bundle
 {
   public function build(ContainerBuilder $container) {
     $container->register('bundle_test_class', 'Drupal\bundle_test\TestClass')
-      ->addTag('event_subscriber');
+      ->addTag('event_subscriber')
+      ->addTag('needs_termination');
 
     // Override a default bundle used by core to a dummy class.
     $container->register('file.usage', 'Drupal\bundle_test\TestFileUsage');
diff --git a/core/modules/system/tests/modules/bundle_test/lib/Drupal/bundle_test/TestClass.php b/core/modules/system/tests/modules/bundle_test/lib/Drupal/bundle_test/TestClass.php
index f58f9c9..160ee1d 100644
--- a/core/modules/system/tests/modules/bundle_test/lib/Drupal/bundle_test/TestClass.php
+++ b/core/modules/system/tests/modules/bundle_test/lib/Drupal/bundle_test/TestClass.php
@@ -7,11 +7,12 @@
 
 namespace Drupal\bundle_test;
 
-use Symfony\Component\HttpKernel\KernelEvents;
-use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use Drupal\Core\TerminationInterface;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use Symfony\Component\HttpKernel\KernelEvents;
 
-class TestClass implements EventSubscriberInterface {
+class TestClass implements EventSubscriberInterface, TerminationInterface {
 
   /**
    * A simple kernel listener method.
@@ -30,4 +31,12 @@ static function getSubscribedEvents() {
     $events[KernelEvents::REQUEST][] = array('onKernelRequestTest', 100);
     return $events;
   }
+
+  /**
+   * Implements Drupal\Core\TerminationInterface::terminate().
+   */
+  public function terminate() {
+    // @todo: This should be injected.
+    state()->set('bundle_test.terminated', TRUE);
+  }
 }
