diff --git a/src/Annotation/SettingsPlugin.php b/src/Annotation/SettingsPlugin.php
new file mode 100644
index 0000000..5619b44
--- /dev/null
+++ b/src/Annotation/SettingsPlugin.php
@@ -0,0 +1,46 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\ultimate_cron\Annotation\SettingsPlugin.
+ */
+
+namespace Drupal\ultimate_cron\Annotation;
+
+use Drupal\Component\Annotation\Plugin;
+
+/**
+ * Defines a Logger plugin annotation object.
+ *
+ * @Annotation
+ *
+ * @see \Drupal\ultimate_cron\LoggerManager
+ */
+class SettingsPlugin extends Plugin {
+
+  /**
+   * The plugin ID.
+   *
+   * @var string
+   */
+  public $id;
+
+  /**
+   * The human-readable title of the scheduler.
+   *
+   * @ingroup plugin_translatable
+   *
+   * @var \Drupal\Core\Annotation\Translation
+   */
+  public $title;
+
+  /**
+   * A short description of the scheduler.
+   *
+   * @ingroup plugin_translatable
+   *
+   * @var \Drupal\Core\Annotation\Translation
+   */
+  public $description;
+
+}
diff --git a/src/CronPlugin.php b/src/CronPlugin.php
index 6432343..702361e 100644
--- a/src/CronPlugin.php
+++ b/src/CronPlugin.php
@@ -41,7 +41,8 @@ abstract class CronPlugin extends PluginBase implements PluginInspectionInterfac
     return array(
       'scheduler' => t('Scheduler'),
       'launcher' => t('Launcher'),
-      'logger' => t('Logger')
+      'logger' => t('Logger'),
+      'settings' => t('Settings')
     );
   }
 
diff --git a/src/CronPluginMultiple.php b/src/CronPluginMultiple.php
index 6cb6b2b..1738e32 100644
--- a/src/CronPluginMultiple.php
+++ b/src/CronPluginMultiple.php
@@ -7,7 +7,9 @@
  */
 namespace Drupal\ultimate_cron;
 
-class CronPluginMultiple extends \Drupal\ultimate_cron\CronPlugin {
+use Drupal\ultimate_cron\CronPlugin;
+
+class CronPluginMultiple extends CronPlugin {
   static public $multiple = TRUE;
 
   /**
@@ -42,7 +44,7 @@ class CronPluginMultiple extends \Drupal\ultimate_cron\CronPlugin {
 
     // No plugins = no settings = no vertical tabs for you mister!
     if (empty($plugins)) {
-      continue;
+      return;
     }
 
     $weight = 10;
diff --git a/src/Form/GeneralSettingsForm.php b/src/Form/GeneralSettingsForm.php
index 4369af1..d7efe9b 100644
--- a/src/Form/GeneralSettingsForm.php
+++ b/src/Form/GeneralSettingsForm.php
@@ -4,6 +4,7 @@
  */
 
 namespace Drupal\ultimate_cron\Form;
+use Drupal\Component\Plugin\PluginManagerInterface;
 use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\Datetime\DateFormatter;
 use Drupal\Core\Form\ConfigFormBase;
@@ -17,40 +18,38 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
 class GeneralSettingsForm extends ConfigFormBase {
 
   /**
-   * Stores the state storage service.
-   *
-   * @var \Drupal\Core\State\StateInterface
+   * {@inheritdoc}
    */
-  protected $state;
+  const CRON_PLUGIN_TYPE = 'settings';
 
   /**
-   * The cron service.
-   *
-   * @var \Drupal\Core\CronInterface
+   * {@inheritdoc}
    */
-  protected $cron;
+  public function getFormId() {
+    return 'ultimate_cron_general_settings';
+  }
 
   /**
-   * The date formatter service.
-   *
-   * @var \Drupal\Core\Datetime\DateFormatter
+   * {@inheritdoc}
+   */
+  protected function getEditableConfigNames() {
+    return ['ultimate_cron.settings'];
+  }
+
+  /**
+   * @var \Drupal\Component\Plugin\PluginManagerInterface
    */
-  protected $dateFormatter;
+  protected $pluginManager;
 
   /**
-   * Constructs a GeneralSettingsForm object.
+   * PluginSettingsFormBase constructor.
    *
    * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
-   *   The factory for configuration objects.
-   * @param \Drupal\Core\State\StateInterface $state
-   *   The state key value store.
-   * @param \Drupal\Core\Datetime\DateFormatter $date_formatter
-   *   The date formatter service.
+   * @param \Drupal\Component\Plugin\PluginManagerInterface $plugin_manager
    */
-  public function __construct(ConfigFactoryInterface $config_factory, StateInterface $state, DateFormatter $date_formatter) {
+  public function __construct(ConfigFactoryInterface $config_factory, PluginManagerInterface $plugin_manager) {
     parent::__construct($config_factory);
-    $this->state = $state;
-    $this->dateFormatter = $date_formatter;
+    $this->pluginManager = $plugin_manager;
   }
 
   /**
@@ -59,23 +58,27 @@ class GeneralSettingsForm extends ConfigFormBase {
   public static function create(ContainerInterface $container) {
     return new static(
       $container->get('config.factory'),
-      $container->get('state'),
-      $container->get('date.formatter')
+      $container->get('plugin.manager.ultimate_cron.' . static::CRON_PLUGIN_TYPE)
     );
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function getFormId() {
-    return 'ultimate_cron_general_settings';
-  }
 
   /**
-   * {@inheritdoc}
+   * Get all plugins for this form.
+   *
+   * @return \Drupal\ultimate_cron\CronPlugin[]
    */
-  protected function getEditableConfigNames() {
-    return ['ultimate_cron.settings'];
+  protected function getPlugins() {
+    $definitions = $this->pluginManager->getDefinitions();
+    /** @var \Drupal\ultimate_cron\CronPlugin[] $plugins */
+    $plugins = [];
+    $config = $this->config('ultimate_cron.settings');
+    $plugins_settings = $config->get(static::CRON_PLUGIN_TYPE)? : [];
+    foreach ($definitions as  $id => $definition) {
+      $config = isset($plugins_settings[$id])? $plugins_settings[$id]: [];
+      $plugins[$id] = $this->pluginManager->createInstance($id, $config);
+    }
+    return $plugins;
   }
 
   /**
@@ -83,114 +86,31 @@ class GeneralSettingsForm extends ConfigFormBase {
    */
   public function buildForm(array $form, FormStateInterface $form_state) {
     $config = $this->config('ultimate_cron.settings');
-    // Setup vertical tabs.
-    $form['settings_tabs'] = [
+    $plugins = $this->getPlugins();
+    $form['settings_tabs'] = array(
       '#type' => 'vertical_tabs',
-    ];
-
-    // @todo enable this when supported again
-    $form['nodejs'] = array(
-      '#type' => 'checkbox',
-      '#title' => t('nodejs'),
-      '#default_value' => $config->get('nodejs'),
-      '#description' => t('Enable nodejs integration (Live reload on jobs page. Requires the nodejs module to be installed and configured).'),
-      '#fallback' => TRUE,
-
-      '#access' => FALSE,
     );
 
-    // Queue settings. Visual hierarchy disabled since this is currently
-    // the only general settings group.
-    $form['queue'] = [
-      //'#type' => 'details',
-      //'#title' => 'queue',
-      //'#group' => 'settings_tabs',
+    $default_options = [];
+    $form['plugins'] = [
       '#tree' => TRUE,
     ];
-
-    $form['queue']['enabled'] = array(
-      '#title' => t('Enable cron queue processing'),
-      '#description' => t('If enabled, cron queues will be processed by this plugin. If another cron queue plugin is installed, it may be necessary/beneficial to disable this plugin.'),
-      '#type' => 'checkbox',
-      '#default_value' => $config->get('queue.enabled', TRUE),
-      '#fallback' => TRUE,
-    );
-
-    $form['queue']['timeouts'] = array(
-      '#type' => 'fieldset',
-      '#title' => t('Timeouts'),
-    );
-    $form['queue']['timeouts']['lease_time'] = array(
-      '#title' => t("Queue lease time"),
-      '#type' => 'number',
-      '#default_value' => $config->get('queue.timeouts.lease_time'),
-      '#description' => t('Seconds to claim a cron queue item.'),
-      '#fallback' => TRUE,
-      '#required' => TRUE,
-    );
-    $form['queue']['timeouts']['time'] = array(
-      '#title' => t('Time'),
-      '#type' => 'number',
-      '#default_value' => $config->get('queue.timeouts.time'),
-      '#description' => t('Time in seconds to process items during a cron run.'),
-      '#fallback' => TRUE,
-      '#required' => TRUE,
-    );
-
-    $form['queue']['delays'] = array(
-      '#type' => 'fieldset',
-      '#title' => t('Delays'),
-    );
-    $form['queue']['delays']['empty_delay'] = array(
-      '#title' => t("Empty delay"),
-      '#type' => 'number',
-      '#default_value' => $config->get('queue.delays.empty_delay'),
-      '#description' => t('Seconds to delay processing of queue if queue is empty (0 = end job).'),
-      '#fallback' => TRUE,
-      '#required' => TRUE,
-    );
-    $form['queue']['delays']['item_delay'] = array(
-      '#title' => t("Item delay"),
-      '#type' => 'number',
-      '#default_value' => $config->get('queue.delays.item_delay'),
-      '#description' => t('Seconds to wait between processing each item in a queue.'),
-      '#fallback' => TRUE,
-      '#required' => TRUE,
-    );
-
-    $states = array(
-      '#states' => array(
-        'visible' => array(':input[name="queue[throttle][enabled]"]' => array('checked' => TRUE)),
-      ),
-    );
-
-    $form['queue']['throttle'] = array(
-        '#type' => 'fieldset',
-        '#title' => t('Throttling'),
-      );
-    $form['queue']['throttle']['enabled'] = array(
-      '#title' => t('Throttle'),
-      '#type' => 'checkbox',
-      '#default_value' => $config->get('queue.throttle.enabled'),
-      '#description' => t('Throttle queues using multiple threads.'),
-    );
-    $form['queue']['throttle']['threads'] = array(
-      '#title' => t('Threads'),
-      '#type' => 'number',
-      '#default_value' => $config->get('queue.throttle.threads'),
-      '#description' => t('Number of threads to use for queues.'),
-      '#fallback' => TRUE,
-      '#required' => TRUE,
-    ) + $states;
-    $form['queue']['throttle']['threshold'] = array(
-      '#title' => t('Threshold'),
-      '#type' => 'number',
-      '#default_value' => $config->get('queue.throttle.threshold'),
-      '#description' => t('Number of items in queue required to activate the next cron job.'),
-      '#fallback' => TRUE,
-      '#required' => TRUE,
-    ) + $states;
-
+    foreach ($plugins as $id => $plugin) {
+      $definition = $plugin->getPluginDefinition();
+      $default_options[$id] = $definition['title'];
+
+      $form['plugins'][$id] = [
+        '#type' => 'details',
+        '#title' => $definition['title'],
+        '#group' => 'settings_tabs',
+        '#tree' => TRUE,
+      ];
+      $form['plugins'][$id] += $plugin->buildConfigurationForm([], $form_state);
+      $form['plugins'][$id]['id'] = [
+        '#type' => 'value',
+        '#value' => $id,
+      ];
+    }
     return parent::buildForm($form, $form_state);
   }
 
@@ -198,11 +118,26 @@ class GeneralSettingsForm extends ConfigFormBase {
    * {@inheritdoc}
    */
   public function submitForm(array &$form, FormStateInterface $form_state) {
-    $this->config('ultimate_cron.settings')
-      ->set('queue', $form_state->getValue('queue'))
-      ->save();
-
+    $form_state->cleanValues();
+    $config = $this->config('ultimate_cron.settings');
+    $values = $form_state->getValues();
+    // Set the default plugin for this type.
+    $config->set('default_plugins.' . static::CRON_PLUGIN_TYPE, $values['default_plugin']);
+    $config->set(static::CRON_PLUGIN_TYPE,$values['plugins']);
+    $config->save();
     parent::submitForm($form, $form_state);
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function validateForm(array &$form, FormStateInterface $form_state) {
+    parent::validateForm($form, $form_state);
+    $plugins = $this->getPlugins();
+    // Validate each plugin form.
+    foreach ($plugins as $plugin) {
+      $plugin->validateConfigurationForm($form, $form_state);
+    }
+  }
+
 }
diff --git a/src/Plugin/ultimate_cron/Settings/QueueSettings.php b/src/Plugin/ultimate_cron/Settings/QueueSettings.php
new file mode 100644
index 0000000..1ba345e
--- /dev/null
+++ b/src/Plugin/ultimate_cron/Settings/QueueSettings.php
@@ -0,0 +1,375 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\ultimate_cron\QueueSettings.
+ *
+ * Queue settings for Ultimate Cron.
+ */
+
+namespace Drupal\ultimate_cron\Plugin\ultimate_cron\Settings;
+
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Logger\RfcLogLevel;
+use Drupal\ultimate_cron\Entity\CronJob;
+use Drupal\ultimate_cron\Settings\TaggedSettings;
+
+/**
+ * Queue Settings.
+ *
+ * @SettingsPlugin(
+ *   id = "queuesettings",
+ *   title = @Translation("Queue Settings"),
+ *   description = @Translation("Enable cron queue processing."),
+ * )
+ */
+class QueueSettings extends TaggedSettings {
+  static private $throttled = array();
+  static private $queues = NULL;
+
+  /**
+   * Get cron queues and static cache them.
+   *
+   * Works like module_invoke_all('cron_queue_info'), but adds
+   * a 'module' to each item.
+   *
+   * @return array
+   *   Cron queue definitions.
+   */
+  private function get_queues() {
+    $module_handler = \Drupal::moduleHandler();
+    if (!isset(self::$queues)) {
+      $queues = array();
+      foreach ($module_handler->getImplementations('cron_queue_info') as $module) {
+        $items = $module_handler->invoke($module, 'cron_queue_info');
+        if (is_array($items)) {
+          foreach ($items as &$item) {
+            $item['module'] = $module;
+          }
+          $queues += $items;
+        }
+      }
+      $module_handler->alter('cron_queue_info', $queues);
+      self::$queues = $queues;
+    }
+    return $queues;
+  }
+
+  /**
+   * Implements hook_cronapi().
+   */
+  public function cronapi() {
+    $items = array();
+    if (!variable_get($this->key . '_enabled', TRUE)) {
+      return $items;
+    }
+
+    // Grab the defined cron queues.
+    $queues = self::get_queues();
+
+    foreach ($queues as $name => $info) {
+      if (!empty($info['skip on cron'])) {
+        continue;
+      }
+
+      $items['queue_' . $name] = array(
+        'title' => t('Queue: @name', array('@name' => $name)),
+        'callback' => array(get_class($this), 'worker_callback'),
+        'scheduler' => array(
+          'simple' => array(
+            'rules' => array('* * * * *'),
+          ),
+          'crontab' => array(
+            'rules' => array('* * * * *'),
+          ),
+        ),
+        'settings' => array(
+          'queue' => array(
+            'name' => $name,
+            'worker callback' => $info['worker callback'],
+          ),
+        ),
+        'tags' => array('queue', 'core', 'killable'),
+        'module' => $info['module'],
+      );
+      if (isset($info['time'])) {
+        $items['queue_' . $name]['settings']['queue']['time'] = $info['time'];
+      }
+    }
+
+    return $items;
+  }
+
+  /**
+   * Process a cron queue.
+   *
+   * This is a wrapper around the cron queues "worker callback".
+   *
+   * @param CronJob $job
+   *   The job being run.
+   */
+  static public function worker_callback($job) {
+    $settings = $job->getPluginSettings('settings');
+    $queue = \Drupal::queue($settings['queue']['name']);
+    $function = $settings['queue']['worker callback'];
+
+    $end = microtime(TRUE) + $settings['queue']['time'];
+    $items = 0;
+    while (microtime(TRUE) < $end) {
+      if ($job->getSignal('kill')) {
+        \Drupal::logger('ultimate_cron')->warning('kill signal recieved');
+        break;
+      }
+      $item = $queue->claimItem($settings['queue']['lease_time']);
+      if (!$item) {
+        if ($settings['queue']['empty_delay']) {
+          usleep($settings['queue']['empty_delay'] * 1000000);
+          continue;
+        }
+        else {
+          break;
+        }
+      }
+      try {
+        if ($settings['queue']['item_delay']) {
+          if ($items == 0) {
+            // Move the boundary if using a throttle, to avoid waiting for nothing.
+            $end -= $settings['queue']['item_delay'] * 1000000;
+          }
+          else {
+            // Sleep before retrieving.
+            usleep($settings['queue']['item_delay'] * 1000000);
+          }
+        }
+        $function($item->data);
+        $queue->deleteItem($item);
+        $items++;
+      }
+      catch (\Exception $e) {
+        // Just continue ...
+        \Drupal::logger($job->hook['module'])->error("Queue item @item_id from queue @queue failed with message @message", array(
+          '@item_id' => $item->item_id,
+          '@queue' => $settings['queue']['name'],
+          '@message' => $e->getMessage()
+        ));
+      }
+    }
+    \Drupal::logger($job->hook['module'])->info('Processed @items items from queue @queue', array(
+      '@items' => $items,
+      '@queue' => $settings['queue']['name'],
+    ));
+
+    // Re-throttle.
+    $job->getPlugin('settings', 'queue')->throttle($job);
+
+    return;
+  }
+
+  /**
+   * Implements hook_cron_alter().
+   */
+  public function cron_alter(&$jobs) {
+    $new_jobs = array();
+    foreach ($jobs as $job) {
+      if (!$this->isValid($job)) {
+        continue;
+      }
+      $settings = $job->getSettings();
+      if (isset($settings['settings']['queue']['name'])) {
+        if ($settings['settings']['queue']['throttle']) {
+          for ($i = 2; $i <= $settings['settings']['queue']['threads']; $i++) {
+            $name = $job->id() . '_' . $i;
+            $hook = $job->hook;
+            $hook['settings']['queue']['master'] = $job->id();
+            $hook['settings']['queue']['thread'] = $i;
+            $hook['name'] = $name;
+            $hook['title'] .= " (#$i)";
+            $hook['immutable'] = TRUE;
+            $new_jobs[$name] = ultimate_cron_prepare_job($name, $hook);
+            $new_jobs[$name]->settings = $settings + $new_jobs[$name]->settings;
+            $new_jobs[$name]->title = $job->title . " (#$i)";
+          }
+        }
+      }
+    }
+    $jobs += $new_jobs;
+  }
+
+  /**
+   * Implements hook_cron_alter().
+   */
+  public function cron_pre_schedule($job) {
+    $queue_name = !empty($job->hook['settings']['queue']['name']) ? $job->hook['settings']['queue']['name'] : FALSE;
+    if ($queue_name) {
+      if (empty(self::$throttled[$job->id()])) {
+        self::$throttled[$job->id()] = TRUE;
+        $this->throttle($job);
+      }
+    }
+  }
+
+  /**
+   * Default settings.
+   */
+  public function defaultConfiguration() {
+    return array(
+      'lease_time' => 30,
+      'empty_delay' => 0,
+      'item_delay' => 0,
+      'throttle' => FALSE,
+      'threads' => 4,
+      'threshold' => 10,
+      'time' => 15,
+    );
+  }
+
+  /**
+   * Settings form.
+   */
+  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
+    $config = \Drupal::service('config.factory')->get('ultimate_cron.settings');
+    $plugin_id = $this->pluginId;
+    $defination = $this->getPluginDefinition();
+
+    $form = [
+      '#type' => 'fieldset',
+      '#title' => $defination['title'],
+      '#tree' => TRUE,
+    ];
+
+    $form['queue']['enabled'] = [
+      '#title' => t('Enable cron queue processing'),
+      '#description' => t('If enabled, cron queues will be processed by this plugin. If another cron queue plugin is installed, it may be necessary/beneficial to disable this plugin.'),
+      '#type' => 'checkbox',
+      '#default_value' => $config->get('queue.enabled', TRUE),
+      '#fallback' => TRUE,
+    ];
+
+    $form['queue']['timeouts'] = [
+      '#type' => 'fieldset',
+      '#title' => t('Timeouts'),
+    ];
+    $form['queue']['timeouts']['lease_time'] = [
+      '#title' => t("Queue lease time"),
+      '#type' => 'number',
+      '#default_value' => $config->get('queue.timeouts.lease_time'),
+      '#description' => t('Seconds to claim a cron queue item.'),
+      '#fallback' => TRUE,
+      '#required' => TRUE,
+    ];
+    $form['queue']['timeouts']['time'] = [
+      '#title' => t('Time'),
+      '#type' => 'number',
+      '#default_value' => $config->get('queue.timeouts.time'),
+      '#description' => t('Time in seconds to process items during a cron run.'),
+      '#fallback' => TRUE,
+      '#required' => TRUE,
+    ];
+
+    $form['queue']['delays'] = [
+      '#type' => 'fieldset',
+      '#title' => t('Delays'),
+    ];
+    $form['queue']['delays']['empty_delay'] = [
+      '#title' => t("Empty delay"),
+      '#type' => 'number',
+      '#default_value' => $config->get('queue.delays.empty_delay'),
+      '#description' => t('Seconds to delay processing of queue if queue is empty (0 = end job).'),
+      '#fallback' => TRUE,
+      '#required' => TRUE,
+    ];
+    $form['queue']['delays']['item_delay'] = [
+      '#title' => t("Item delay"),
+      '#type' => 'number',
+      '#default_value' => $config->get('queue.delays.item_delay'),
+      '#description' => t('Seconds to wait between processing each item in a queue.'),
+      '#fallback' => TRUE,
+      '#required' => TRUE,
+    ];
+
+    $states = [
+      '#states' => [
+        'visible' => [':input[name="queue[throttle][enabled]"]' => ['checked' => TRUE]],
+      ],
+    ];
+
+    $form['queue']['throttle'] = [
+      '#type' => 'fieldset',
+      '#title' => t('Throttling'),
+    ];
+    $form['queue']['throttle']['enabled'] = [
+      '#title' => t('Throttle'),
+      '#type' => 'checkbox',
+      '#default_value' => $config->get('queue.throttle.enabled'),
+      '#description' => t('Throttle queues using multiple threads.'),
+    ];
+    $form['queue']['throttle']['threads'] = [
+        '#title' => t('Threads'),
+        '#type' => 'number',
+        '#default_value' => $config->get('queue.throttle.threads'),
+        '#description' => t('Number of threads to use for queues.'),
+        '#fallback' => TRUE,
+        '#required' => TRUE,
+      ] + $states;
+    $form['queue']['throttle']['threshold'] = [
+        '#title' => t('Threshold'),
+        '#type' => 'number',
+        '#default_value' => $config->get('queue.throttle.threshold'),
+        '#description' => t('Number of items in queue required to activate the next cron job.'),
+        '#fallback' => TRUE,
+        '#required' => TRUE,
+      ] + $states;
+
+    return $form;
+  }
+
+  /**
+   * Form submit handler.
+   */
+  public function settingsFormSubmit(&$form, &$form_state, $job = NULL) {
+    if (!$job) {
+      $values = &$form_state['values']['settings'][$this->type][$this->name];
+      variable_set($this->key . '_enabled', $values['enabled']);
+      unset($values['enabled']);
+    }
+  }
+
+  /**
+   * Throttle queues.
+   *
+   * Enables or disables queue threads depending on remaining items in queue.
+   */
+  public function throttle($job) {
+    if (!empty($job->hook['settings']['queue']['master'])) {
+      // We always base the threads on the master.
+      $master_job = ultimate_cron_job_load($job->hook['settings']['queue']['master']);
+      $settings = $master_job->getSettings('settings');
+    }
+    else {
+      return;
+    }
+    if ($settings['queue']['throttle']) {
+      $queue = \Drupal::queue($settings['queue']['name']);
+      $items = $queue->numberOfItems();
+      $thread = $job->hook['settings']['queue']['thread'];
+
+      $name = $master_job->name . '_' . $thread;
+      $status = empty($master_job->disabled) && ($items >= ($thread - 1) * $settings['queue']['threshold']);
+      $new_status = !$status ? TRUE : FALSE;
+      $old_status = ultimate_cron_job_get_status($name) ? TRUE : FALSE;
+      if ($old_status !== $new_status) {
+        $log_entry = $job->startLog(uniqid($job->id(), TRUE), 'throttling', ULTIMATE_CRON_LOG_TYPE_ADMIN);
+        $log_entry->log($job->id(), 'Job @status by queue throttling (items:@items, boundary:@boundary, threshold:@threshold)', array(
+          '@status' => $new_status ? t('disabled') : t('enabled'),
+          '@items' => $items,
+          '@boundary' => ($thread - 1) * $settings['queue']['threshold'],
+          '@threshold' => $settings['queue']['threshold'],
+        ), RfcLogLevel::INFO);
+        $log_entry->finish();
+        $job->dont_log = TRUE;
+        ultimate_cron_job_set_status($job, $new_status);
+        $job->disabled = $new_status;
+      }
+    }
+  }
+}
diff --git a/src/QueueSettings.php b/src/QueueSettings.php
deleted file mode 100644
index 4440872..0000000
--- a/src/QueueSettings.php
+++ /dev/null
@@ -1,384 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\ultimate_cron\QueueSettings.
- *
- * Queue settings for Ultimate Cron.
- */
-
-namespace Drupal\ultimate_cron;
-
-use Drupal\Core\Logger\RfcLogLevel;
-use Drupal\ultimate_cron\Entity\CronJob;
-use Drupal\ultimate_cron\TaggedSettings;
-
-/**
- * Queue settings plugin class.
- */
-class QueueSettings extends TaggedSettings {
-  static private $throttled = array();
-  static private $queues = NULL;
-
-  /**
-   * Get cron queues and static cache them.
-   *
-   * Works like module_invoke_all('cron_queue_info'), but adds
-   * a 'module' to each item.
-   *
-   * @return array
-   *   Cron queue definitions.
-   */
-  private function get_queues() {
-    if (!isset(self::$queues)) {
-      $queues = array();
-      foreach (module_implements('cron_queue_info') as $module) {
-        $items = module_invoke($module, 'cron_queue_info');
-        if (is_array($items)) {
-          foreach ($items as &$item) {
-            $item['module'] = $module;
-          }
-          $queues += $items;
-        }
-      }
-      drupal_alter('cron_queue_info', $queues);
-      self::$queues = $queues;
-    }
-    return $queues;
-  }
-
-  /**
-   * Implements hook_cronapi().
-   */
-  public function cronapi() {
-    $items = array();
-    if (!variable_get($this->key . '_enabled', TRUE)) {
-      return $items;
-    }
-
-    // Grab the defined cron queues.
-    $queues = self::get_queues();
-
-    foreach ($queues as $name => $info) {
-      if (!empty($info['skip on cron'])) {
-        continue;
-      }
-
-      $items['queue_' . $name] = array(
-        'title' => t('Queue: @name', array('@name' => $name)),
-        'callback' => array(get_class($this), 'worker_callback'),
-        'scheduler' => array(
-          'simple' => array(
-            'rules' => array('* * * * *'),
-          ),
-          'crontab' => array(
-            'rules' => array('* * * * *'),
-          ),
-        ),
-        'settings' => array(
-          'queue' => array(
-            'name' => $name,
-            'worker callback' => $info['worker callback'],
-          ),
-        ),
-        'tags' => array('queue', 'core', 'killable'),
-        'module' => $info['module'],
-      );
-      if (isset($info['time'])) {
-        $items['queue_' . $name]['settings']['queue']['time'] = $info['time'];
-      }
-    }
-
-    return $items;
-  }
-
-  /**
-   * Process a cron queue.
-   *
-   * This is a wrapper around the cron queues "worker callback".
-   *
-   * @param CronJob $job
-   *   The job being run.
-   */
-  static public function worker_callback($job) {
-    $settings = $job->getPluginSettings('settings');
-    $queue = DrupalQueue::get($settings['queue']['name']);
-    $function = $settings['queue']['worker callback'];
-
-    $end = microtime(TRUE) + $settings['queue']['time'];
-    $items = 0;
-    while (microtime(TRUE) < $end) {
-      if ($job->getSignal('kill')) {
-        \Drupal::logger('ultimate_cron')->warning('kill signal recieved');
-        break;
-      }
-
-      $item = $queue->claimItem($settings['queue']['lease_time']);
-      if (!$item) {
-        if ($settings['queue']['empty_delay']) {
-          usleep($settings['queue']['empty_delay'] * 1000000);
-          continue;
-        }
-        else {
-          break;
-        }
-      }
-      try {
-        if ($settings['queue']['item_delay']) {
-          if ($items == 0) {
-            // Move the boundary if using a throttle, to avoid waiting for nothing.
-            $end -= $settings['queue']['item_delay'] * 1000000;
-          }
-          else {
-            // Sleep before retrieving.
-            usleep($settings['queue']['item_delay'] * 1000000);
-          }
-        }
-        $function($item->data);
-        $queue->deleteItem($item);
-        $items++;
-      }
-      catch (Exception $e) {
-        // Just continue ...
-        \Drupal::logger($job->hook['module'])->error("Queue item @item_id from queue @queue failed with message @message", array(
-          '@item_id' => $item->item_id,
-          '@queue' => $settings['queue']['name'],
-          '@message' => $e->getMessage()
-        ));
-      }
-    }
-    \Drupal::logger($job->hook['module'])->info('Processed @items items from queue @queue', array(
-      '@items' => $items,
-      '@queue' => $settings['queue']['name'],
-    ));
-
-    // Re-throttle.
-    $job->getPlugin('settings', 'queue')->throttle($job);
-
-    return;
-  }
-
-  /**
-   * Implements hook_cron_alter().
-   */
-  public function cron_alter(&$jobs) {
-    $new_jobs = array();
-    foreach ($jobs as $job) {
-      if (!$this->isValid($job)) {
-        continue;
-      }
-      $settings = $job->getSettings();
-      if (isset($settings['settings']['queue']['name'])) {
-        if ($settings['settings']['queue']['throttle']) {
-          for ($i = 2; $i <= $settings['settings']['queue']['threads']; $i++) {
-            $name = $job->id() . '_' . $i;
-            $hook = $job->hook;
-            $hook['settings']['queue']['master'] = $job->id();
-            $hook['settings']['queue']['thread'] = $i;
-            $hook['name'] = $name;
-            $hook['title'] .= " (#$i)";
-            $hook['immutable'] = TRUE;
-            $new_jobs[$name] = ultimate_cron_prepare_job($name, $hook);
-            $new_jobs[$name]->settings = $settings + $new_jobs[$name]->settings;
-            $new_jobs[$name]->title = $job->title . " (#$i)";
-          }
-        }
-      }
-    }
-    $jobs += $new_jobs;
-  }
-
-  /**
-   * Implements hook_cron_alter().
-   */
-  public function cron_pre_schedule($job) {
-    $queue_name = !empty($job->hook['settings']['queue']['name']) ? $job->hook['settings']['queue']['name'] : FALSE;
-    if ($queue_name) {
-      if (empty(self::$throttled[$job->id()])) {
-        self::$throttled[$job->id()] = TRUE;
-        $this->throttle($job);
-      }
-    }
-  }
-
-  /**
-   * Default settings.
-   */
-  public function defaultSettings() {
-    return array(
-      'lease_time' => 30,
-      'empty_delay' => 0,
-      'item_delay' => 0,
-      'throttle' => FALSE,
-      'threads' => 4,
-      'threshold' => 10,
-      'time' => 15,
-    );
-  }
-
-  /**
-   * Settings form.
-   */
-  public function settingsForm(&$form, &$form_state, $job = NULL) {
-    $elements = &$form['settings'][$this->type][$this->name];
-    $values = &$form_state['values']['settings'][$this->type][$this->name];
-
-    $states = array();
-    if (!$job) {
-      $elements['enabled'] = array(
-        '#title' => t('Enable cron queue processing'),
-        '#description' => t('If enabled, cron queues will be processed by this plugin. If another cron queue plugin is installed, it may be necessary/beneficial to disable this plugin.'),
-        '#type' => 'checkbox',
-        '#default_value' => variable_get($this->key . '_enabled', TRUE),
-        '#fallback' => TRUE,
-      );
-      $states = array(
-        '#states' => array(
-          'visible' => array(
-            ':input[name="settings[' . $this->type . '][' . $this->name . '][enabled]"]' => array(
-              'checked' => TRUE,
-            ),
-          ),
-        ),
-      );
-    }
-
-    $elements['timeouts'] = array(
-      '#type' => 'fieldset',
-      '#title' => t('Timeouts'),
-    ) + $states;
-    $elements['timeouts']['lease_time'] = array(
-      '#parents' => array('settings', $this->type, $this->name, 'lease_time'),
-      '#title' => t("Queue lease time"),
-      '#type' => 'textfield',
-      '#default_value' => $values['lease_time'],
-      '#description' => t('Seconds to claim a cron queue item.'),
-      '#fallback' => TRUE,
-      '#required' => TRUE,
-    );
-    $elements['timeouts']['time'] = array(
-      '#parents' => array('settings', $this->type, $this->name, 'time'),
-      '#title' => t('Time'),
-      '#type' => 'textfield',
-      '#default_value' => $values['time'],
-      '#description' => t('Time in seconds to process items during a cron run.'),
-      '#fallback' => TRUE,
-      '#required' => TRUE,
-    );
-
-    $elements['delays'] = array(
-      '#type' => 'fieldset',
-      '#title' => t('Delays'),
-    ) + $states;
-    $elements['delays']['empty_delay'] = array(
-      '#parents' => array('settings', $this->type, $this->name, 'empty_delay'),
-      '#title' => t("Empty delay"),
-      '#type' => 'textfield',
-      '#default_value' => $values['empty_delay'],
-      '#description' => t('Seconds to delay processing of queue if queue is empty (0 = end job).'),
-      '#fallback' => TRUE,
-      '#required' => TRUE,
-    );
-    $elements['delays']['item_delay'] = array(
-      '#parents' => array('settings', $this->type, $this->name, 'item_delay'),
-      '#title' => t("Item delay"),
-      '#type' => 'textfield',
-      '#default_value' => $values['item_delay'],
-      '#description' => t('Seconds to wait between processing each item in a queue.'),
-      '#fallback' => TRUE,
-      '#required' => TRUE,
-    );
-
-    $elements['throttle'] = array(
-      '#title' => t('Throttle'),
-      '#type' => 'checkbox',
-      '#default_value' => $values['throttle'],
-      '#description' => t('Throttle queues using multiple threads.'),
-    );
-
-    $states = !$job ? $states : array(
-      '#states' => array(
-        'visible' => array(':input[name="settings[' . $this->type . '][' . $this->name . '][throttle]"]' => array('checked' => TRUE))
-      ),
-    );
-
-    $elements['throttling'] = array(
-      '#type' => 'fieldset',
-      '#title' => t('Throttling'),
-    ) + $states;
-    $elements['throttling']['threads'] = array(
-      '#parents' => array('settings', $this->type, $this->name, 'threads'),
-      '#title' => t('Threads'),
-      '#type' => 'textfield',
-      '#default_value' => $values['threads'],
-      '#description' => t('Number of threads to use for queues.'),
-      '#states' => array(
-        'visible' => array(':input[name="settings[' . $this->type . '][' . $this->name . '][throttle]"]' => array('checked' => TRUE))
-      ),
-      '#fallback' => TRUE,
-      '#required' => TRUE,
-    );
-    $elements['throttling']['threshold'] = array(
-      '#parents' => array('settings', $this->type, $this->name, 'threshold'),
-      '#title' => t('Threshold'),
-      '#type' => 'textfield',
-      '#default_value' => $values['threshold'],
-      '#description' => t('Number of items in queue required to activate the next cron job.'),
-      '#states' => array(
-        'visible' => array(':input[name="settings[' . $this->type . '][' . $this->name . '][throttle]"]' => array('checked' => TRUE))
-      ),
-      '#fallback' => TRUE,
-      '#required' => TRUE,
-    );
-  }
-
-  /**
-   * Form submit handler.
-   */
-  public function settingsFormSubmit(&$form, &$form_state, $job = NULL) {
-    if (!$job) {
-      $values = &$form_state['values']['settings'][$this->type][$this->name];
-      variable_set($this->key . '_enabled', $values['enabled']);
-      unset($values['enabled']);
-    }
-  }
-
-  /**
-   * Throttle queues.
-   *
-   * Enables or disables queue threads depending on remaining items in queue.
-   */
-  public function throttle($job) {
-    if (!empty($job->hook['settings']['queue']['master'])) {
-      // We always base the threads on the master.
-      $master_job = ultimate_cron_job_load($job->hook['settings']['queue']['master']);
-      $settings = $master_job->getSettings('settings');
-    }
-    else {
-      return;
-    }
-    if ($settings['queue']['throttle']) {
-      $queue = DrupalQueue::get($settings['queue']['name']);
-      $items = $queue->numberOfItems();
-      $thread = $job->hook['settings']['queue']['thread'];
-
-      $name = $master_job->name . '_' . $thread;
-      $status = empty($master_job->disabled) && ($items >= ($thread - 1) * $settings['queue']['threshold']);
-      $new_status = !$status ? TRUE : FALSE;
-      $old_status = ultimate_cron_job_get_status($name) ? TRUE : FALSE;
-      if ($old_status !== $new_status) {
-        $log_entry = $job->startLog(uniqid($job->id(), TRUE), 'throttling', ULTIMATE_CRON_LOG_TYPE_ADMIN);
-        $log_entry->log($job->id(), 'Job @status by queue throttling (items:@items, boundary:@boundary, threshold:@threshold)', array(
-          '@status' => $new_status ? t('disabled') : t('enabled'),
-          '@items' => $items,
-          '@boundary' => ($thread - 1) * $settings['queue']['threshold'],
-          '@threshold' => $settings['queue']['threshold'],
-        ), RfcLogLevel::INFO);
-        $log_entry->finish();
-        $job->dont_log = TRUE;
-        ultimate_cron_job_set_status($job, $new_status);
-        $job->disabled = $new_status;
-      }
-    }
-  }
-}
diff --git a/src/Settings.php b/src/Settings.php
deleted file mode 100644
index 1f1771e..0000000
--- a/src/Settings.php
+++ /dev/null
@@ -1,18 +0,0 @@
-<?php
-/**
- * Created by PhpStorm.
- * User: berdir
- * Date: 4/4/14
- * Time: 3:03 PM
- */
-
-namespace Drupal\ultimate_cron;
-use Drupal\Core\Form\FormBase;
-
-/**
- * Base class for settings.
- *
- * There's nothing special about this plugin.
- */
-class Settings extends CronPluginMultiple {
-}
diff --git a/src/Settings/SettingsBase.php b/src/Settings/SettingsBase.php
new file mode 100644
index 0000000..9e64d51
--- /dev/null
+++ b/src/Settings/SettingsBase.php
@@ -0,0 +1,21 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: berdir
+ * Date: 4/4/14
+ * Time: 3:03 PM
+ */
+
+namespace Drupal\ultimate_cron\Settings;
+
+use Drupal\Core\Form\FormBase;
+use Drupal\ultimate_cron\CronPluginMultiple;
+use Drupal\ultimate_cron\Settings\SettingsInterface;
+
+/**
+ * Base class for settings.
+ *
+ * There's nothing special about this plugin.
+ */
+abstract class SettingsBase extends CronPluginMultiple implements SettingsInterface {
+}
diff --git a/src/Settings/SettingsInterface.php b/src/Settings/SettingsInterface.php
new file mode 100644
index 0000000..7773f0c
--- /dev/null
+++ b/src/Settings/SettingsInterface.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * Contains \Drupal\ultimate_cron\Settings\SettingsInterface.
+ */
+
+namespace Drupal\ultimate_cron\Settings;
+
+use Drupal\Component\Plugin\ConfigurablePluginInterface;
+use Drupal\Component\Plugin\PluginInspectionInterface;
+use Drupal\Core\Plugin\PluginFormInterface;
+use Drupal\ultimate_cron\Entity\CronJob;
+
+/**
+ * Defines a scheduler method.
+ */
+interface SettingsInterface extends PluginInspectionInterface, ConfigurablePluginInterface, PluginFormInterface {
+
+  /**
+   * Returns the default configuration.
+   *
+   * @return mixed
+   */
+  public function defaultConfiguration();
+
+}
diff --git a/src/Settings/SettingsManager.php b/src/Settings/SettingsManager.php
new file mode 100644
index 0000000..dd6a828
--- /dev/null
+++ b/src/Settings/SettingsManager.php
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\ultimate_cron\Settings\SettingsManager.
+ */
+
+namespace Drupal\ultimate_cron\Settings;
+
+use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\ultimate_cron\PluginManagerBase;
+
+/**
+ * A plugin manager for launcher plugins.
+ */
+class SettingsManager extends PluginManagerBase {
+
+  /**
+   * Constructs a SettingsManager object.
+   *
+   * @param \Traversable $namespaces
+   *   An object that implements \Traversable which contains the root paths
+   *   keyed by the corresponding namespace to look for plugin implementations.
+   * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
+   *   Cache backend instance to use.
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   *   The module handler to invoke the alter hook with.
+   */
+  public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
+    parent::__construct('Plugin/ultimate_cron/Settings', $namespaces, $module_handler, '\Drupal\ultimate_cron\Settings\SettingsInterface', 'Drupal\ultimate_cron\Annotation\SettingsPlugin');
+    $this->alterInfo('ultimate_cron_settings_info');
+    $this->setCacheBackend($cache_backend, 'ultimate_cron_settings');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function pluginType() {
+    return 'settings';
+  }
+
+}
diff --git a/src/Settings/TaggedSettings.php b/src/Settings/TaggedSettings.php
new file mode 100644
index 0000000..5133d97
--- /dev/null
+++ b/src/Settings/TaggedSettings.php
@@ -0,0 +1,25 @@
+<?php
+/**
+ * @file
+ * Plugin framework for Ultimate Cron.
+ */
+
+namespace Drupal\ultimate_cron\Settings;
+
+use Drupal\ultimate_cron\Entity\CronJob;
+
+
+/**
+ * Base class for tagged settings.
+ *
+ * Settings plugins using this as a base class, will only be available
+ * to jobs having the same tag as the name of the plugin.
+ */
+abstract class TaggedSettings extends SettingsBase {
+  /**
+   * Only valid for jobs tagged with the proper tag.
+   */
+  public function isValid($job = NULL) {
+    return $job ? in_array($this->name, $job->hook['tags']) : \Drupal\ultimate_cron\parent::isValid();
+  }
+}
diff --git a/src/TaggedSettings.php b/src/TaggedSettings.php
deleted file mode 100644
index 62b453c..0000000
--- a/src/TaggedSettings.php
+++ /dev/null
@@ -1,24 +0,0 @@
-<?php
-/**
- * @file
- * Plugin framework for Ultimate Cron.
- */
-namespace Drupal\ultimate_cron;
-
-use Drupal\ultimate_cron\Entity\CronJob;
-
-
-/**
- * Base class for tagged settings.
- *
- * Settings plugins using this as a base class, will only be available
- * to jobs having the same tag as the name of the plugin.
- */
-class TaggedSettings extends Settings {
-  /**
-   * Only valid for jobs tagged with the proper tag.
-   */
-  public function isValid($job = NULL) {
-    return $job ? in_array($this->name, $job->hook['tags']) : \Drupal\ultimate_cron\parent::isValid();
-  }
-}
diff --git a/ultimate_cron.links.task.yml b/ultimate_cron.links.task.yml
index 54e0a37..386f900 100644
--- a/ultimate_cron.links.task.yml
+++ b/ultimate_cron.links.task.yml
@@ -14,7 +14,7 @@ ultimate_cron.settings:
   base_route: entity.ultimate_cron_job.collection
 
 ultimate_cron.general_settings:
-  title: Queue
+  title: General Settings
   route_name: ultimate_cron.general_settings
   parent_id: ultimate_cron.settings
 
diff --git a/ultimate_cron.services.yml b/ultimate_cron.services.yml
index b8f87e5..e77cd1c 100644
--- a/ultimate_cron.services.yml
+++ b/ultimate_cron.services.yml
@@ -14,6 +14,9 @@ services:
   plugin.manager.ultimate_cron.scheduler:
     class: Drupal\ultimate_cron\Scheduler\SchedulerManager
     parent: default_plugin_manager
+  plugin.manager.ultimate_cron.settings:
+    class: Drupal\ultimate_cron\Settings\SettingsManager
+    parent: default_plugin_manager
   ultimate_cron.lock:
     class: Drupal\ultimate_cron\Lock\Lock
     arguments: ['@database']
