diff --git b/imagefield_crop.install a/imagefield_crop.install
new file mode 100644
index 0000000..7890eff
--- /dev/null
+++ a/imagefield_crop.install
@@ -0,0 +1,47 @@
+<?php
+
+/**
+ * Implements hook_schema().
+ */
+function imagefield_crop_schema() {
+  $schema['imagefield_crop'] = array(
+    'fields' => array(
+      'fid' => array('type' => 'int', 'unsigned' => FALSE, 'not null' => FALSE),
+      'x' => array('type' => 'int', 'unsigned' => FALSE, 'not null' => FALSE),
+      'y' => array('type' => 'int', 'unsigned' => FALSE, 'not null' => FALSE),
+      'width' => array('type' => 'int', 'unsigned' => FALSE, 'not null' => FALSE),
+      'height' => array('type' => 'int', 'unsigned' => FALSE, 'not null' => FALSE),
+    ),
+    'primary key' => array('fid'),
+  );
+  return $schema;
+}
+
+/**
+ * Install imagefield_crop table and migrate settings away from variables table.
+ */
+function imagefield_crop_update_7001() {
+  if (!db_table_exists('imagefield_crop')) {
+    drupal_install_schema('imagefield_crop');
+  }
+
+  // Migrate the data out of the variables table.
+  $crop_info = variable_get('imagefield_crop_info', array());
+  if (!empty($crop_info)) {
+    $txn = db_transaction();
+    // Chunk the field inserts into rows of 100 to
+    // stay within any database multi-insert limit.
+    $chunks = array_chunk($crop_info, 100, TRUE);
+    foreach ($chunks as $insert_data) {
+      $insert = db_insert('imagefield_crop')
+        ->fields(array('fid', 'x', 'y', 'width', 'height'));
+      foreach ($insert_data as $fid => $values) {
+        $values['fid'] = $fid;
+        $insert->values($values);
+      }
+      $insert->execute();
+    }
+  }
+  // Remove the imagefield_crop variable as its no longer needed.
+  variable_del('imagefield_crop_info');
+}
diff --git b/imagefield_crop.module a/imagefield_crop.module
index c981ffd..2ea61c1 100644
--- b/imagefield_crop.module
+++ a/imagefield_crop.module
@@ -33,6 +33,45 @@ function imagefield_crop_field_widget_info() {
 }
 
 /**
+ * Get imagefield crop settings for a file.
+ */
+function imagefield_crop_file_settings($fid) {
+  $settings = &drupal_static(__FUNCTION__, array());
+  if (isset($settings[$fid])) {
+    return $settings[$fid];
+  }
+  $settings[$fid] = db_query('SELECT * FROM {imagefield_crop} WHERE fid = :fid', array(':fid' => $fid))->fetchAssoc();
+
+  // We should always return an array, even if there are no settings found.
+  if (!is_array($settings[$fid])) {
+    $settings[$fid] = array(
+      'x'       => 0,
+      'y'       => 0,
+      'width'   => 50,
+      'height'  => 50,
+      'changed' => 0,
+    );
+  }
+  return $settings[$fid];
+}
+
+/**
+ * Get imagefield crop settings for a file.
+ */
+function imagefield_crop_file_settings_save($crop_settings) {
+  $fid = $crop_settings['fid'];
+  $settings = &drupal_static('imagefield_crop_file_settings', array());
+  $settings[$fid] = $crop_settings;
+
+  unset($crop_settings['fid']);
+
+  return db_merge('imagefield_crop')
+    ->key(array('fid' => $fid))
+    ->fields($crop_settings)
+    ->execute();
+}
+
+/**
  * Implements hook_filefield_sources_widgets().
  *
  * This returns a list of widgets that are compatible with FileField Sources.
@@ -263,20 +302,9 @@ function imagefield_crop_widget_process($element, &$form_state, $form) {
   return $element;
 }
 
-function _imagefield_add_cropinfo_fields($fid = NULL) {
-  $defaults = array(
-    'x'       => 0,
-    'y'       => 0,
-    'width'   => 50,
-    'height'  => 50,
-    'changed' => 0,
-  );
-  if ($fid) {
-    $crop_info = variable_get('imagefield_crop_info', array());
-    if (isset($crop_info[$fid]) && !empty($crop_info[$fid])) {
-      $defaults = array_merge($defaults, $crop_info[$fid]);
-    }
-  }
+function _imagefield_add_cropinfo_fields($fid = 0) {
+  $defaults = imagefield_crop_file_settings($fid);
+  $defaults['changed'] = 0;
 
   foreach ($defaults as $name => $default) {
     $element[$name] = array(
@@ -367,10 +395,9 @@ function imagefield_crop_widget_value(&$element, &$input, $form_state) {
     
     if (_imagefield_crop_resize(drupal_realpath($file_to_crop->uri), $crop, $scale, drupal_realpath($src->uri))) {
       // insert crop info for this image in imagefield_crop_info variable
-      $crop_info = variable_get('imagefield_crop_info', array());
+      $crop['fid'] = $src->fid;
       unset($crop['changed']);
-      $crop_info[$src->fid] = $crop;
-      variable_set('imagefield_crop_info', $crop_info);
+      imagefield_crop_file_settings_save($crop);
       // Remove cached versions of the cropped image.
       image_path_flush($src->uri);
     }
@@ -385,9 +412,7 @@ function imagefield_crop_widget_delete($form, &$form_state) {
   if ($orig->fid != $element['fid']) {
     file_usage_delete($orig, 'imagefield_crop');
     file_delete($orig);
-    $crop_info = variable_get('imagefield_crop_info', array());
-    unset($crop_info[$element['fid']]);
-    variable_set('imagefield_crop_info', $crop_info);
+    db_delete('imagefield_crop')->condition('fid', $element['fid'])->execute();
   }
 }
 
