diff --git a/core/lib/Drupal/Core/CoreBundle.php b/core/lib/Drupal/Core/CoreBundle.php
index 4dca804..bf8f8fe 100644
--- a/core/lib/Drupal/Core/CoreBundle.php
+++ b/core/lib/Drupal/Core/CoreBundle.php
@@ -53,6 +53,8 @@ class CoreBundle extends Bundle
       ->setFactoryMethod('getConnection')
       ->addArgument('slave');
     $container->register('typed_data', 'Drupal\Core\TypedData\TypedDataManager');
+    $container->register('user.tempstore', 'Drupal\user\TempStoreDatabase')
+      ->addArgument(new Reference('database'));
 
     // @todo Replace below lines with the commented out block below it when it's
     //   performant to do so: http://drupal.org/node/1706064.
diff --git a/core/lib/Drupal/Core/KeyValueStore/DatabaseStorage.php b/core/lib/Drupal/Core/KeyValueStore/DatabaseStorage.php
index 4484e9f..d165957 100644
--- a/core/lib/Drupal/Core/KeyValueStore/DatabaseStorage.php
+++ b/core/lib/Drupal/Core/KeyValueStore/DatabaseStorage.php
@@ -6,6 +6,7 @@
  */
 
 namespace Drupal\Core\KeyValueStore;
+use Drupal\Core\Database\Query\Merge;
 
 /**
  * Defines a default key/value store implementation.
@@ -79,6 +80,20 @@ class DatabaseStorage extends StorageBase {
       ->execute();
   }
 
+  public function setIfNotExists($key, $value) {
+    $result = db_merge($this->table)
+      ->insertFields(array(
+        'collection' => $this->collection,
+        'name' => $key,
+        'value' => $value,
+      ))
+      ->condition('collection', $this->collection)
+      ->condition('name', $key)
+      ->condition('value', $value)
+      ->execute();
+    return $result == Merge::STATUS_INSERT;
+  }
+
   /**
    * Implements Drupal\Core\KeyValueStore\KeyValueStoreInterface::deleteMultiple().
    */
@@ -93,4 +108,12 @@ class DatabaseStorage extends StorageBase {
     while (count($keys));
   }
 
+  /**
+   * Implements Drupal\Core\KeyValueStore\KeyValueStoreInterface::deleteAll().
+   */
+  public function deleteAll() {
+    db_delete($this->table)
+      ->conditon('collection', $this->collection)
+      ->execute();
+  }
 }
diff --git a/core/lib/Drupal/Core/KeyValueStore/DatabaseStorageExpire.php b/core/lib/Drupal/Core/KeyValueStore/DatabaseStorageExpire.php
new file mode 100644
index 0000000..e71d05a
--- /dev/null
+++ b/core/lib/Drupal/Core/KeyValueStore/DatabaseStorageExpire.php
@@ -0,0 +1,167 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\KeyValueStore\DatabaseStorage.
+ */
+
+namespace Drupal\Core\KeyValueStore;
+use Drupal\Core\Database\Query\Merge;
+
+  /**
+ * Defines a default key/value store implementation for expiring items.
+ *
+ * This is Drupal's default key/value store implementation. It uses the database
+ * to store key/value data with an expire date.
+ */
+/**
+ *
+ */
+class DatabaseStorageExpire extends StorageBase implements KeyValueStoreExpireInterface {
+
+  /**
+   * The time to live for items in seconds. Defaults to a week.
+   */
+  protected $expire = 604800;
+
+  /**
+   * @var Drupal\Core\Database\Connection $connection
+   */
+  protected $connection;
+
+  /**
+   * Overrides Drupal\Core\KeyValueStore\StorageBase::__construct().
+   *
+   * @param string $collection
+   *   The name of the collection holding key and value pairs.
+   * @param array $options
+   *   An associative array of options for the key/value storage collection.
+   *   Keys used:
+   *   - table. The name of the SQL table to use, defaults to key_value.
+   */
+  public function __construct($collection, array $options = array()) {
+    parent::__construct($collection, $options);
+    $this->connection = $options['connection'];
+    $this->table = isset($options['table']) ? $options['table'] : 'key_value_expire';
+  }
+
+  /**
+   * Implements Drupal\Core\KeyValueStore\KeyValueStoreInterface::getMultiple().
+   */
+  public function getMultiple(array $keys) {
+    $values = array();
+    debug($keys);
+    debug($this->collection);
+    try {
+      $result = $this->connection->query('SELECT name, value FROM {' . db_escape_table($this->table) . '} WHERE expire > :now AND name IN (:keys) AND collection = :collection',
+        array(
+          ':now' => REQUEST_TIME,
+          ':keys' => $keys,
+          ':collection' => $this->collection,
+      ))->fetchAllAssoc('name');
+      foreach ($keys as $key) {
+        if (isset($result[$key])) {
+          $values[$key] = unserialize($result[$key]->value);
+        }
+      }
+    }
+    catch (\Exception $e) {
+      // @todo: Perhaps if the database is never going to be available,
+      // key/value requests should return FALSE in order to allow exception
+      // handling to occur but for now, keep it an array, always.
+    }
+    return $values;
+  }
+
+  /**
+   * Implements Drupal\Core\KeyValueStore\KeyValueStoreInterface::getAll().
+   */
+  public function getAll() {
+    $result = $this->connection->query('SELECT name, value FROM {' . db_escape_table($this->table) . '} WHERE collection = :collection AND expire < :expire', array(':collection' => $this->collection, ':expire' => REQUEST_TIME));
+    $values = array();
+
+    foreach ($result as $item) {
+      if ($item) {
+        $values[$item->name] = unserialize($item->value);
+      }
+    }
+    return $values;
+  }
+
+  /**
+   * Implements Drupal\Core\KeyValueStore\KeyValueStoreInterface::set().
+   */
+  public function set($key, $value) {
+    $this->garbageCollection();
+    $this->connection->merge($this->table)
+      ->key(array(
+        'name' => $key,
+        'collection' => $this->collection,
+      ))
+      ->fields(array(
+        'value' => serialize($value),
+        'expire' => REQUEST_TIME + $this->expire,
+      ))
+      ->execute();
+  }
+
+  /**
+   * @param string $key
+   * @param mixed $value
+   */
+  public function setIfNotExists($key, $value) {
+    $this->garbageCollection();
+    $result = $this->connection->merge($this->table)
+      ->insertFields(array(
+        'collection' => $this->collection,
+        'name' => $key,
+        'value' => serialize($value),
+        'expire' => REQUEST_TIME + $this->expire,
+      ))
+      ->condition('collection', $this->collection)
+      ->condition('name', $key)
+      ->execute();
+    return $result == MERGE::STATUS_INSERT;
+  }
+
+  /**
+   * Implements Drupal\Core\KeyValueStore\KeyValueStoreInterface::deleteMultiple().
+   */
+  public function deleteMultiple(array $keys) {
+    $this->garbageCollection();
+    // Delete in chunks when a large array is passed.
+    do {
+      $this->connection->delete($this->table)
+        ->condition('name', array_splice($keys, 0, 1000))
+        ->condition('collection', $this->collection)
+        ->execute();
+    }
+    while (count($keys));
+  }
+
+  /**
+   * Implements Drupal\Core\KeyValueStore\KeyValueStoreInterface::deleteAll().
+   */
+  public function deleteAll() {
+    $this->garbageCollection();
+    $this->connection->delete($this->table)
+      ->condition('collection', $this->collection)
+      ->execute();
+  }
+
+  /**
+   * Delete expired items.
+   */
+  protected function garbageCollection() {
+    $this->connection->delete($this->table)
+      ->condition('expire', REQUEST_TIME, '<')
+      ->execute();
+  }
+
+  /**
+   * Implements Drupal\Core\KeyValueStore\KeyValueStoreExpireInterface::expire().
+   */
+  public function setExpire($expire) {
+    $this->expire = $expire;
+  }
+}
diff --git a/core/lib/Drupal/Core/KeyValueStore/KeyValueStoreDefaultExpire.php b/core/lib/Drupal/Core/KeyValueStore/KeyValueStoreDefaultExpire.php
new file mode 100644
index 0000000..ede97a3
--- /dev/null
+++ b/core/lib/Drupal/Core/KeyValueStore/KeyValueStoreDefaultExpire.php
@@ -0,0 +1,74 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\KeyValueStore\KeyValueStoreDefaultExpire.
+ */
+
+namespace Drupal\Core\KeyValueStore;
+
+/**
+ * Stores and retrieves values from a key-value store with a default key.
+ */
+class KeyValueStoreDefaultExpire {
+
+  /**
+   * @param KeyValueStoreExpireInterface $storage
+   * @param string $key
+   */
+  function __construct(KeyValueStoreExpireInterface $storage, $key) {
+    $this->storage = $storage;
+    $this->key = $key;
+  }
+
+  /**
+   * Returns the stored value for the default key.
+   *
+   * @return mixed
+   */
+  function getDefault() {
+    return $this->storage->get($this->key);
+  }
+
+  /**
+   * Adds the value for the default key if it doesn't exist yet.
+   *
+   * @return mixed
+   */
+  function setIfNotExistsDefault($value) {
+    return $this->storage->setIfNotExists($this->key, $value);
+  }
+
+  /**
+   * Sets the value for the default key.
+   *
+   * @return mixed
+   */
+  function setDefault($value) {
+    return $this->storage->set($this->key, $value);
+  }
+
+  /**
+   * Gets all values in the storage.
+   *
+   * @return array
+   */
+  function getAll() {
+    return $this->storage->getAll();
+  }
+
+  /**
+   * Deletes the value of the default key.
+   */
+  function deleteDefault() {
+    $this->storage->delete($this->key);
+  }
+
+  /**
+   * Deletes all values in the storage.
+   */
+  function deleteAll() {
+    $this->storage->deleteAll();
+  }
+
+}
diff --git a/core/lib/Drupal/Core/KeyValueStore/KeyValueStoreExpireInterface.php b/core/lib/Drupal/Core/KeyValueStore/KeyValueStoreExpireInterface.php
new file mode 100644
index 0000000..4b339a1
--- /dev/null
+++ b/core/lib/Drupal/Core/KeyValueStore/KeyValueStoreExpireInterface.php
@@ -0,0 +1,21 @@
+<?php
+/**
+ * @file
+ * Contains Drupal\Core\KeyValueStore\KeyValueStoreExpireInterface.
+ */
+
+namespace Drupal\Core\KeyValueStore;
+
+/**
+ * Defines the interface for expiring date in a key/value store.
+ */
+interface KeyValueStoreExpireInterface extends KeyValueStoreInterface {
+
+  /**
+   * Set the expiration time for this key-value store collection.
+   *
+   * @param int $expire
+   */
+  function setExpire($expire);
+
+}
diff --git a/core/lib/Drupal/Core/KeyValueStore/KeyValueStoreInterface.php b/core/lib/Drupal/Core/KeyValueStore/KeyValueStoreInterface.php
index 9e7bb34..90dfeb3 100644
--- a/core/lib/Drupal/Core/KeyValueStore/KeyValueStoreInterface.php
+++ b/core/lib/Drupal/Core/KeyValueStore/KeyValueStoreInterface.php
@@ -73,6 +73,18 @@ interface KeyValueStoreInterface {
   public function set($key, $value);
 
   /**
+   * Saves a value for a given key if it does not exist yet.
+   *
+   * @param string $key
+   *   The key of the data to store.
+   * @param mixed $value
+   *   The data to store.
+   * @return
+   *   TRUE if the data was set, FALSE if it already existed.
+   */
+  public function setIfNotExists($key, $value);
+
+  /**
    * Saves key/value pairs.
    *
    * @param array $data
@@ -96,4 +108,12 @@ interface KeyValueStoreInterface {
    */
   public function deleteMultiple(array $keys);
 
+  /**
+   * Deletes all items from this namespace of the key-value store.
+   *
+   * @param array $keys
+   *   A list of item names to delete.
+   */
+  public function deleteAll();
+
 }
diff --git a/core/lib/Drupal/Core/KeyValueStore/MemoryStorage.php b/core/lib/Drupal/Core/KeyValueStore/MemoryStorage.php
index 4724005..f74de02 100644
--- a/core/lib/Drupal/Core/KeyValueStore/MemoryStorage.php
+++ b/core/lib/Drupal/Core/KeyValueStore/MemoryStorage.php
@@ -65,6 +65,17 @@ class MemoryStorage implements KeyValueStoreInterface {
   }
 
   /**
+   * Implements Drupal\Core\KeyValueStore\KeyValueStoreInterface::setIfNotExists().
+   */
+  public function setIfNotExists($key, $value) {
+    if (!isset($this->data[$key])) {
+      $this->data[$key] = $value;
+      return TRUE;
+    }
+    return FALSE;
+  }
+
+  /**
    * Implements Drupal\Core\KeyValueStore\KeyValueStoreInterface::setMultiple().
    */
   public function setMultiple(array $data) {
@@ -87,4 +98,11 @@ class MemoryStorage implements KeyValueStoreInterface {
     }
   }
 
+  /**
+   * Implements Drupal\Core\KeyValueStore\KeyValueStoreInterface::deleteAll().
+   */
+  public function deleteAll() {
+    $this->data = array();
+  }
+
 }
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 3790f2b..c6826f9 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -832,6 +832,43 @@ function system_schema() {
     'primary key' => array('collection', 'name'),
   );
 
+  $schema['key_value_expire'] = array(
+    'description' => 'Generic key-value storage table. See state() for an example.',
+    'fields' => array(
+      'collection' => array(
+        'description' => 'A named collection of key and value pairs.',
+        'type' => 'varchar',
+        'length' => 128,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'name' => array(
+        'description' => 'The key of the key-value pair. As KEY is a SQL reserved keyword, name was chosen instead.',
+        'type' => 'varchar',
+        'length' => 128,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'value' => array(
+        'description' => 'The value.',
+        'type' => 'blob',
+        'not null' => TRUE,
+        'size' => 'big',
+        'translatable' => TRUE,
+      ),
+      'expire' => array(
+        'description' => 'The time since Unix epoch in seconds when this item expires.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+    ),
+    'primary key' => array('collection', 'name'),
+    'indexes' => array(
+      'all' => array('name', 'collection', 'expire'),
+    ),
+  );
+
   $schema['menu_router'] = array(
     'description' => 'Maps paths to various callbacks (access, page and title)',
     'fields' => array(
@@ -1976,6 +2013,52 @@ function system_update_8021() {
 }
 
 /**
+ * Create the 'temp_store' table.
+ */
+function system_update_8022() {
+  $table = array(
+    'description' => t('A temporary data store for objects that are being edited. Allows state to be saved in a stateless environment.'),
+    'fields' => array(
+      'owner_id' => array(
+        'type' => 'varchar',
+        'length' => '64',
+        'not null' => TRUE,
+        'description' => 'The session ID this object belongs to.',
+      ),
+      'namespace' => array(
+        'type' => 'varchar',
+        'length' => '128',
+        'not null' => TRUE,
+        'description' => 'The owner (type of the object) for this data store. Allows multiple namespaces to use this data store.',
+      ),
+      'temp_key' => array(
+        'type' => 'varchar',
+        'length' => '128',
+        'not null' => TRUE,
+        'description' => 'The key of the object this data store is attached to.',
+      ),
+      'updated' => array(
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+        'description' => 'The time this data store was created or updated.',
+      ),
+      'data' => array(
+        'type' => 'text',
+        'size' => 'big',
+        'description' => 'Serialized data being stored.',
+        'serialize' => TRUE,
+      ),
+    ),
+    'primary key' => array('owner_id', 'namespace', 'temp_key'),
+    'indexes' => array('updated' => array('updated')),
+  );
+
+  db_create_table('temp_store', $table);
+}
+
+/**
  * @} End of "defgroup updates-7.x-to-8.x".
  * The next series of updates should start at 9000.
  */
diff --git a/core/modules/user/lib/Drupal/user/TempStoreDatabase.php b/core/modules/user/lib/Drupal/user/TempStoreDatabase.php
new file mode 100644
index 0000000..9d65646
--- /dev/null
+++ b/core/modules/user/lib/Drupal/user/TempStoreDatabase.php
@@ -0,0 +1,30 @@
+<?php
+/**
+ * @file
+ * Definition of Drupal\user\TempStoreDatabase.
+ */
+
+namespace Drupal\user;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\KeyValueStore\DatabaseStorageExpire;
+use Drupal\Core\KeyValueStore\KeyValueStoreDefaultExpire;
+
+class TempStoreDatabase {
+
+  function __construct(Connection $connection) {
+    $this->connection = $connection;
+  }
+
+  /**
+   * Create a KeyValueStoreDefaultExpire stored in the database.
+   *
+   * @param Drupal\Core\Database\Connection $connection
+   *
+   * @return Drupal\Core\KeyValueStore\KeyValueStoreDefaultExpire
+   */
+  function get($namespace) {
+    $storage = new DatabaseStorageExpire($namespace, array('connection' => $this->connection));
+    return new KeyValueStoreDefaultExpire($storage, $GLOBALS['user']->uid ?: session_id());
+  }
+}
diff --git a/core/modules/user/lib/Drupal/user/Tests/TempStoreDatabaseTest.php b/core/modules/user/lib/Drupal/user/Tests/TempStoreDatabaseTest.php
new file mode 100644
index 0000000..ca7d781
--- /dev/null
+++ b/core/modules/user/lib/Drupal/user/Tests/TempStoreDatabaseTest.php
@@ -0,0 +1,100 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\user\Tests\TempStoreDatabaseTest.
+ */
+
+namespace Drupal\user\Tests;
+
+use Drupal\simpletest\WebTestBase;
+use stdClass;
+
+/**
+ * Tests the TempStore namespace.
+ *
+ * @see Drupal\Core\TempStore\TempStore.
+ */
+class TempStoreDatabaseTest extends WebTestBase {
+
+  /**
+   * An array of Drupal\user\User entities.
+   *
+   * @var array
+   */
+  protected $users = array();
+
+  /**
+   * Random stdClass objects.
+   *
+   * @var stdClass
+   */
+  protected $objects = array();
+
+  public static function getInfo() {
+    return array(
+      'name' => 'TempStore',
+      'description' => 'Tests the temporary object storage system.',
+      'group' => 'TempStore',
+    );
+  }
+
+  protected function setUp() {
+    parent::setUp();
+    // Create two users and two objects for testing.
+    for ($i = 0; $i <= 1; $i++) {
+      $this->users[$i] = $this->drupalCreateUser();
+      $this->objects[$i] = $this->randomObject();
+    }
+  }
+
+  /**
+   * Generates a random PHP object.
+   *
+   * @param int $size
+   *   The number of random keys to add to the object.
+   *
+   * @return stdClass
+   *   The generated object, with the specified number of random keys. Each key
+   *   has a random string value.
+   */
+  public function randomObject($size = 4) {
+    $object = new stdClass();
+    for ($i = 0; $i < $size; $i++) {
+      $random_key = $this->randomName();
+      $random_value = $this->randomString();
+      $object->{$random_key} = $random_value;
+    }
+    return $object;
+  }
+
+  /**
+   * Tests the UserTempStore API.
+   */
+  public function testUserTempStore() {
+    $namespace = $this->randomName();
+    for ($i = 0; $i <= 1; $i++) {
+      $this->drupalLogin($this->users[$i]);
+      $tempStore = drupal_container()->get('user.tempstore')->get($namespace);
+      // Setting twice results only in the first succeeding.
+      $this->assertEqual(!$i, $tempStore->setIfNotExistsDefault($this->objects[$i]));
+      $this->assertIdenticalObject($this->objects[0], $tempStore->getDefault());
+    }
+    // Break the lock.
+    $tempStore->deleteAll();
+    $tempStore->setIfNotExistsDefault($this->objects[1]);
+    // Break succeeded.
+    $this->assertIdenticalObject($this->objects[1], $tempStore->getDefault());
+  }
+
+  protected function assertIdenticalObject($object1, $object2) {
+    $identical = TRUE;
+    foreach ($object1 as $key => $value) {
+      $identical = $identical && ($object2->$key === $value);
+    }
+    $this->assertTrue($identical, format_string('!object1 is identical to !object2', array(
+      '!object1' => var_export($object1, TRUE),
+      '!object2' => var_export($object2, TRUE),
+    )));
+  }
+}
