diff --git a/core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php b/core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php
index cc97849..22cf527 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Database\Connection;
 use Drupal\Core\Entity\Query\QueryInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\Language\Language;
 use Drupal\field\FieldInfo;
 use Drupal\field\FieldConfigUpdateForbiddenException;
@@ -821,7 +822,7 @@ protected function doLoadFieldItems($entities, $age) {
             $delta_count[$row->entity_id][$row->langcode] = 0;
           }
 
-          if ($field->getCardinality() == FieldConfigInterface::CARDINALITY_UNLIMITED || $delta_count[$row->entity_id][$row->langcode] < $field->getCardinality()) {
+          if ($field->getCardinality() == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED || $delta_count[$row->entity_id][$row->langcode] < $field->getCardinality()) {
             $item = array();
             // For each column declared by the field, populate the item from the
             // prefixed database column.
@@ -907,7 +908,7 @@ protected function doSaveFieldItems(EntityInterface $entity, $update) {
           $query->values($record);
           $revision_query->values($record);
 
-          if ($field->getCardinality() != FieldConfigInterface::CARDINALITY_UNLIMITED && ++$delta_count == $field->getCardinality()) {
+          if ($field->getCardinality() != FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED && ++$delta_count == $field->getCardinality()) {
             break;
           }
         }
diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php
index 5d10375..f0df059 100644
--- a/core/lib/Drupal/Core/Entity/EntityManager.php
+++ b/core/lib/Drupal/Core/Entity/EntityManager.php
@@ -99,6 +99,16 @@ class EntityManager extends PluginManagerBase implements EntityManagerInterface
   protected $fieldDefinitions;
 
   /**
+   * Static cache of field storage definitions per entity type.
+   *
+   * Elements of the array:
+   *  - $entity_type_id: \Drupal\Core\Field\FieldDefinition[]
+   *
+   * @var array
+   */
+  protected $fieldStorageDefinitions;
+
+  /**
    * The root paths.
    *
    * @see self::__construct().
@@ -332,7 +342,7 @@ public function getBaseFieldDefinitions($entity_type_id) {
    *
    * @param string $entity_type_id
    *   The entity type ID. Only entity types that implement
-   *   \Drupal\Core\Entity\ContentEntityInterface are supported
+   *   \Drupal\Core\Entity\ContentEntityInterface are supported.
    *
    * @return \Drupal\Core\Field\FieldDefinitionInterface[]
    *   An array of field definitions, keyed by field name.
@@ -348,8 +358,8 @@ protected function buildBaseFieldDefinitions($entity_type_id) {
     $base_field_definitions = $class::baseFieldDefinitions($entity_type);
     $provider = $entity_type->getProvider();
     foreach ($base_field_definitions as $definition) {
-      // @todo Remove this check one FieldDefinitionInterface exposes a proper
-      //   provider setter. See https://drupal.org/node/2225961.
+      // @todo Remove this check once FieldDefinitionInterface exposes a proper
+      //  provider setter. See https://drupal.org/node/2225961.
       if ($definition instanceof FieldDefinition) {
         $definition->setProvider($provider);
       }
@@ -362,8 +372,8 @@ protected function buildBaseFieldDefinitions($entity_type_id) {
         // Ensure the provider key actually matches the name of the provider
         // defining the field.
         foreach ($module_definitions as $field_name => $definition) {
-          // @todo Remove this check one FieldDefinitionInterface exposes a
-          //   proper provider setter. See https://drupal.org/node/2225961.
+          // @todo Remove this check once FieldDefinitionInterface exposes a
+          //  proper provider setter. See https://drupal.org/node/2225961.
           if ($definition instanceof FieldDefinition) {
             $definition->setProvider($module);
           }
@@ -445,8 +455,8 @@ protected function buildBundleFieldDefinitions($entity_type_id, $bundle, array $
     $bundle_field_definitions = $class::bundleFieldDefinitions($entity_type, $bundle, $base_field_definitions);
     $provider = $entity_type->getProvider();
     foreach ($bundle_field_definitions as $definition) {
-      // @todo Remove this check one FieldDefinitionInterface exposes a proper
-      //   provider setter. See https://drupal.org/node/2225961.
+      // @todo Remove this check once FieldDefinitionInterface exposes a proper
+      //  provider setter. See https://drupal.org/node/2225961.
       if ($definition instanceof FieldDefinition) {
         $definition->setProvider($provider);
       }
@@ -459,8 +469,8 @@ protected function buildBundleFieldDefinitions($entity_type_id, $bundle, array $
         // Ensure the provider key actually matches the name of the provider
         // defining the field.
         foreach ($module_definitions as $field_name => $definition) {
-          // @todo Remove this check one FieldDefinitionInterface exposes a
-          //   proper provider setter. See https://drupal.org/node/2225961.
+          // @todo Remove this check once FieldDefinitionInterface exposes a
+          //  proper provider setter. See https://drupal.org/node/2225961.
           if ($definition instanceof FieldDefinition) {
             $definition->setProvider($module);
           }
@@ -486,9 +496,74 @@ protected function buildBundleFieldDefinitions($entity_type_id, $bundle, array $
   /**
    * {@inheritdoc}
    */
+  public function getFieldStorageDefinitions($entity_type_id) {
+    if (!isset($this->fieldStorageDefinitions[$entity_type_id])) {
+      $this->fieldStorageDefinitions[$entity_type_id] = array();
+      // Add all non-computed base fields.
+      foreach ($this->getBaseFieldDefinitions($entity_type_id) as $field_name => $definition) {
+        if (!$definition->isComputed()) {
+          $this->fieldStorageDefinitions[$entity_type_id][$field_name] = $definition;
+        }
+      }
+      // Not prepared, try to load from cache.
+      $cid = 'entity_field_storage_definitions:' . $entity_type_id . ':' . $this->languageManager->getCurrentLanguage()->id;
+      if ($cache = $this->cache->get($cid)) {
+        $field_storage_definitions = $cache->data;
+      }
+      else {
+        // Rebuild the definitions and put it into the cache.
+        $field_storage_definitions = $this->buildFieldStorageDefinitions($entity_type_id);
+        $this->cache->set($cid, $field_storage_definitions, Cache::PERMANENT, array('entity_types' => TRUE, 'entity_field_info' => TRUE));
+      }
+      $this->fieldStorageDefinitions[$entity_type_id] += $field_storage_definitions;
+    }
+    return $this->fieldStorageDefinitions[$entity_type_id];
+  }
+
+  /**
+   * Builds field storage definitions for an entity type.
+   *
+   * @param string $entity_type_id
+   *   The entity type ID. Only entity types that implement
+   *   \Drupal\Core\Entity\ContentEntityInterface are supported
+   *
+   * @return \Drupal\Core\Field\FieldStorageDefinitionInterface[]
+   *   An array of field storage definitions, keyed by field name.
+   */
+  protected function buildFieldStorageDefinitions($entity_type_id) {
+    $entity_type = $this->getDefinition($entity_type_id);
+    $field_definitions = array();
+
+    // Retrieve base field definitions from modules.
+    foreach ($this->moduleHandler->getImplementations('entity_field_storage_info') as $module) {
+      $module_definitions = $this->moduleHandler->invoke($module, 'entity_field_storage_info', array($entity_type));
+      if (!empty($module_definitions)) {
+        // Ensure the provider key actually matches the name of the provider
+        // defining the field.
+        foreach ($module_definitions as $field_name => $definition) {
+          // @todo Remove this check once FieldDefinitionInterface exposes a
+          //  proper provider setter. See https://drupal.org/node/2225961.
+          if ($definition instanceof FieldDefinition) {
+            $definition->setProvider($module);
+          }
+          $field_definitions[$field_name] = $definition;
+        }
+      }
+    }
+
+    // Invoke alter hook.
+    $this->moduleHandler->alter('entity_field_storage_info', $field_definitions, $entity_type);
+
+    return $field_definitions;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function clearCachedFieldDefinitions() {
     $this->baseFieldDefinitions = array();
     $this->fieldDefinitions = array();
+    $this->fieldStorageDefinitions = array();
     Cache::deleteTags(array('entity_field_info' => TRUE));
   }
 
diff --git a/core/lib/Drupal/Core/Entity/EntityManagerInterface.php b/core/lib/Drupal/Core/Entity/EntityManagerInterface.php
index ce964ab..da36a36 100644
--- a/core/lib/Drupal/Core/Entity/EntityManagerInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityManagerInterface.php
@@ -57,6 +57,26 @@ public function getBaseFieldDefinitions($entity_type_id);
   public function getFieldDefinitions($entity_type_id, $bundle);
 
   /**
+   * Gets the field storage definitions for a content entity type.
+   *
+   * This returns all field storage definitions for base fields and bundle
+   * fields of an entity type. Note that field storage definitions of a base
+   * field equal the full base field definition (i.e. they implement
+   * FieldDefinitionInterface), while the storage definitions for bundle fields
+   * may implement FieldStorageDefinitionInterface only.
+   *
+   * @param string $entity_type_id
+   *   The entity type ID. Only content entities are supported.
+   *
+   * @return \Drupal\Core\Field\FieldStorageDefinitionInterface[]
+   *   The array of field storage definitions for the entity type, keyed by
+   *   field name.
+   *
+   * @see \Drupal\Core\Field\FieldStorageDefinitionInterface
+   */
+  public function getFieldStorageDefinitions($entity_type_id);
+
+  /**
    * Creates a new access controller instance.
    *
    * @param string $entity_type
diff --git a/core/lib/Drupal/Core/Field/FieldDefinition.php b/core/lib/Drupal/Core/Field/FieldDefinition.php
index e5f4734..8d36fba 100644
--- a/core/lib/Drupal/Core/Field/FieldDefinition.php
+++ b/core/lib/Drupal/Core/Field/FieldDefinition.php
@@ -68,6 +68,37 @@ public static function create($type) {
   }
 
   /**
+   * Creates a new field definition based upon a field storage definition.
+   *
+   * In cases where one needs a field storage definitions to act like full
+   * field definitions, this creates a new field definition based upon the
+   * (limited) information available. That way it is possible to use the field
+   * definition in places where a full field definition is required; e.g., with
+   * widgets or formatters.
+   *
+   * @param \Drupal\Core\Field\FieldStorageDefinitionInterface $definition
+   *   The field storage definition to base the new field definition upon.
+   *
+   * @return $this
+   */
+  public static function createFromFieldStorageDefinition(FieldStorageDefinitionInterface $definition) {
+    return static::create($definition->getType())
+      ->setCardinality($definition->getCardinality())
+      ->setConstraints($definition->getConstraints())
+      ->setCustomStorage($definition->hasCustomStorage())
+      ->setDescription($definition->getDescription())
+      ->setLabel($definition->getLabel())
+      ->setName($definition->getName())
+      ->setProvider($definition->getProvider())
+      ->setQueryable($definition->isQueryable())
+      ->setRequired($definition->isRequired())
+      ->setRevisionable($definition->isRevisionable())
+      ->setSettings($definition->getSettings())
+      ->setTargetEntityTypeId($definition->getTargetEntityTypeId())
+      ->setTranslatable($definition->isTranslatable());
+  }
+
+  /**
    * {@inheritdoc}
    */
   public static function createFromItemType($item_type) {
diff --git a/core/lib/Drupal/Core/Field/FieldDefinitionInterface.php b/core/lib/Drupal/Core/Field/FieldDefinitionInterface.php
index 61a879b..83ae5d9 100644
--- a/core/lib/Drupal/Core/Field/FieldDefinitionInterface.php
+++ b/core/lib/Drupal/Core/Field/FieldDefinitionInterface.php
@@ -52,80 +52,7 @@
  * based on that abstract definition, even though that abstract definition can
  * differ from the concrete definition of any particular node's body field.
  */
-interface FieldDefinitionInterface extends ListDataDefinitionInterface {
-
-  /**
-   * Value indicating a field accepts an unlimited number of values.
-   */
-  const CARDINALITY_UNLIMITED = -1;
-
-  /**
-   * Returns the machine name of the field.
-   *
-   * This defines how the field data is accessed from the entity. For example,
-   * if the field name is "foo", then $entity->foo returns its data.
-   *
-   * @return string
-   *   The field name.
-   */
-  public function getName();
-
-  /**
-   * Returns the field type.
-   *
-   * @return string
-   *   The field type, i.e. the id of a field type plugin. For example 'text'.
-   *
-   * @see \Drupal\Core\Field\FieldTypePluginManagerInterface
-   */
-  public function getType();
-
-  /**
-   * Returns the field settings.
-   *
-   * Each field type defines the settings that are meaningful for that type.
-   * For example, a text field can define a 'max_length' setting, and an image
-   * field can define a 'alt_field_required' setting.
-   *
-   * @return array
-   *   An array of key/value pairs.
-   */
-  public function getSettings();
-
-  /**
-   * Returns the value of a given field setting.
-   *
-   * @param string $setting_name
-   *   The setting name.
-   *
-   * @return mixed
-   *   The setting value.
-   */
-  public function getSetting($setting_name);
-
-  /**
-   * Returns the name of the provider of this field.
-   *
-   * @return string
-   *   The provider name; e.g., the module name.
-   */
-  public function getProvider();
-
-  /**
-   * Returns whether the field is translatable.
-   *
-   * @return bool
-   *   TRUE if the field is translatable.
-   */
-  public function isTranslatable();
-
-  /**
-   * Returns whether the field is revisionable.
-   *
-   * @return bool
-   *   TRUE if the field is revisionable.
-   */
-  public function isRevisionable();
+interface FieldDefinitionInterface extends FieldStorageDefinitionInterface, ListDataDefinitionInterface {
 
   /**
    * Returns whether the display for the field can be configured.
@@ -174,45 +101,6 @@ public function isDisplayConfigurable($display_context);
   public function getDisplayOptions($display_context);
 
   /**
-   * Determines whether the field is queryable via QueryInterface.
-   *
-   * @return bool
-   *   TRUE if the field is queryable.
-   */
-  public function isQueryable();
-
-  /**
-   * Returns the human-readable label for the field.
-   *
-   * @return string
-   *   The field label.
-   */
-  public function getLabel();
-
-  /**
-   * Returns the human-readable description for the field.
-   *
-   * This is displayed in addition to the label in places where additional
-   * descriptive information is helpful. For example, as help text below the
-   * form element in entity edit forms.
-   *
-   * @return string|null
-   *   The field description, or NULL if no description is available.
-   */
-  public function getDescription();
-
-  /**
-   * Returns the maximum number of items allowed for the field.
-   *
-   * Possible values are positive integers or
-   * FieldDefinitionInterface::CARDINALITY_UNLIMITED.
-   *
-   * @return integer
-   *   The field cardinality.
-   */
-  public function getCardinality();
-
-  /**
    * Returns whether at least one non-empty item is required for this field.
    *
    * Currently, required-ness is only enforced at the Form API level in entity
@@ -224,14 +112,6 @@ public function getCardinality();
   public function isRequired();
 
   /**
-   * Returns whether the field can contain multiple items.
-   *
-   * @return bool
-   *   TRUE if the field can contain multiple items, FALSE otherwise.
-   */
-  public function isMultiple();
-
-  /**
    * Returns the default value for the field in a newly created entity.
    *
    * @param \Drupal\Core\Entity\EntityInterface $entity
@@ -248,112 +128,4 @@ public function isMultiple();
    */
   public function getDefaultValue(EntityInterface $entity);
 
-  /**
-   * Gets the definition of a contained property.
-   *
-   * @param string $name
-   *   The name of property.
-   *
-   * @return \Drupal\Core\TypedData\DataDefinitionInterface|null
-   *   The definition of the property or NULL if the property does not exist.
-   */
-  public function getPropertyDefinition($name);
-
-  /**
-   * Gets an array of property definitions of contained properties.
-   *
-   * @return \Drupal\Core\TypedData\DataDefinitionInterface[]
-   *   An array of property definitions of contained properties, keyed by
-   *   property name.
-   */
-  public function getPropertyDefinitions();
-
-  /**
-   * Returns the names of the field's subproperties.
-   *
-   * A field is a list of items, and each item can contain one or more
-   * properties. All items for a given field contain the same property names,
-   * but the values can be different for each item.
-   *
-   * For example, an email field might just contain a single 'value' property,
-   * while a link field might contain 'title' and 'url' properties, and a text
-   * field might contain 'value', 'summary', and 'format' properties.
-   *
-   * @return array
-   *   The property names.
-   */
-  public function getPropertyNames();
-
-  /**
-   * Returns the name of the main property, if any.
-   *
-   * Some field items consist mainly of one main property, e.g. the value of a
-   * text field or the @code target_id @endcode of an entity reference. If the
-   * field item has no main property, the method returns NULL.
-   *
-   * @return string|null
-   *   The name of the value property, or NULL if there is none.
-   */
-  public function getMainPropertyName();
-
-  /**
-   * Returns the ID of the type of the entity this field is attached to.
-   *
-   * This method should not be confused with EntityInterface::entityType()
-   * (configurable fields are config entities, and thus implement both
-   * interfaces):
-   *   - FieldDefinitionInterface::getTargetEntityTypeId() answers "as a field,
-   *     which entity type are you attached to?".
-   *   - EntityInterface::getEntityTypeId() answers "as a (config) entity, what
-   *     is your own entity type".
-   *
-   * @return string
-   *   The name of the entity type.
-   */
-  public function getTargetEntityTypeId();
-
-  /**
-   * Returns the field schema.
-   *
-   * Note that this method returns an empty array for computed fields which have
-   * no schema.
-   *
-   * @return array
-   *   The field schema, as an array of key/value pairs in the format returned
-   *   by hook_field_schema():
-   *   - columns: An array of Schema API column specifications, keyed by column
-   *     name. This specifies what comprises a single value for a given field.
-   *     No assumptions should be made on how storage backends internally use
-   *     the original column name to structure their storage.
-   *   - indexes: An array of Schema API index definitions. Some storage
-   *     backends might not support indexes.
-   *   - foreign keys: An array of Schema API foreign key definitions. Note,
-   *     however, that depending on the storage backend specified for the field,
-   *     the field data is not necessarily stored in SQL.
-   */
-  public function getSchema();
-
-  /**
-   * Returns the field columns, as defined in the field schema.
-   *
-   * @return array
-   *   The array of field columns, keyed by column name, in the same format
-   *   returned by getSchema().
-   *
-   * @see \Drupal\Core\Field\FieldDefinitionInterface::getSchema()
-   */
-  public function getColumns();
-
-  /**
-   * Returns the storage behavior for this field.
-   *
-   * Indicates whether the entity type's storage should take care of storing the
-   * field values or whether it is handled separately; e.g. by the
-   * module providing the field.
-   *
-   * @return bool
-   *   FALSE if the storage takes care of storing the field, TRUE otherwise.
-   */
-  public function hasCustomStorage();
-
 }
diff --git a/core/lib/Drupal/Core/Field/FieldItemInterface.php b/core/lib/Drupal/Core/Field/FieldItemInterface.php
index 58d816c..d10790d 100644
--- a/core/lib/Drupal/Core/Field/FieldItemInterface.php
+++ b/core/lib/Drupal/Core/Field/FieldItemInterface.php
@@ -32,7 +32,7 @@
    *
    * @see \Drupal\Core\Field\FieldDefinition
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition);
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition);
 
   /**
    * Returns the name of the main property, if any.
@@ -57,7 +57,7 @@ public static function mainPropertyName();
    *
    * Computed fields having no schema should return an empty array.
    *
-   * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
+   * @param \Drupal\Core\Field\FieldStorageDefinitionInterface $field_definition
    *   The field definition.
    *
    * @return array
@@ -81,7 +81,7 @@ public static function mainPropertyName();
    *     specify another field as related, only existing SQL tables,
    *     such as {taxonomy_term_data}.
    */
-  public static function schema(FieldDefinitionInterface $field_definition);
+  public static function schema(FieldStorageDefinitionInterface $field_definition);
 
   /**
    * Gets the entity that field belongs to.
diff --git a/core/lib/Drupal/Core/Field/FieldStorageDefinitionInterface.php b/core/lib/Drupal/Core/Field/FieldStorageDefinitionInterface.php
new file mode 100644
index 0000000..aa1d90e
--- /dev/null
+++ b/core/lib/Drupal/Core/Field/FieldStorageDefinitionInterface.php
@@ -0,0 +1,288 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Field\FieldStorageDefinitionInterface.
+ */
+
+namespace Drupal\Core\Field;
+
+/**
+ * Defines an interface for entity field storage definitions.
+ *
+ * Field storage definitions represent the part of full field definitions (see
+ * FieldDefinitionInterface) that is responsible for defining how the field is
+ * stored. While field definitions may differ by entity bundle, all of those
+ * bundle fields have to share the same common field storage definition. Thus,
+ * the storage definitions can be defined by entity type only.
+ * The bundle fields corresponding to a field storage definition may provide
+ * additional information; e.g., they may provide bundle-specific settings or
+ * constraints that are not present in the storage definition. However bundle
+ * fields may not override or alter any information provided by the storage
+ * definition except for the label and the description; e.g., any constraints
+ * and settings on the storage definition must be present on the bundle field as
+ * well.
+ *
+ * @see hook_entity_field_storage_info()
+ */
+interface FieldStorageDefinitionInterface {
+
+  /**
+   * Value indicating a field accepts an unlimited number of values.
+   */
+  const CARDINALITY_UNLIMITED = -1;
+
+  /**
+   * Returns the machine name of the field.
+   *
+   * This defines how the field data is accessed from the entity. For example,
+   * if the field name is "foo", then $entity->foo returns its data.
+   *
+   * @return string
+   *   The field name.
+   */
+  public function getName();
+
+  /**
+   * Returns the field type.
+   *
+   * @return string
+   *   The field type, i.e. the id of a field type plugin. For example 'text'.
+   *
+   * @see \Drupal\Core\Field\FieldTypePluginManagerInterface
+   */
+  public function getType();
+
+  /**
+   * Returns the field settings.
+   *
+   * Each field type defines the settings that are meaningful for that type.
+   * For example, a text field can define a 'max_length' setting, and an image
+   * field can define a 'alt_field_required' setting.
+   *
+   * @return mixed[]
+   *   An array of key/value pairs.
+   */
+  public function getSettings();
+
+  /**
+   * Returns the value of a given field setting.
+   *
+   * @param string $setting_name
+   *   The setting name.
+   *
+   * @return mixed
+   *   The setting value.
+   */
+  public function getSetting($setting_name);
+
+  /**
+   * Returns whether the field is translatable.
+   *
+   * @return bool
+   *   TRUE if the field is translatable.
+   */
+  public function isTranslatable();
+
+  /**
+   * Returns whether the field is revisionable.
+   *
+   * @return bool
+   *   TRUE if the field is revisionable.
+   */
+  public function isRevisionable();
+
+  /**
+   * Determines whether the field is queryable via QueryInterface.
+   *
+   * @return bool
+   *   TRUE if the field is queryable.
+   */
+  public function isQueryable();
+
+  /**
+   * Returns the human-readable label for the field.
+   *
+   * @return string
+   *   The field label.
+   */
+  public function getLabel();
+
+  /**
+   * Returns the human-readable description for the field.
+   *
+   * This is displayed in addition to the label in places where additional
+   * descriptive information is helpful. For example, as help text below the
+   * form element in entity edit forms.
+   *
+   * @return string|null
+   *   The field description, or NULL if no description is available.
+   */
+  public function getDescription();
+
+  /**
+   * Returns whether the field can contain multiple items.
+   *
+   * @return bool
+   *   TRUE if the field can contain multiple items, FALSE otherwise.
+   */
+  public function isMultiple();
+
+  /**
+   * Returns the maximum number of items allowed for the field.
+   *
+   * Possible values are positive integers or
+   * FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED.
+   *
+   * @return int
+   *   The field cardinality.
+   */
+  public function getCardinality();
+
+  /**
+   * Gets the definition of a contained property.
+   *
+   * @param string $name
+   *   The name of property.
+   *
+   * @return \Drupal\Core\TypedData\DataDefinitionInterface|null
+   *   The definition of the property or NULL if the property does not exist.
+   */
+  public function getPropertyDefinition($name);
+
+  /**
+   * Gets an array of property definitions of contained properties.
+   *
+   * @return \Drupal\Core\TypedData\DataDefinitionInterface[]
+   *   An array of property definitions of contained properties, keyed by
+   *   property name.
+   */
+  public function getPropertyDefinitions();
+
+  /**
+   * Returns the names of the field's subproperties.
+   *
+   * A field is a list of items, and each item can contain one or more
+   * properties. All items for a given field contain the same property names,
+   * but the values can be different for each item.
+   *
+   * For example, an email field might just contain a single 'value' property,
+   * while a link field might contain 'title' and 'url' properties, and a text
+   * field might contain 'value', 'summary', and 'format' properties.
+   *
+   * @return string[]
+   *   The property names.
+   */
+  public function getPropertyNames();
+
+  /**
+   * Returns the name of the main property, if any.
+   *
+   * Some field items consist mainly of one main property, e.g. the value of a
+   * text field or the @code target_id @endcode of an entity reference. If the
+   * field item has no main property, the method returns NULL.
+   *
+   * @return string|null
+   *   The name of the value property, or NULL if there is none.
+   */
+  public function getMainPropertyName();
+
+  /**
+   * Returns the ID of the type of the entity this field is attached to.
+   *
+   * This method should not be confused with EntityInterface::entityType()
+   * (configurable fields are config entities, and thus implement both
+   * interfaces):
+   *   - FieldDefinitionInterface::getTargetEntityTypeId() answers "as a field,
+   *     which entity type are you attached to?".
+   *   - EntityInterface::getEntityTypeId() answers "as a (config) entity, what
+   *     is your own entity type".
+   *
+   * @return string
+   *   The name of the entity type.
+   */
+  public function getTargetEntityTypeId();
+
+  /**
+   * Returns the field schema.
+   *
+   * Note that this method returns an empty array for computed fields which have
+   * no schema.
+   *
+   * @return array[]
+   *   The field schema, as an array of key/value pairs in the format returned
+   *   by hook_field_schema():
+   *   - columns: An array of Schema API column specifications, keyed by column
+   *     name. This specifies what comprises a single value for a given field.
+   *     No assumptions should be made on how storage backends internally use
+   *     the original column name to structure their storage.
+   *   - indexes: An array of Schema API index definitions. Some storage
+   *     backends might not support indexes.
+   *   - foreign keys: An array of Schema API foreign key definitions. Note,
+   *     however, that depending on the storage backend specified for the field,
+   *     the field data is not necessarily stored in SQL.
+   */
+  public function getSchema();
+
+  /**
+   * Returns the field columns, as defined in the field schema.
+   *
+   * @return array[]
+   *   The array of field columns, keyed by column name, in the same format
+   *   returned by getSchema().
+   *
+   * @see \Drupal\Core\Field\FieldDefinitionInterface::getSchema()
+   */
+  public function getColumns();
+
+  /**
+   * Returns an array of validation constraints.
+   *
+   * See \Drupal\Core\TypedData\TypedDataManager::getConstraints() for details.
+   *
+   * @return array[]
+   *   An array of validation constraint definitions, keyed by constraint name.
+   *   Each constraint definition can be used for instantiating
+   *   \Symfony\Component\Validator\Constraint objects.
+   *
+   * @see \Symfony\Component\Validator\Constraint
+   */
+  public function getConstraints();
+
+  /**
+   * Returns a validation constraint.
+   *
+   * See \Drupal\Core\TypedData\TypedDataManager::getConstraints() for details.
+   *
+   * @param string $constraint_name
+   *   The name of the the constraint, i.e. its plugin id.
+   *
+   * @return array
+   *   A validation constraint definition which can be used for instantiating a
+   *   \Symfony\Component\Validator\Constraint object.
+   *
+   * @see \Symfony\Component\Validator\Constraint
+   */
+  public function getConstraint($constraint_name);
+
+  /**
+   * Returns the name of the provider of this field.
+   *
+   * @return string
+   *   The provider name; e.g., the module name.
+   */
+  public function getProvider();
+
+  /**
+   * Returns the storage behavior for this field.
+   *
+   * Indicates whether the entity type's storage should take care of storing the
+   * field values or whether it is handled separately; e.g. by the
+   * module providing the field.
+   *
+   * @return bool
+   *   FALSE if the storage takes care of storing the field, TRUE otherwise.
+   */
+  public function hasCustomStorage();
+
+}
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/BooleanItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/BooleanItem.php
index d674e75..14d0f83 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/BooleanItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/BooleanItem.php
@@ -7,8 +7,8 @@
 
 namespace Drupal\Core\Field\Plugin\Field\FieldType;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
 use Drupal\Core\Field\FieldItemBase;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\TypedData\DataDefinition;
 
 /**
@@ -26,7 +26,7 @@ class BooleanItem extends FieldItemBase {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $properties['value'] = DataDefinition::create('boolean')
       ->setLabel(t('Boolean value'));
 
@@ -36,7 +36,7 @@ public static function propertyDefinitions(FieldDefinitionInterface $field_defin
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     return array(
       'columns' => array(
         'value' => array(
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/DateItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/DateItem.php
index 7267da0..c93d494 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/DateItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/DateItem.php
@@ -7,8 +7,8 @@
 
 namespace Drupal\Core\Field\Plugin\Field\FieldType;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
 use Drupal\Core\Field\FieldItemBase;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\TypedData\DataDefinition;
 
 /**
@@ -26,7 +26,7 @@ class DateItem extends FieldItemBase {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $properties['value'] = DataDefinition::create('date')
       ->setLabel(t('Date value'));
 
@@ -36,7 +36,7 @@ public static function propertyDefinitions(FieldDefinitionInterface $field_defin
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     return array(
       'columns' => array(
         'value' => array(
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/DecimalItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/DecimalItem.php
index cbb79d8..30d33c5 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/DecimalItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/DecimalItem.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core\Field\Plugin\Field\FieldType;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\TypedData\DataDefinition;
 
 /**
@@ -35,8 +35,9 @@ public static function defaultSettings() {
 
   /**
    * {@inheritdoc}
+
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $properties['value'] = DataDefinition::create('string')
       ->setLabel(t('Decimal value'));
 
@@ -46,7 +47,7 @@ public static function propertyDefinitions(FieldDefinitionInterface $field_defin
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     return array(
       'columns' => array(
         'value' => array(
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EmailItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EmailItem.php
index 4061b12..6e84507 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EmailItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EmailItem.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core\Field\Plugin\Field\FieldType;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\Field\FieldItemBase;
 use Drupal\Core\TypedData\DataDefinition;
 
@@ -27,7 +27,7 @@ class EmailItem extends FieldItemBase {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $properties['value'] = DataDefinition::create('email')
       ->setLabel(t('E-mail value'));
 
@@ -37,7 +37,7 @@ public static function propertyDefinitions(FieldDefinitionInterface $field_defin
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     return array(
       'columns' => array(
         'value' => array(
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
index 4ad8849..1697c16 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
@@ -8,7 +8,7 @@
 namespace Drupal\Core\Field\Plugin\Field\FieldType;
 
 use Drupal\Core\Entity\TypedData\EntityDataDefinition;
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\Field\FieldItemBase;
 use Drupal\Core\TypedData\DataDefinition;
 use Drupal\Core\TypedData\DataReferenceDefinition;
@@ -54,7 +54,7 @@ public static function defaultInstanceSettings() {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $settings = $field_definition->getSettings();
     $target_type_info = \Drupal::entityManager()->getDefinition($settings['target_type']);
 
@@ -95,7 +95,7 @@ public static function mainPropertyName() {
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     $target_type = $field_definition->getSetting('target_type');
     $target_type_info = \Drupal::entityManager()->getDefinition($target_type);
 
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/FloatItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/FloatItem.php
index eda49cc..a78ebdb 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/FloatItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/FloatItem.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core\Field\Plugin\Field\FieldType;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\TypedData\DataDefinition;
 
 /**
@@ -26,7 +26,7 @@ class FloatItem extends NumericItemBase {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $properties['value'] = DataDefinition::create('float')
       ->setLabel(t('Float value'));
 
@@ -36,7 +36,7 @@ public static function propertyDefinitions(FieldDefinitionInterface $field_defin
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     return array(
       'columns' => array(
         'value' => array(
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/IntegerItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/IntegerItem.php
index 760a225..2bafa8b 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/IntegerItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/IntegerItem.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core\Field\Plugin\Field\FieldType;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\TypedData\DataDefinition;
 
 /**
@@ -47,7 +47,7 @@ public static function defaultInstanceSettings() {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $properties['value'] = DataDefinition::create('integer')
       ->setLabel(t('Integer value'));
 
@@ -83,7 +83,7 @@ public function getConstraints() {
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     return array(
       'columns' => array(
         'value' => array(
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/LanguageItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/LanguageItem.php
index 9519b8d..e3192b2 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/LanguageItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/LanguageItem.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core\Field\Plugin\Field\FieldType;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\Field\FieldItemBase;
 use Drupal\Core\Language\Language;
 use Drupal\Core\TypedData\DataDefinition;
@@ -33,7 +33,7 @@ class LanguageItem extends FieldItemBase {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $properties['value'] = DataDefinition::create('string')
       ->setLabel(t('Language code'));
 
@@ -50,7 +50,7 @@ public static function propertyDefinitions(FieldDefinitionInterface $field_defin
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     return array(
       'columns' => array(
         'value' => array(
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/MapItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/MapItem.php
index 7b78006..26cdc41 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/MapItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/MapItem.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core\Field\Plugin\Field\FieldType;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\Field\FieldItemBase;
 use Drupal\Core\TypedData\DataDefinition;
 
@@ -26,7 +26,7 @@ class MapItem extends FieldItemBase {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $properties['value'] = DataDefinition::create('string')
       ->setLabel(t('Serialized values'));
 
@@ -36,7 +36,7 @@ public static function propertyDefinitions(FieldDefinitionInterface $field_defin
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     return array(
       'columns' => array(
         'value' => array(
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/StringItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/StringItem.php
index 1dfd9f4..fe7c4f4 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/StringItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/StringItem.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core\Field\Plugin\Field\FieldType;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\Field\FieldItemBase;
 use Drupal\Core\TypedData\DataDefinition;
 
@@ -37,7 +37,7 @@ public static function defaultSettings() {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $properties['value'] = DataDefinition::create('string')
       ->setLabel(t('Text value'));
 
@@ -47,7 +47,7 @@ public static function propertyDefinitions(FieldDefinitionInterface $field_defin
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     return array(
       'columns' => array(
         'value' => array(
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/StringLongItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/StringLongItem.php
index c8b1575..6337c12 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/StringLongItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/StringLongItem.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core\Field\Plugin\Field\FieldType;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 
 /**
  * Defines the 'string_long' field type.
@@ -24,7 +24,7 @@ class StringLongItem extends StringItem {
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     return array(
       'columns' => array(
         'value' => array(
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/TimestampItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/TimestampItem.php
index a2d87a6..ba432e3 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/TimestampItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/TimestampItem.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core\Field\Plugin\Field\FieldType;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\Field\FieldItemBase;
 use Drupal\Core\TypedData\DataDefinition;
 
@@ -26,7 +26,7 @@ class TimestampItem extends FieldItemBase {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $properties['value'] = DataDefinition::create('timestamp')
       ->setLabel(t('Timestamp value'));
     return $properties;
@@ -35,7 +35,7 @@ public static function propertyDefinitions(FieldDefinitionInterface $field_defin
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     return array(
       'columns' => array(
         'value' => array(
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/UriItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/UriItem.php
index d74a85a..693e4ce 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/UriItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/UriItem.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core\Field\Plugin\Field\FieldType;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\TypedData\DataDefinition;
 
 /**
@@ -38,7 +38,7 @@ public static function defaultSettings() {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $properties['value'] = DataDefinition::create('uri')
       ->setLabel(t('URI value'));
 
@@ -48,7 +48,7 @@ public static function propertyDefinitions(FieldDefinitionInterface $field_defin
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     return array(
       'columns' => array(
         'value' => array(
diff --git a/core/modules/comment/lib/Drupal/comment/CommentFieldNameItem.php b/core/modules/comment/lib/Drupal/comment/CommentFieldNameItem.php
index 0f6eae2..94b8587 100644
--- a/core/modules/comment/lib/Drupal/comment/CommentFieldNameItem.php
+++ b/core/modules/comment/lib/Drupal/comment/CommentFieldNameItem.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\comment;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\Field\Plugin\Field\FieldType\StringItem;
 use Drupal\Core\TypedData\DataDefinition;
 
@@ -19,7 +19,7 @@ class CommentFieldNameItem extends StringItem {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $properties['value'] = DataDefinition::create('string')
       ->setLabel(t('String value'))
       ->setClass('\Drupal\comment\CommentFieldNameValue')
diff --git a/core/modules/comment/lib/Drupal/comment/Plugin/Field/FieldType/CommentItem.php b/core/modules/comment/lib/Drupal/comment/Plugin/Field/FieldType/CommentItem.php
index 78bdf82..dd6e7e8 100644
--- a/core/modules/comment/lib/Drupal/comment/Plugin/Field/FieldType/CommentItem.php
+++ b/core/modules/comment/lib/Drupal/comment/Plugin/Field/FieldType/CommentItem.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\comment\Plugin\Field\FieldType;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\TypedData\DataDefinition;
 use Drupal\Core\Field\FieldItemBase;
 use Drupal\Core\Session\AnonymousUserSession;
@@ -51,7 +51,7 @@ public static function defaultInstanceSettings() {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $properties['status'] = DataDefinition::create('integer')
       ->setLabel(t('Comment status value'));
 
@@ -79,7 +79,7 @@ public static function propertyDefinitions(FieldDefinitionInterface $field_defin
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     return array(
       'columns' => array(
         'status' => array(
diff --git a/core/modules/content_translation/content_translation.module b/core/modules/content_translation/content_translation.module
index d7204a5..38b5b41 100644
--- a/core/modules/content_translation/content_translation.module
+++ b/core/modules/content_translation/content_translation.module
@@ -682,9 +682,9 @@ function content_translation_form_field_ui_field_edit_form_submit($form, array &
  * Implements hook_form_FORM_ID_alter() for 'field_ui_field_instance_edit_form'.
  */
 function content_translation_form_field_ui_field_instance_edit_form_alter(array &$form, array &$form_state, $form_id) {
-  if ($form['#field']->isTranslatable()) {
+  if ($form_state['instance']->isTranslatable()) {
     module_load_include('inc', 'content_translation', 'content_translation.admin');
-    $element = content_translation_field_sync_widget($form['#field']);
+    $element = content_translation_field_sync_widget($form_state['instance']);
     if ($element) {
       $form['instance']['settings']['translation_sync'] = $element;
     }
diff --git a/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldType/DateTimeItem.php b/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldType/DateTimeItem.php
index 6b6adef..d347815 100644
--- a/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldType/DateTimeItem.php
+++ b/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldType/DateTimeItem.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\datetime\Plugin\Field\FieldType;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\Field\PrepareCacheInterface;
 use Drupal\Core\TypedData\DataDefinition;
 use Drupal\Core\Field\FieldItemBase;
@@ -48,7 +48,7 @@ public static function defaultSettings() {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $properties['value'] = DataDefinition::create('datetime_iso8601')
       ->setLabel(t('Date value'));
 
@@ -65,7 +65,7 @@ public static function propertyDefinitions(FieldDefinitionInterface $field_defin
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     return array(
       'columns' => array(
         'value' => array(
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/ConfigurableEntityReferenceItem.php b/core/modules/entity_reference/lib/Drupal/entity_reference/ConfigurableEntityReferenceItem.php
index 372f2f8..dc4816d 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/ConfigurableEntityReferenceItem.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/ConfigurableEntityReferenceItem.php
@@ -8,7 +8,7 @@
 namespace Drupal\entity_reference;
 
 use Drupal\Component\Utility\String;
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\TypedData\AllowedValuesInterface;
@@ -98,7 +98,7 @@ public function getSettableOptions(AccountInterface $account = NULL) {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $settings = $field_definition->getSettings();
     $target_type = $settings['target_type'];
 
@@ -137,7 +137,7 @@ public function getConstraints() {
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     $schema = parent::schema($field_definition);
 
     $target_type = $field_definition->getSetting('target_type');
diff --git a/core/modules/field/field.module b/core/modules/field/field.module
index 4c73352..029db41 100644
--- a/core/modules/field/field.module
+++ b/core/modules/field/field.module
@@ -174,6 +174,28 @@ function field_system_info_alter(&$info, Extension $file, $type) {
 }
 
 /**
+ * Implements hook_entity_field_storage_info().
+ */
+function field_entity_field_storage_info(\Drupal\Core\Entity\EntityTypeInterface $entity_type) {
+  // Expose storage definitions for all exposed bundle fields.
+  if ($entity_type->isFieldable()) {
+    // Query by filtering on the ID as this is more efficient than filtering
+    // on the entity_type property directly.
+    $ids = \Drupal::entityQuery('field_config')
+      ->condition('id', $entity_type->id() . '.', 'STARTS_WITH')
+      ->execute();
+
+    // Fetch all fields and key them by field name.
+    $field_configs = entity_load_multiple('field_config', $ids);
+    $result = array();
+    foreach ($field_configs as $field_config) {
+      $result[$field_config->getName()] = $field_config;
+    }
+    return $result;
+  }
+}
+
+/**
  * Implements hook_entity_bundle_field_info().
  */
 function field_entity_bundle_field_info(EntityTypeInterface $entity_type, $bundle, array $base_field_definitions) {
diff --git a/core/modules/field/lib/Drupal/field/Entity/FieldConfig.php b/core/modules/field/lib/Drupal/field/Entity/FieldConfig.php
index be31562..da29536 100644
--- a/core/modules/field/lib/Drupal/field/Entity/FieldConfig.php
+++ b/core/modules/field/lib/Drupal/field/Entity/FieldConfig.php
@@ -9,10 +9,8 @@
 
 use Drupal\Component\Utility\Unicode;
 use Drupal\Core\Config\Entity\ConfigEntityBase;
-use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityStorageInterface;
-use Drupal\Core\Field\FieldDefinition;
-use Drupal\Core\Field\TypedData\FieldItemDataDefinition;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\field\FieldException;
 use Drupal\field\FieldConfigInterface;
 
@@ -102,10 +100,10 @@ class FieldConfig extends ConfigEntityBase implements FieldConfigInterface {
    * The field cardinality.
    *
    * The maximum number of values the field can hold. Possible values are
-   * positive integers or FieldDefinitionInterface::CARDINALITY_UNLIMITED.
-   * Defaults to 1.
+   * positive integers or
+   * FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED. Defaults to 1.
    *
-   * @var integer
+   * @var int
    */
   public $cardinality = 1;
 
@@ -182,13 +180,6 @@ class FieldConfig extends ConfigEntityBase implements FieldConfigInterface {
   protected $propertyDefinitions;
 
   /**
-   * The data definition of a field item.
-   *
-   * @var \Drupal\Core\TypedData\DataDefinition
-   */
-  protected $itemDefinition;
-
-  /**
    * Constructs a FieldConfig object.
    *
    * @param array $values
@@ -539,8 +530,7 @@ public function getSettings() {
     $field_type_manager = \Drupal::service('plugin.manager.field.field_type');
 
     $settings = $field_type_manager->getDefaultSettings($this->type);
-    $instance_settings = $field_type_manager->getDefaultInstanceSettings($this->type);
-    return $this->settings + $settings + $instance_settings;
+    return $this->settings + $settings;
   }
 
   /**
@@ -630,7 +620,7 @@ public function isRequired() {
    */
   public function isMultiple() {
     $cardinality = $this->getCardinality();
-    return ($cardinality == static::CARDINALITY_UNLIMITED) || ($cardinality > 1);
+    return ($cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) || ($cardinality > 1);
   }
 
   /**
@@ -643,26 +633,6 @@ public function isLocked() {
   /**
    * {@inheritdoc}
    */
-  public function getDefaultValue(EntityInterface $entity) { }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function isDisplayConfigurable($context) {
-    return TRUE;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getDisplayOptions($display_context) {
-    // Hide configurable fields by default.
-    return array('type' => 'hidden');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public function getTargetEntityTypeId() {
     return $this->entity_type;
   }
@@ -742,62 +712,6 @@ public function __wakeup() {
   /**
    * {@inheritdoc}
    */
-  public static function createFromDataType($type) {
-    // Forward to the field definition class for creating new data definitions
-    // via the typed manager.
-    return FieldDefinition::createFromDataType($type);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function createFromItemType($item_type) {
-    // Forward to the field definition class for creating new data definitions
-    // via the typed manager.
-    return FieldDefinition::createFromItemType($item_type);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getDataType() {
-    return 'list';
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function isList() {
-    return TRUE;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function isReadOnly() {
-    return FALSE;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function isComputed() {
-    return FALSE;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getClass() {
-    // Derive list class from the field type.
-    $type_definition = \Drupal::service('plugin.manager.field.field_type')
-      ->getDefinition($this->getType());
-    return $type_definition['list_class'];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public function getConstraints() {
     return array();
   }
@@ -812,17 +726,6 @@ public function getConstraint($constraint_name) {
   /**
    * {@inheritdoc}
    */
-  public function getItemDefinition() {
-    if (!isset($this->itemDefinition)) {
-      $this->itemDefinition = FieldItemDataDefinition::create($this)
-        ->setSettings($this->getSettings());
-    }
-    return $this->itemDefinition;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public function getPropertyDefinition($name) {
     if (!isset($this->propertyDefinitions)) {
       $this->getPropertyDefinitions();
@@ -860,19 +763,11 @@ public function getMainPropertyName() {
 
   /**
    * Helper to retrieve the field item class.
-   *
-   * @todo: Remove once getClass() adds in defaults. See
-   * https://drupal.org/node/2116341.
    */
   protected function getFieldItemClass() {
-    if ($class = $this->getItemDefinition()->getClass()) {
-      return $class;
-    }
-    else {
-      $type_definition = \Drupal::typedDataManager()
-        ->getDefinition($this->getItemDefinition()->getDataType());
-      return $type_definition['class'];
-    }
+    $type_definition = \Drupal::typedDataManager()
+      ->getDefinition('field_item:' . $this->getType());
+    return $type_definition['class'];
   }
 
 }
diff --git a/core/modules/field/lib/Drupal/field/Entity/FieldInstanceConfig.php b/core/modules/field/lib/Drupal/field/Entity/FieldInstanceConfig.php
index 437c81d..ff6217d 100644
--- a/core/modules/field/lib/Drupal/field/Entity/FieldInstanceConfig.php
+++ b/core/modules/field/lib/Drupal/field/Entity/FieldInstanceConfig.php
@@ -721,7 +721,10 @@ public function isComputed() {
    * {@inheritdoc}
    */
   public function getClass() {
-    return $this->field->getClass();
+    // Derive list class from the field type.
+    $type_definition = \Drupal::service('plugin.manager.field.field_type')
+      ->getDefinition($this->getType());
+    return $type_definition['list_class'];
   }
 
   /**
diff --git a/core/modules/field/lib/Drupal/field/FieldConfigInterface.php b/core/modules/field/lib/Drupal/field/FieldConfigInterface.php
index 1b63629..c6575ec 100644
--- a/core/modules/field/lib/Drupal/field/FieldConfigInterface.php
+++ b/core/modules/field/lib/Drupal/field/FieldConfigInterface.php
@@ -8,12 +8,12 @@
 namespace Drupal\field;
 
 use Drupal\Core\Config\Entity\ConfigEntityInterface;
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 
 /**
  * Provides an interface defining a field entity.
  */
-interface FieldConfigInterface extends ConfigEntityInterface, FieldDefinitionInterface {
+interface FieldConfigInterface extends ConfigEntityInterface, FieldStorageDefinitionInterface {
 
   /**
    * Returns the list of bundles where the field has instances.
diff --git a/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php b/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php
index 2628dfa..030bd50 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php
@@ -10,6 +10,7 @@
 use Drupal\Component\Utility\Xss;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\Core\Field\FieldDefinition;
 use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\Core\Render\Element;
 use Drupal\field\Field as FieldHelper;
@@ -42,9 +43,13 @@ class Field extends FieldPluginBase {
   public $items = array();
 
   /**
-   * The field information as returned by field_info_field().
+   * The field definition to use.
    *
-   * @var \Drupal\field\FieldConfigInterface
+   * A field storage definition turned into a field definition, so it can be
+   * used with widgets and formatters. See
+   * FieldDefinition::createFromFieldStorageDefinition().
+   *
+   * @var \Drupal\Core\Field\FieldDefinitionInterface
    */
   public $field_info;
 
@@ -141,7 +146,8 @@ public static function create(ContainerInterface $container, array $configuratio
   public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
     parent::init($view, $display, $options);
 
-    $this->field_info = FieldHelper::fieldInfo()->getField($this->definition['entity_type'], $this->definition['field_name']);
+    $field_storage_definition = FieldHelper::fieldInfo()->getField($this->definition['entity_type'], $this->definition['field_name']);
+    $this->field_info = FieldDefinition::createFromFieldStorageDefinition($field_storage_definition);
     $this->multiple = FALSE;
     $this->limit_values = FALSE;
 
diff --git a/core/modules/field/lib/Drupal/field/Tests/ConfigFieldDefinitionTest.php b/core/modules/field/lib/Drupal/field/Tests/ConfigFieldDefinitionTest.php
new file mode 100644
index 0000000..d1b712c
--- /dev/null
+++ b/core/modules/field/lib/Drupal/field/Tests/ConfigFieldDefinitionTest.php
@@ -0,0 +1,75 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\field\Tests\ConfigFieldDefinitionTest.
+ */
+
+namespace Drupal\field\Tests;
+
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
+
+/**
+ * Tests exposing field definitions for configurable fields.
+ */
+class ConfigFieldDefinitionTest extends FieldUnitTestBase {
+
+  /**
+   * The entity manager service.
+   *
+   * @var \Drupal\Core\Entity\EntityManagerInterface;
+   */
+  protected $entityManager;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Config field definitions',
+      'description' => 'Tests exposing field definitions for configurable fields.',
+      'group' => 'Field API',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+
+    // Create a field and instance of type 'test_field', on the 'entity_test'
+    // entity type.
+    $this->entityType = 'entity_test';
+    $this->bundle = 'entity_test';
+    $this->createFieldWithInstance('', $this->entityType, $this->bundle);
+    $this->entityManager = $this->container->get('entity.manager');
+
+    // Create a second instance on 'entity_test_rev'.
+    $this->createFieldWithInstance('_rev', 'entity_test_rev', 'entity_test_rev');
+  }
+
+  /**
+   * Makes sure a field definition is exposed for a configurable field.
+   */
+  public function testBundleFieldDefinition() {
+    $definitions = $this->entityManager->getFieldDefinitions($this->entityType, $this->bundle);
+    $this->assertTrue(isset($definitions[$this->instance->getName()]));
+    $this->assertTrue($definitions[$this->instance->getName()] instanceof FieldStorageDefinitionInterface);
+    // Make sure no field for the instance on another entity type is exposed.
+    $this->assertFalse(isset($definitions[$this->instance_rev->getName()]));
+  }
+
+  /**
+   * Makes sure a field storage definition is exposed for a configurable field.
+   */
+  public function testFieldStorageDefinition() {
+    $storage_definitions = $this->entityManager->getFieldStorageDefinitions($this->entityType);
+    $this->assertTrue(isset($storage_definitions[$this->instance->getName()]));
+    $this->assertTrue($storage_definitions[$this->instance->getName()] instanceof FieldStorageDefinitionInterface);
+    // Make sure no storage field for the instance on another entity type is
+    // exposed.
+    $this->assertFalse(isset($storage_definitions[$this->instance_rev->getName()]));
+  }
+
+}
diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/HiddenTestItem.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/HiddenTestItem.php
index 700efde..b145abe 100644
--- a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/HiddenTestItem.php
+++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/HiddenTestItem.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\field_test\Plugin\Field\FieldType;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\TypedData\DataDefinition;
 
 /**
@@ -27,7 +27,7 @@ class HiddenTestItem extends TestItem {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $properties['value'] = DataDefinition::create('integer')
       ->setLabel(t('Test integer value'));
 
diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/ShapeItem.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/ShapeItem.php
index 58985b8..87a7f31 100644
--- a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/ShapeItem.php
+++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/ShapeItem.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\field_test\Plugin\Field\FieldType;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\TypedData\DataDefinition;
 use Drupal\Core\Field\FieldItemBase;
 
@@ -36,7 +36,7 @@ public static function defaultSettings() {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $properties['shape'] = DataDefinition::create('string')
       ->setLabel(t('Shape'));
 
@@ -49,7 +49,7 @@ public static function propertyDefinitions(FieldDefinitionInterface $field_defin
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     $foreign_keys = array();
     // The 'foreign keys' key is not always used in tests.
     if ($field_definition->getSetting('foreign_key_name')) {
diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/TestItem.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/TestItem.php
index b3326ef..fcc599c 100644
--- a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/TestItem.php
+++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/TestItem.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\field_test\Plugin\Field\FieldType;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\Field\PrepareCacheInterface;
 use Drupal\Core\TypedData\DataDefinition;
 use Drupal\Core\Field\FieldItemBase;
@@ -49,7 +49,7 @@ public static function defaultInstanceSettings() {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $properties['value'] = DataDefinition::create('integer')
       ->setLabel(t('Test integer value'));
 
@@ -59,7 +59,7 @@ public static function propertyDefinitions(FieldDefinitionInterface $field_defin
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     return array(
       'columns' => array(
         'value' => array(
diff --git a/core/modules/file/lib/Drupal/file/Plugin/Field/FieldType/FileItem.php b/core/modules/file/lib/Drupal/file/Plugin/Field/FieldType/FileItem.php
index 7e66420..16ada1e 100644
--- a/core/modules/file/lib/Drupal/file/Plugin/Field/FieldType/FileItem.php
+++ b/core/modules/file/lib/Drupal/file/Plugin/Field/FieldType/FileItem.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\file\Plugin\Field\FieldType;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
 use Drupal\Core\TypedData\DataDefinition;
 
@@ -52,7 +52,7 @@ public static function defaultInstanceSettings() {
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     return array(
       'columns' => array(
         'target_id' => array(
@@ -90,7 +90,7 @@ public static function schema(FieldDefinitionInterface $field_definition) {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $properties = parent::propertyDefinitions($field_definition);
 
     $properties['display'] = DataDefinition::create('boolean')
diff --git a/core/modules/image/lib/Drupal/image/Plugin/Field/FieldType/ImageItem.php b/core/modules/image/lib/Drupal/image/Plugin/Field/FieldType/ImageItem.php
index 3ea3d84..249933e 100644
--- a/core/modules/image/lib/Drupal/image/Plugin/Field/FieldType/ImageItem.php
+++ b/core/modules/image/lib/Drupal/image/Plugin/Field/FieldType/ImageItem.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\image\Plugin\Field\FieldType;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\TypedData\DataDefinition;
 use Drupal\file\Plugin\Field\FieldType\FileItem;
 
@@ -84,7 +84,7 @@ public static function defaultInstanceSettings() {
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     return array(
       'columns' => array(
         'target_id' => array(
@@ -131,7 +131,7 @@ public static function schema(FieldDefinitionInterface $field_definition) {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $properties = parent::propertyDefinitions($field_definition);
 
     $properties['alt'] = DataDefinition::create('string')
diff --git a/core/modules/link/lib/Drupal/link/Plugin/Field/FieldType/LinkItem.php b/core/modules/link/lib/Drupal/link/Plugin/Field/FieldType/LinkItem.php
index 323987f..850c19e 100644
--- a/core/modules/link/lib/Drupal/link/Plugin/Field/FieldType/LinkItem.php
+++ b/core/modules/link/lib/Drupal/link/Plugin/Field/FieldType/LinkItem.php
@@ -8,7 +8,7 @@
 namespace Drupal\link\Plugin\Field\FieldType;
 
 use Drupal\Core\Field\FieldItemBase;
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\TypedData\DataDefinition;
 use Drupal\Core\TypedData\MapDataDefinition;
 use Drupal\link\LinkItemInterface;
@@ -40,7 +40,7 @@ public static function defaultInstanceSettings() {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $properties['url'] = DataDefinition::create('string')
       ->setLabel(t('URL'));
 
@@ -62,7 +62,7 @@ public static function propertyDefinitions(FieldDefinitionInterface $field_defin
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     return array(
       'columns' => array(
         'url' => array(
diff --git a/core/modules/options/lib/Drupal/options/Plugin/Field/FieldType/ListBooleanItem.php b/core/modules/options/lib/Drupal/options/Plugin/Field/FieldType/ListBooleanItem.php
index 76de3b7..095c89c 100644
--- a/core/modules/options/lib/Drupal/options/Plugin/Field/FieldType/ListBooleanItem.php
+++ b/core/modules/options/lib/Drupal/options/Plugin/Field/FieldType/ListBooleanItem.php
@@ -8,7 +8,7 @@
 namespace Drupal\options\Plugin\Field\FieldType;
 
 use Drupal\Component\Utility\NestedArray;
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\Field\FieldItemBase;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\TypedData\AllowedValuesInterface;
@@ -68,7 +68,7 @@ public function getSettableOptions(AccountInterface $account = NULL) {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $properties['value'] = DataDefinition::create('boolean')
       ->setLabel(t('Boolean value'));
 
@@ -78,7 +78,7 @@ public static function propertyDefinitions(FieldDefinitionInterface $field_defin
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     return array(
       'columns' => array(
         'value' => array(
diff --git a/core/modules/options/lib/Drupal/options/Plugin/Field/FieldType/ListFloatItem.php b/core/modules/options/lib/Drupal/options/Plugin/Field/FieldType/ListFloatItem.php
index b3f7271..30cd382 100644
--- a/core/modules/options/lib/Drupal/options/Plugin/Field/FieldType/ListFloatItem.php
+++ b/core/modules/options/lib/Drupal/options/Plugin/Field/FieldType/ListFloatItem.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\options\Plugin\Field\FieldType;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\TypedData\DataDefinition;
 
 /**
@@ -26,7 +26,7 @@ class ListFloatItem extends ListItemBase {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $properties['value'] = DataDefinition::create('float')
       ->setLabel(t('Float value'));
 
@@ -36,7 +36,7 @@ public static function propertyDefinitions(FieldDefinitionInterface $field_defin
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     return array(
       'columns' => array(
         'value' => array(
diff --git a/core/modules/options/lib/Drupal/options/Plugin/Field/FieldType/ListIntegerItem.php b/core/modules/options/lib/Drupal/options/Plugin/Field/FieldType/ListIntegerItem.php
index cc506d4..c049878 100644
--- a/core/modules/options/lib/Drupal/options/Plugin/Field/FieldType/ListIntegerItem.php
+++ b/core/modules/options/lib/Drupal/options/Plugin/Field/FieldType/ListIntegerItem.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\options\Plugin\Field\FieldType;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\TypedData\DataDefinition;
 
 /**
@@ -26,7 +26,7 @@ class ListIntegerItem extends ListItemBase {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $properties['value'] = DataDefinition::create('integer')
       ->setLabel(t('Integer value'));
 
@@ -36,7 +36,7 @@ public static function propertyDefinitions(FieldDefinitionInterface $field_defin
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     return array(
       'columns' => array(
         'value' => array(
diff --git a/core/modules/options/lib/Drupal/options/Plugin/Field/FieldType/ListTextItem.php b/core/modules/options/lib/Drupal/options/Plugin/Field/FieldType/ListTextItem.php
index 754d397..1cf34b4 100644
--- a/core/modules/options/lib/Drupal/options/Plugin/Field/FieldType/ListTextItem.php
+++ b/core/modules/options/lib/Drupal/options/Plugin/Field/FieldType/ListTextItem.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\options\Plugin\Field\FieldType;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\TypedData\DataDefinition;
 
 /**
@@ -26,7 +26,7 @@ class ListTextItem extends ListItemBase {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $properties['value'] = DataDefinition::create('string')
       ->setLabel(t('Text value'))
       ->addConstraint('Length', array('max' => 255));
@@ -37,7 +37,7 @@ public static function propertyDefinitions(FieldDefinitionInterface $field_defin
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     return array(
       'columns' => array(
         'value' => array(
diff --git a/core/modules/path/lib/Drupal/path/Plugin/Field/FieldType/PathItem.php b/core/modules/path/lib/Drupal/path/Plugin/Field/FieldType/PathItem.php
index e43efb2..1150c99 100644
--- a/core/modules/path/lib/Drupal/path/Plugin/Field/FieldType/PathItem.php
+++ b/core/modules/path/lib/Drupal/path/Plugin/Field/FieldType/PathItem.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\path\Plugin\Field\FieldType;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\Field\FieldItemBase;
 use Drupal\Core\TypedData\DataDefinition;
 
@@ -26,7 +26,7 @@ class PathItem extends FieldItemBase {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $properties['alias'] = DataDefinition::create('string')
         ->setLabel(t('Path alias'));
     $properties['pid'] = DataDefinition::create('string')
@@ -37,7 +37,7 @@ public static function propertyDefinitions(FieldDefinitionInterface $field_defin
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     return array();
   }
 
diff --git a/core/modules/shortcut/lib/Drupal/shortcut/ShortcutPathItem.php b/core/modules/shortcut/lib/Drupal/shortcut/ShortcutPathItem.php
index 10dbed5..8ad82d3 100644
--- a/core/modules/shortcut/lib/Drupal/shortcut/ShortcutPathItem.php
+++ b/core/modules/shortcut/lib/Drupal/shortcut/ShortcutPathItem.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\shortcut;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\Field\Plugin\Field\FieldType\StringItem;
 use Drupal\Core\TypedData\DataDefinition;
 
@@ -19,7 +19,7 @@ class ShortcutPathItem extends StringItem {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $properties['value'] = DataDefinition::create('string')
       ->setLabel(t('String value'))
       ->setComputed(TRUE)
diff --git a/core/modules/system/entity.api.php b/core/modules/system/entity.api.php
index 4417e0b..c53444b 100644
--- a/core/modules/system/entity.api.php
+++ b/core/modules/system/entity.api.php
@@ -707,6 +707,10 @@ function hook_entity_base_field_info_alter(&$fields, \Drupal\Core\Entity\EntityT
 /**
  * Provides field definitions for a specific bundle within an entity type.
  *
+ * Bundle fields either have to override an existing base field, or need to
+ * provide a field storage definition via hook_entity_field_storage_info()
+ * unless they are computed.
+ *
  * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
  *   The entity type definition.
  * @param string $bundle
@@ -719,6 +723,8 @@ function hook_entity_base_field_info_alter(&$fields, \Drupal\Core\Entity\EntityT
  *
  * @see hook_entity_base_field_info()
  * @see hook_entity_base_field_info_alter()
+ * @see hook_entity_field_storage_info()
+ * @see hook_entity_field_storage_info_alter()
  * @see hook_entity_bundle_field_info_alter()
  * @see \Drupal\Core\Field\FieldDefinitionInterface
  * @see \Drupal\Core\Entity\EntityManagerInterface::getFieldDefinitions()
@@ -757,6 +763,55 @@ function hook_entity_bundle_field_info_alter(&$fields, \Drupal\Core\Entity\Entit
 }
 
 /**
+ * Provides field storage definitions for a content entity type.
+ *
+ * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
+ *   The entity type definition.
+ *
+ * @return \Drupal\Core\Field\FieldStorageDefinitionInterface[]
+ *   An array of field storage definitions, keyed by field name.
+ *
+ * @see hook_entity_field_storage_info_alter()
+ * @see \Drupal\Core\Field\FieldStorageDefinitionInterface
+ * @see \Drupal\Core\Entity\EntityManagerInterface::getFieldStorageDefinitions()
+ */
+function hook_entity_field_storage_info(\Drupal\Core\Entity\EntityTypeInterface $entity_type) {
+  // Expose storage definitions for all exposed bundle fields.
+  if ($entity_type->isFieldable()) {
+    // Query by filtering on the ID as this is more efficient than filtering
+    // on the entity_type property directly.
+    $ids = \Drupal::entityQuery('field_config')
+      ->condition('id', $entity_type->id() . '.', 'STARTS_WITH')
+      ->execute();
+
+    // Fetch all fields and key them by field name.
+    $field_configs = entity_load_multiple('field_config', $ids);
+    $result = array();
+    foreach ($field_configs as $field_config) {
+      $result[$field_config->getName()] = $field_config;
+    }
+    return $result;
+  }
+}
+
+/**
+ * Alters field storage definitions for a content entity type.
+ *
+ * @param \Drupal\Core\Field\FieldStorageDefinitionInterface[] $fields
+ *   The array of field storage definitions for the entity type.
+ * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
+ *   The entity type definition.
+ *
+ * @see hook_entity_field_storage_info()
+ */
+function hook_entity_field_storage_info_alter(&$fields, \Drupal\Core\Entity\EntityTypeInterface $entity_type) {
+  // Alter the max_length setting.
+  if ($entity_type->id() == 'node' && !empty($fields['mymodule_text'])) {
+    $fields['mymodule_text']->setSetting('max_length', 128);
+  }
+}
+
+/**
  * Declares entity operations.
  *
  * @param \Drupal\Core\Entity\EntityInterface $entity
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Field/FieldType/TaxonomyTermReferenceItem.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Field/FieldType/TaxonomyTermReferenceItem.php
index eaa2103..a893063 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Field/FieldType/TaxonomyTermReferenceItem.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Field/FieldType/TaxonomyTermReferenceItem.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\taxonomy\Plugin\Field\FieldType;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\TypedData\AllowedValuesInterface;
@@ -94,7 +94,7 @@ public function getSettableOptions(AccountInterface $account = NULL) {
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     return array(
       'columns' => array(
         'target_id' => array(
diff --git a/core/modules/telephone/lib/Drupal/telephone/Plugin/Field/FieldType/TelephoneItem.php b/core/modules/telephone/lib/Drupal/telephone/Plugin/Field/FieldType/TelephoneItem.php
index 6be9dff..2b1a5b6 100644
--- a/core/modules/telephone/lib/Drupal/telephone/Plugin/Field/FieldType/TelephoneItem.php
+++ b/core/modules/telephone/lib/Drupal/telephone/Plugin/Field/FieldType/TelephoneItem.php
@@ -8,7 +8,7 @@
 namespace Drupal\telephone\Plugin\Field\FieldType;
 
 use Drupal\Core\Field\FieldItemBase;
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\TypedData\DataDefinition;
 
 /**
@@ -27,7 +27,7 @@ class TelephoneItem extends FieldItemBase {
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     return array(
       'columns' => array(
         'value' => array(
@@ -42,7 +42,7 @@ public static function schema(FieldDefinitionInterface $field_definition) {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $properties['value'] = DataDefinition::create('string')
       ->setLabel(t('Telephone number'));
 
diff --git a/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextItem.php b/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextItem.php
index 49ca7f1..b2ba0a1 100644
--- a/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextItem.php
+++ b/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextItem.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\text\Plugin\Field\FieldType;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 
 /**
  * Plugin implementation of the 'text' field type.
@@ -34,7 +34,7 @@ public static function defaultSettings() {
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     return array(
       'columns' => array(
         'value' => array(
diff --git a/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextItemBase.php b/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextItemBase.php
index fe704c2..4f2deca 100644
--- a/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextItemBase.php
+++ b/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextItemBase.php
@@ -8,7 +8,7 @@
 namespace Drupal\text\Plugin\Field\FieldType;
 
 use Drupal\Core\Field\FieldItemBase;
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\Field\PrepareCacheInterface;
 use Drupal\Core\TypedData\DataDefinition;
 
@@ -29,7 +29,7 @@ public static function defaultInstanceSettings() {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $properties['value'] = DataDefinition::create('string')
       ->setLabel(t('Text value'));
 
diff --git a/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextLongItem.php b/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextLongItem.php
index 1cf0385..367ae19 100644
--- a/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextLongItem.php
+++ b/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextLongItem.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\text\Plugin\Field\FieldType;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 
 /**
  * Plugin implementation of the 'text_long' field type.
@@ -25,7 +25,7 @@ class TextLongItem extends TextItemBase {
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     return array(
       'columns' => array(
         'value' => array(
diff --git a/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextWithSummaryItem.php b/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextWithSummaryItem.php
index 8cb505f..0d686e0 100644
--- a/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextWithSummaryItem.php
+++ b/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextWithSummaryItem.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\text\Plugin\Field\FieldType;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\TypedData\DataDefinition;
 
 /**
@@ -36,7 +36,7 @@ public static function defaultInstanceSettings() {
   /**
    * {@inheritdoc}
    */
-  public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
     $properties = parent::propertyDefinitions($field_definition);
 
     $properties['summary'] = DataDefinition::create('string')
@@ -55,7 +55,7 @@ public static function propertyDefinitions(FieldDefinitionInterface $field_defin
   /**
    * {@inheritdoc}
    */
-  public static function schema(FieldDefinitionInterface $field_definition) {
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
     return array(
       'columns' => array(
         'value' => array(
diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
index b16008c..5e59cad 100644
--- a/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
@@ -476,6 +476,40 @@ public function testGetFieldDefinitions() {
   }
 
   /**
+   * Tests the getFieldStorageDefinitions() method.
+   *
+   * @covers ::getFieldStorageDefinitions()
+   */
+  public function testGetFieldStorageDefinitions() {
+    $field_definition = $this->setUpEntityWithFieldDefinition(TRUE);
+    $field_storage_definition = $this->getMock('\Drupal\Core\Field\FieldStorageDefinitionInterface');
+    $field_storage_definition->expects($this->any())
+      ->method('getName')
+      ->will($this->returnValue('field_storage'));
+
+    $this->moduleHandler->expects($this->at(0))
+      ->method('getImplementations')
+      ->with('entity_base_field_info')
+      ->will($this->returnValue(array()));
+
+    $this->moduleHandler->expects($this->at(2))
+      ->method('getImplementations')
+      ->with('entity_field_storage_info')
+      ->will($this->returnValue(array('example_module')));
+
+    $this->moduleHandler->expects($this->any())
+      ->method('invoke')
+      ->with('example_module', 'entity_field_storage_info')
+      ->will($this->returnValue(array('field_storage' => $field_storage_definition)));
+
+    $expected = array(
+      'id' => $field_definition,
+      'field_storage' => $field_storage_definition,
+    );
+    $this->assertSame($expected, $this->entityManager->getFieldStorageDefinitions('test_entity_type'));
+  }
+
+  /**
    * Tests the getBaseFieldDefinitions() method with caching.
    *
    * @covers ::getBaseFieldDefinitions()
@@ -501,7 +535,6 @@ public function testGetBaseFieldDefinitionsWithCaching() {
     $this->assertSame($expected, $this->entityManager->getBaseFieldDefinitions('test_entity_type'));
   }
 
-
   /**
    * Tests the getFieldDefinitions() method with caching.
    *
@@ -537,6 +570,57 @@ public function testGetFieldDefinitionsWithCaching() {
   }
 
   /**
+   * Tests the getFieldStorageDefinitions() method with caching.
+   *
+   * @covers ::getFieldStorageDefinitions()
+   */
+  public function testGetFieldStorageDefinitionsWithCaching() {
+    $field_definition = $this->setUpEntityWithFieldDefinition(TRUE, 'id', 0);
+    $field_storage_definition = $this->getMock('\Drupal\Core\Field\FieldStorageDefinitionInterface');
+    $field_storage_definition->expects($this->any())
+      ->method('getName')
+      ->will($this->returnValue('field_storage'));
+
+    $this->moduleHandler->expects($this->any())
+      ->method('getImplementations')
+      ->with('entity_field_storage_info')
+      ->will($this->returnValue(array('example_module')));
+
+    $this->moduleHandler->expects($this->once())
+      ->method('invoke')
+      ->with('example_module')
+      ->will($this->returnValue(array('field_storage' => $field_storage_definition)));
+
+    $expected = array(
+      'id' => $field_definition,
+      'field_storage' => $field_storage_definition,
+    );
+
+    $this->cache->expects($this->at(0))
+      ->method('get')
+      ->with('entity_base_field_definitions:test_entity_type:en', FALSE)
+      ->will($this->returnValue((object) array('data' => array('id' => $expected['id']))));
+    $this->cache->expects($this->at(1))
+      ->method('get')
+      ->with('entity_field_storage_definitions:test_entity_type:en', FALSE)
+      ->will($this->returnValue(FALSE));
+    $this->cache->expects($this->at(2))
+      ->method('set');
+    $this->cache->expects($this->at(3))
+      ->method('get')
+      ->with('entity_base_field_definitions:test_entity_type:en', FALSE)
+      ->will($this->returnValue((object) array('data' => array('id' => $expected['id']))));
+    $this->cache->expects($this->at(4))
+      ->method('get')
+      ->with('entity_field_storage_definitions:test_entity_type:en', FALSE)
+      ->will($this->returnValue((object) array('data' => $expected)));
+
+    $this->assertSame($expected, $this->entityManager->getFieldStorageDefinitions('test_entity_type'));
+    $this->entityManager->testClearEntityFieldInfo();
+    $this->assertSame($expected, $this->entityManager->getFieldStorageDefinitions('test_entity_type'));
+  }
+
+  /**
    * Tests the getBaseFieldDefinitions() method with an invalid definition.
    *
    * @covers ::getBaseFieldDefinitions()
@@ -904,11 +988,12 @@ public function setDiscovery(DiscoveryInterface $discovery) {
   }
 
   /**
-   * Allows the $entityFieldInfo property to be cleared.
+   * Allows the static caches to be cleared.
    */
   public function testClearEntityFieldInfo() {
     $this->baseFieldDefinitions = array();
     $this->fieldDefinitions = array();
+    $this->fieldStorageDefinitions = array();
   }
 
 }
