diff --git a/message_subscribe.install b/message_subscribe.install
new file mode 100644
index 0000000..b856ce6
--- /dev/null
+++ b/message_subscribe.install
@@ -0,0 +1,14 @@
+<?php
+
+/**
+ * @file
+ * Install, update, and uninstall functions for Message subscribe.
+ */
+
+/**
+ * Implements hook_uninstall().
+ */
+function message_subscribe_uninstall() {
+  variable_del('message_subscribe_scalable');
+}
+
diff --git a/message_subscribe.module b/message_subscribe.module
index 53b43cc..3518b84 100644
--- a/message_subscribe.module
+++ b/message_subscribe.module
@@ -24,7 +24,12 @@
  *   - "skip context": Determine if extracting basic context should be
  *     skipped in message_subscribe_get_subscribers(). Defaults to FALSE.
  *   - "last uid": The last user ID to query.
- *   - "range": The number of items to fetch in the query.
+ *   - "range": The number of items to fetch in the query. If the messages
+ *     are to be sent in a scalable way the range defaults to 100,
+ *     otherwise all items are fetched, and the range is set to 0.
+ *   - "queue name": If the messages are to be sent in a scalable way,
+ *     this determines the queue name where the tasks will be stored.
+ *     Defautls to  "message_subscribe_tasks".
  * @param $context
  *   Optional; Array keyed with the entity type and array of entity IDs as
  *   the value. For example, if the event is related to a node
@@ -44,19 +49,50 @@
  * @return
  *   The message object.
  */
-function message_subscribe_process_message($entity_type, $entity, Message $message, $notify_options = array(), $subscribe_options = array(), $context = array()) {
+function message_subscribe_process_message($entity_type, $entity, Message $message, $notify_options = array(), $subscribe_options = array(), $context = array(), $queue_item = NULL) {
+  $is_scalable = variable_get('message_subscribe_scalable', FALSE);
   // Save message by default.
   $subscribe_options += array(
     'save message' => TRUE,
     'skip context' => FALSE,
     'last uid' => 0,
-    'range' => FALSE,
+    'range' => $is_scalable ? 100 : 0,
+    'queue name' => 'message_subscribe_tasks',
   );
 
   if (empty($message->mid) && $subscribe_options['save message']) {
     $message->save();
   }
 
+  if ($is_scalable && !$queue_item) {
+    if (empty($message->mid)) {
+      throw new Exception('Cannot add a non-saved message to the queue.');
+    }
+
+    list($id) = entity_extract_ids($entity_type, $entity);
+    $context = message_subscribe_get_basic_context($entity_type, $entity, $message, $subscribe_options, $context);
+
+    // Get the context once, so we don't need to process it every time
+    // a worker claims the item.
+    $subscribe_options['skip context'] = TRUE;
+
+    // Add item to the queue.
+    $queue = DrupalQueue::get($subscribe_options['queue name']);
+    $task = array(
+      'mid' => $message->mid,
+      'uid' => $subscribe_options['last uid'],
+      'entity_type' => $entity_type,
+      'entity_id' => $id,
+      'notify_options' => $notify_options,
+      'subscribe_options' => $subscribe_options,
+      'context' => $context,
+    );
+    $queue->createItem($task);
+
+    // Exit now, as send will be processed via queue.
+    return;
+  }
+
   $message->message_subscribe = array();
 
   // Retrieve all users subscribed.
@@ -64,6 +100,7 @@ function message_subscribe_process_message($entity_type, $entity, Message $messa
     return $message;
   }
 
+  $last_sent_uid = 0;
   foreach ($uids as $uid => $values) {
     $values['notifiers'] = !empty($values['notifiers']) ? $values['notifiers'] : array('email');
 
@@ -83,6 +120,7 @@ function message_subscribe_process_message($entity_type, $entity, Message $messa
 
       message_notify_send_message($cloned_message, $options, $notifier_name);
     }
+    $last_sent_uid = $uid;
   }
 
   // Add the context and the user IDs to the message for further
@@ -92,10 +130,71 @@ function message_subscribe_process_message($entity_type, $entity, Message $messa
     'uids' => $uids,
   );
 
+  // TODO: This should move after message_notify_send_message() so if we
+  // timeout, we still capture to last user ID.
+  if ($is_scalable && $queue_item) {
+    // Delete previous item (as we cannot update existing one).
+    $queue = DrupalQueue::get($subscribe_options['queue name']);
+    $task->item_id = $queue_item;
+    $queue->deleteItem($task);
+
+    // Check there is atleast one more users to process.
+    $subscribe_options['last uid'] = $last_sent_uid;
+    $subscribe_options['range'] = 1;
+    if (!message_subscribe_get_subscribers($entity_type, $entity, $message, $subscribe_options, $context)) {
+      // There are no more users.
+      return $message;
+    }
+
+    list($id) = entity_extract_ids($entity_type, $entity);
+
+    // Re-create a new task.
+    $task = array(
+      'mid' => $message->mid,
+      'uid' => $last_sent_uid,
+      'entity_type' => $entity_type,
+      'entity_id' => $id,
+      'notify_options' => $notify_options,
+      'subscribe_options' => $subscribe_options,
+      'context' => $context,
+    );
+    $queue->createItem($task);
+  }
+
   return $message;
 }
 
 /**
+ * Implements hook_cron_queue_info().
+ */
+function message_subscribe_cron_queue_info() {
+  if (!variable_get('message_subscribe_scalable', FALSE) || !variable_get('message_subscribe_scalable_cron', FALSE)) {
+    // We don't process message in a scalable way, or don't need hook_cron
+    // to do it, as we have workers implemnted in a different way.
+    return;
+  }
+  $queues['message_subscribe_tasks'] = array(
+    'worker callback' => 'message_subscribe_run_task',
+    'time' => 60,
+  );
+  return $queues;
+}
+
+/**
+ * Queue worker callback for running a single task.
+ */
+function message_subscribe_run_task($task) {
+  $data = $task->data;
+  $entity_type = $data['entity_type'];
+  $entity = entity_load_single($entity_type, $data['entity_id']);
+  $message = message_load($data['mid']);
+
+  $subscribe_options['last uid'] = $data['uid'];
+
+  message_subscribe_process_message($entity_type, $entity, $message, $data['notify_options'], $data['subscribe_options'], $data['context'] , $task->item_id);
+}
+
+/**
  * Get a list of user IDs that need to recieve the message.
  *
  * @param $entity_type
