diff --git a/commerce_license_billing.info b/commerce_license_billing.info
index 2338fd8..5fecf0b 100644
--- a/commerce_license_billing.info
+++ b/commerce_license_billing.info
@@ -16,6 +16,7 @@ files[] = commerce_license_billing.info.inc
 files[] = plugins/billing_cycle_engine/base.inc
 files[] = includes/commerce_license_billing.interface.inc
 files[] = includes/commerce_license_billing.cycle_type_ui.inc
+files[] = includes/commerce_license_billing.cycle_type_controller.inc
 files[] = includes/commerce_license_billing.cycle.inc
 
 ; Views
diff --git a/commerce_license_billing.module b/commerce_license_billing.module
index 24b643b..8bb2217 100644
--- a/commerce_license_billing.module
+++ b/commerce_license_billing.module
@@ -115,7 +115,7 @@ function commerce_license_billing_entity_info() {
     'module' => 'commerce_license_billing',
     'base table' => 'cl_billing_cycle_type',
     'access callback' => 'commerce_license_billing_cycle_type_access',
-    'controller class' => 'EntityBundlePluginEntityControllerExportable',
+    'controller class' => 'CommerceLicenseBillingCycleTypeControllerExportable',
     'fieldable' => TRUE,
     'exportable' => TRUE,
     'bundles' => array(),
diff --git a/includes/commerce_license_billing.cycle_type_controller.inc b/includes/commerce_license_billing.cycle_type_controller.inc
new file mode 100644
index 0000000..c689c95
--- /dev/null
+++ b/includes/commerce_license_billing.cycle_type_controller.inc
@@ -0,0 +1,73 @@
+<?php
+class CommerceLicenseBillingCycleTypeControllerExportable extends EntityAPIControllerExportable {
+
+  const ID_CACHE_CID = '_commerce_license_billing_cycle_type_ids';
+
+  /**
+   * Override the load function to record the IDs of entities by machine name.
+   * We use this information to ensure that IDs don't randomly change when the
+   * user reverts Billing Cycle Types. That can break product associations.
+   *
+   * @param array $ids
+   * @param array $conditions
+   * @return array
+   */
+  public function load($ids = array(), $conditions = array()) {
+    $cached_id_cache = cache_get(self::ID_CACHE_CID);
+    if (empty($cached_id_cache)) {
+      $id_cache = array();
+    }
+    else {
+      $id_cache = $cached_id_cache->data;
+    }
+
+    $loaded_entities = parent::load($ids, $conditions);
+
+    // Extract IDs from the loaded entities and into our static cache.
+    foreach ($loaded_entities as $loaded_entity) {
+      if (!empty($loaded_entity->{$this->idKey})) {
+        $id_cache[$loaded_entity->{$this->nameKey}] = $loaded_entity->{$this->idKey};
+      }
+    }
+
+    cache_set(self::ID_CACHE_CID, $id_cache);
+
+    // Return the $loaded_entities, as the caller would expect.
+    return $loaded_entities;
+  }
+
+  /**
+   * Cleans up our static cache.
+   *
+   * @param $entity
+   * @param \DatabaseTransaction|NULL $transaction
+   * @return bool|int
+   */
+  public function save($entity, DatabaseTransaction $transaction = NULL) {
+    $id_cache = NULL;
+    $cached_id_cache = cache_get(self::ID_CACHE_CID);
+    if ($cached_id_cache) {
+      $id_cache = $cached_id_cache->data;
+    }
+
+    // If we know what the previous ID for the billing cycle with this name
+    // was, ensure that it retains the same ID when saved here. But only do
+    // this if nothing else has already set the ID.
+    if ($id_cache && empty($entity->{$this->idKey}) && !empty($id_cache[$entity->{$this->nameKey}])) {
+      $entity->{$this->idKey} = $id_cache[$entity->{$this->nameKey}];
+    }
+
+    $save_result = parent::save($entity, $transaction);
+
+    // If the save succeeded, then we don't need that key in the static cache
+    // anymore. May as well unset it.
+    if ($save_result) {
+      unset($id_cache[$entity->{$this->nameKey}]);
+    }
+
+    cache_set(self::ID_CACHE_CID, $id_cache);
+
+    return $save_result;
+  }
+
+}
