diff --git a/push_hub.module b/push_hub.module
index 5211427..040e06b 100644
--- a/push_hub.module
+++ b/push_hub.module
@@ -10,6 +10,25 @@ include_once 'PuSHHub.inc';
 define('PUSH_HUB_NOTIFICATIONS_QUEUE', 'push_hub_notifications');
 
 /**
+ * Flag for notifications that should get sent using a browser batch process.
+ */
+define('PUSH_HUB_BATCH', 1);
+
+/**
+ * Flag for notifications that should get sent on cron.
+ */
+define('PUSH_HUB_CRON', 2);
+
+/**
+ * Flag to specify notifications should be sent immediately in hook_exit().
+ *
+ * Note: Do not use this flag directly. Only use it in combination with PUSH_HUB_CRON.
+ */
+define('PUSH_HUB_IMMEDIATE', 4);
+
+
+
+/**
  * Implements hook_enable().
  */
 function push_hub_enable() {
@@ -68,14 +87,36 @@ function push_hub_drupal_queue_load_classes() {
  *   a light ping (without any content) will be issued to subscriber and
  *   subscriber is expected to fetch content from publisher. Light pings are
  *   not pubsubhubbub spec conform.
- * @param $batch
+ * @param $send
+ *   Specifies when items should be sent to subscribers.  This parameter must
+ *   be one of the following constants:
+ *     - PUSH_HUB_CRON: Notifications will be queued for execution on cron.
+ *     - PUSH_HUB_BATCH: Notifications will be sent using browser-based batching.
+ *         Note that this should never be called from an automated process.
+ *     - PUSH_HUB_IMMEDIATE: This is the same as PUSH_HUB_CRON, except that
+ *         the queue will also be processed on request exit.  That means low-
+ *         volume notifications should get sent immediately, while high-volume
+ *         notifications will at least get a head start. Note: Do not use this
+ *         option unless it is bitwise-&'ed with PUSH_HUB_CRON.
  *   Set to true to use browser based batching, otherwise notifications will be
  *   queued for execution cron.
  *
  * @todo Support batching, queue failing notifications for later.
  */
-function push_hub_notify($topic, $changed = NULL, $batch = FALSE) {
-  if ($batch) {
+function push_hub_notify($topic, $changed = NULL, $send = PUSH_HUB_CRON) {
+  // For backward compatibility, fold the old booean values to their new
+  // equivalents. Because we want both FALSE and 0 to mean "cron", use an
+  // equality check rather than an identify check.
+  if ($send == FALSE) {
+    $send = PUSH_HUB_CRON;
+  }
+  if ($send === TRUE) {
+    $send = PUSH_HUB_BATCH;
+  }
+
+  // Batch and Cron are mutually exclusive, mostly because Batch was never
+  // ported to Cron.  Bah.
+  if ($send & PUSH_HUB_BATCH) {
     $operations = array();
     watchdog('push_hub', "notifying all subscribers batched", NULL, WATCHDOG_DEBUG);
     foreach (push_hub()->allSubscribers($topic) as $subscriber) {
@@ -95,13 +136,61 @@ function push_hub_notify($topic, $changed = NULL, $batch = FALSE) {
     );
     batch_set($batch);
   }
-  else {
+  else if ($send & PUSH_HUB_CRON) {
     watchdog('push_hub', "notifying all subscribers queued", NULL, WATCHDOG_DEBUG);
     foreach (push_hub()->allSubscribers($topic) as $subscriber) {
       watchdog('push_hub', "notifying subscriber queued " . $subscriber, NULL, WATCHDOG_DEBUG);
       push_hub_queue()->createItem(array('topic' => $topic, 'subscriber' => $subscriber, 'changed' => $changed));
     }
   }
+
+  // If necessary, flag to process the queue immediately.
+  if ($send & PUSH_HUB_IMMEDIATE) {
+    push_hub_needs_immediate_send(TRUE);
+  }
+}
+
+/**
+ * Collector function for whether we need to process a PuSH queue immediately.
+ *
+ * @param boolean $send
+ *   TRUE to flag that we need to process the queue at the end of this request,
+ *   FALSE to not process. By default, this value is FALSE.
+ * @return boolean
+ *   The current status of this flag.
+ */
+function push_hub_needs_immedaite_send($send = NULL) {
+  $needs_send = &drupal_static(__FUNCTION__);
+  if (!is_null($send)) {
+    $needs_send = $send;
+  }
+
+  return $needs_send;
+}
+
+/**
+ * Implements hook_exit().
+ *
+ * Note that because hook_exit() runs after the process completes, it should
+ * have no impact on the speed at which a user sees content in their browser.
+ */
+function push_hub_exit() {
+  if (push_hub_needs_immediate_send()) {
+    // Try to allocate enough time to run through any notifications that were
+    // just added.
+    drupal_set_time_limit(240);
+
+    // This code borrowed from drupal_cron_run().
+    $info = module_invoke('push_hub', 'cron_queue_info');
+    $function = $info['worker callback'];
+    $end = time() + (isset($info['time']) ? $info['time'] : 15);
+
+    $queue = DrupalQueue::get($queue_name);
+    while (time() < $end && ($item = $queue->claimItem())) {
+      $function($item->data);
+      $queue->deleteItem($item);
+    }
+  }
 }
 
 /**
