diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index c6e501c3b036a59869fcb24480ebdc535ded7fa8..c5afb32514ead2450fcad4b9989de009f9a280b5 100644
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -1009,42 +1009,24 @@ static ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER;
 static pthread_t poll_thread = AST_PTHREADT_NULL;
 static unsigned char poll_thread_run;
 
-/*! Subscription to MWI event subscription changes */
-static struct stasis_subscription *mwi_sub_sub;
-
 /*!
- * \brief An MWI subscription
+ * \brief A mailbox to be polled
  *
- * This is so we can keep track of which mailboxes are subscribed to.
  * This way, we know which mailboxes to poll when the pollmailboxes
  * option is being used.
  */
-struct mwi_sub {
-	AST_RWLIST_ENTRY(mwi_sub) entry;
+struct poll_state {
+	int marked_used;
 	int old_urgent;
 	int old_new;
 	int old_old;
-	char *uniqueid;
 	char mailbox[0];
 };
 
-struct mwi_sub_task {
-	const char *mailbox;
-	const char *context;
-	const char *uniqueid;
-};
-
-static void mwi_sub_task_dtor(struct mwi_sub_task *mwist)
-{
-	ast_free((void *) mwist->mailbox);
-	ast_free((void *) mwist->context);
-	ast_free((void *) mwist->uniqueid);
-	ast_free(mwist);
-}
-
-static struct ast_taskprocessor *mwi_subscription_tps;
-
-static AST_RWLIST_HEAD_STATIC(mwi_subs, mwi_sub);
+#define POLL_LIST_BUCKETS 511
+static struct ao2_container *poll_list;
+AO2_STRING_FIELD_HASH_FN(poll_state, mailbox);
+AO2_STRING_FIELD_CMP_FN(poll_state, mailbox);
 
 /* custom audio control prompts for voicemail playback */
 static char listen_control_forward_key[12];
@@ -1122,7 +1104,7 @@ static const char *substitute_escapes(const char *value);
 static int message_range_and_existence_check(struct vm_state *vms, const char *msg_ids [], size_t num_msgs, int *msg_nums, struct ast_vm_user *vmu);
 static void notify_new_state(struct ast_vm_user *vmu);
 static int append_vmu_info_astman(struct mansession *s, struct ast_vm_user *vmu, const char* event_name, const char* actionid);
-
+static int poll_mailbox(void *obj, void *arg, int flags);
 
 /*!
  * Place a message in the indicated folder
@@ -12310,6 +12292,59 @@ static int add_message_id(struct ast_config *msg_cfg, char *dir, int msg, char *
 	return 0;
 }
 
+static void poll_state_dtor(void *obj)
+{
+	struct poll_state *poll_state = obj;
+
+	ast_debug(3, "DTOR: Mailbox: %s New: %d  Old: %d  Urgent: %d  Marked Used: %d\n", poll_state->mailbox,
+		poll_state->old_new, poll_state->old_old, poll_state->old_urgent,
+		poll_state->marked_used);
+}
+
+static int mark_or_create_poll_state(struct ast_vm_user *vmu)
+{
+	size_t len;
+	struct poll_state *poll_state;
+	char *mailbox;
+
+	if (ast_strlen_zero(vmu->mailbox)) {
+		ast_log(LOG_ERROR, "Mailbox can't be empty\n");
+		return -1;
+	}
+
+	len = sizeof(vmu->mailbox) + sizeof(vmu->context) + sizeof('@') + 1;
+	mailbox = ast_alloca(len);
+	len = snprintf(mailbox, len, "%s%s%s",
+		vmu->mailbox,
+		ast_strlen_zero(vmu->context) ? "" : "@",
+		vmu->context);
+
+	len++; /* For NULL terminator */
+
+	poll_state = ao2_find(poll_list, mailbox, OBJ_SEARCH_KEY);
+	if (poll_state) {
+		poll_state->marked_used = 1;
+		ao2_ref(poll_state, -1);
+		return 0;
+	}
+
+	poll_state = ao2_alloc_options(len + sizeof(*poll_state), poll_state_dtor,
+		AO2_ALLOC_OPT_LOCK_NOLOCK);
+	if (!poll_state) {
+		return -1;
+	}
+	strcpy(poll_state->mailbox, mailbox); /* Safe */
+	poll_state->marked_used = 1;
+
+	ao2_link_flags(poll_list, poll_state, OBJ_NOLOCK);
+
+	poll_mailbox(poll_state, NULL, 0);
+
+	ao2_ref(poll_state, -1);
+
+	return 0;
+}
+
 static struct ast_vm_user *find_or_create(const char *context, const char *box)
 {
 	struct ast_vm_user *vmu;
@@ -12339,12 +12374,18 @@ static struct ast_vm_user *find_or_create(const char *context, const char *box)
 		}
 	}
 
-	if (!(vmu = ast_calloc(1, sizeof(*vmu))))
+	if (!(vmu = ast_calloc(1, sizeof(*vmu)))) {
 		return NULL;
+	}
 
 	ast_copy_string(vmu->context, context, sizeof(vmu->context));
 	ast_copy_string(vmu->mailbox, box, sizeof(vmu->mailbox));
 
+	if (mark_or_create_poll_state(vmu)) {
+		ast_free(vmu);
+		return NULL;
+	}
+
 	AST_LIST_INSERT_TAIL(&users, vmu, list);
 
 	return vmu;
@@ -12600,6 +12641,7 @@ AST_TEST_DEFINE(test_voicemail_vmuser)
 #endif
 
 	free_user(vmu);
+
 	return res ? AST_TEST_FAIL : AST_TEST_PASS;
 }
 #endif
@@ -13010,38 +13052,33 @@ static struct ast_cli_entry cli_voicemail[] = {
 	AST_CLI_DEFINE(handle_voicemail_reload, "Reload voicemail configuration"),
 };
 
-static void poll_subscribed_mailbox(struct mwi_sub *mwi_sub)
+static int poll_mailbox(void *obj, void *arg, int flags)
 {
+	struct poll_state *poll_state = obj;
 	int new = 0, old = 0, urgent = 0;
 
-	inboxcount2(mwi_sub->mailbox, &urgent, &new, &old);
+
+	inboxcount2(poll_state->mailbox, &urgent, &new, &old);
+	ast_debug(4, "Polled mailbox '%s' urgent: %d  new: %d  old: %d\n",
+		poll_state->mailbox, urgent, new, old);
 
 #ifdef IMAP_STORAGE
 	if (imap_poll_logout) {
-		imap_logout(mwi_sub->mailbox);
+		imap_logout(poll_state->mailbox);
 	}
 #endif
 
-	if (urgent != mwi_sub->old_urgent || new != mwi_sub->old_new || old != mwi_sub->old_old) {
-		mwi_sub->old_urgent = urgent;
-		mwi_sub->old_new = new;
-		mwi_sub->old_old = old;
-		queue_mwi_event(NULL, mwi_sub->mailbox, urgent, new, old);
-		run_externnotify(NULL, mwi_sub->mailbox, NULL);
+	if (urgent != poll_state->old_urgent || new != poll_state->old_new || old != poll_state->old_old) {
+		ast_debug(4, "Notifying subscribers of mailbox '%s' urgent: %d  new: %d  old: %d\n",
+			poll_state->mailbox, urgent, new, old);
+		poll_state->old_urgent = urgent;
+		poll_state->old_new = new;
+		poll_state->old_old = old;
+		queue_mwi_event(NULL, poll_state->mailbox, urgent, new, old);
+		run_externnotify(NULL, poll_state->mailbox, NULL);
 	}
-}
 
-static void poll_subscribed_mailboxes(void)
-{
-	struct mwi_sub *mwi_sub;
-
-	AST_RWLIST_RDLOCK(&mwi_subs);
-	AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
-		if (!ast_strlen_zero(mwi_sub->mailbox)) {
-			poll_subscribed_mailbox(mwi_sub);
-		}
-	}
-	AST_RWLIST_UNLOCK(&mwi_subs);
+	return 0;
 }
 
 static void *mb_poll_thread(void *data)
@@ -13061,18 +13098,13 @@ static void *mb_poll_thread(void *data)
 		if (!poll_thread_run)
 			break;
 
-		poll_subscribed_mailboxes();
+		ast_debug(3, "Polling mailboxes\n");
+		ao2_callback(poll_list, OBJ_NODATA | OBJ_MULTIPLE, poll_mailbox, NULL);
 	}
 
 	return NULL;
 }
 
-static void mwi_sub_destroy(struct mwi_sub *mwi_sub)
-{
-	ast_free(mwi_sub->uniqueid);
-	ast_free(mwi_sub);
-}
-
 #ifdef IMAP_STORAGE
 static void imap_logout(const char *mailbox_id)
 {
@@ -13108,155 +13140,22 @@ static void imap_logout(const char *mailbox_id)
 	vmstate_delete(vms);
 }
 
-static void imap_close_subscribed_mailboxes(void)
-{
-	struct mwi_sub *mwi_sub;
-
-	AST_RWLIST_RDLOCK(&mwi_subs);
-	AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
-		if (!ast_strlen_zero(mwi_sub->mailbox)) {
-			imap_logout(mwi_sub->mailbox);
-		}
-	}
-	AST_RWLIST_UNLOCK(&mwi_subs);
-}
-#endif
-
-static int handle_unsubscribe(void *datap)
+static int imap_close_subscribed_mailboxes_cb(void *obj, void *arg, int flags)
 {
-	struct mwi_sub *mwi_sub;
-	char *uniqueid = datap;
-
-	AST_RWLIST_WRLOCK(&mwi_subs);
-	AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {
-		if (!strcmp(mwi_sub->uniqueid, uniqueid)) {
-			AST_LIST_REMOVE_CURRENT(entry);
-			/* Don't break here since a duplicate uniqueid
-			 * may have been added as a result of a cache dump. */
-#ifdef IMAP_STORAGE
-			imap_logout(mwi_sub->mailbox);
-#endif
-			mwi_sub_destroy(mwi_sub);
-		}
-	}
-	AST_RWLIST_TRAVERSE_SAFE_END
-	AST_RWLIST_UNLOCK(&mwi_subs);
+	struct poll_state *poll_state = obj;
+	imap_logout(poll_state->mailbox);
 
-	ast_free(uniqueid);
 	return 0;
 }
-
-static int handle_subscribe(void *datap)
-{
-	unsigned int len;
-	struct mwi_sub *mwi_sub;
-	struct mwi_sub_task *p = datap;
-
-	len = sizeof(*mwi_sub) + 1;
-	if (!ast_strlen_zero(p->mailbox))
-		len += strlen(p->mailbox);
-
-	if (!ast_strlen_zero(p->context))
-		len += strlen(p->context) + 1; /* Allow for seperator */
-
-	if (!(mwi_sub = ast_calloc(1, len)))
-		return -1;
-
-	mwi_sub->uniqueid = ast_strdup(p->uniqueid);
-	if (!ast_strlen_zero(p->mailbox))
-		strcpy(mwi_sub->mailbox, p->mailbox);
-
-	if (!ast_strlen_zero(p->context)) {
-		strcat(mwi_sub->mailbox, "@");
-		strcat(mwi_sub->mailbox, p->context);
-	}
-
-	AST_RWLIST_WRLOCK(&mwi_subs);
-	AST_RWLIST_INSERT_TAIL(&mwi_subs, mwi_sub, entry);
-	AST_RWLIST_UNLOCK(&mwi_subs);
-	mwi_sub_task_dtor(p);
-	poll_subscribed_mailbox(mwi_sub);
-	return 0;
-}
-
-static void mwi_unsub_event_cb(struct stasis_subscription_change *change)
-{
-	char *uniqueid = ast_strdup(change->uniqueid);
-
-	if (!uniqueid) {
-		ast_log(LOG_ERROR, "Unable to allocate memory for uniqueid\n");
-		return;
-	}
-
-	if (ast_taskprocessor_push(mwi_subscription_tps, handle_unsubscribe, uniqueid) < 0) {
-		ast_free(uniqueid);
-	}
-}
-
-static void mwi_sub_event_cb(struct stasis_subscription_change *change)
-{
-	struct mwi_sub_task *mwist;
-	char *context;
-	char *mailbox;
-
-	mwist = ast_calloc(1, (sizeof(*mwist)));
-	if (!mwist) {
-		return;
-	}
-
-	if (separate_mailbox(ast_strdupa(stasis_topic_name(change->topic)), &mailbox, &context)) {
-		ast_free(mwist);
-		return;
-	}
-
-	mwist->mailbox = ast_strdup(mailbox);
-	mwist->context = ast_strdup(context);
-	mwist->uniqueid = ast_strdup(change->uniqueid);
-
-	if (ast_taskprocessor_push(mwi_subscription_tps, handle_subscribe, mwist) < 0) {
-		mwi_sub_task_dtor(mwist);
-	}
-}
-
-static void mwi_event_cb(void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
-{
-	struct stasis_subscription_change *change;
-	/* Only looking for subscription change notices here */
-	if (stasis_message_type(msg) != stasis_subscription_change_type()) {
-		return;
-	}
-
-	change = stasis_message_data(msg);
-	if (change->topic == ast_mwi_topic_all()) {
-		return;
-	}
-
-	if (!strcmp(change->description, "Subscribe")) {
-		mwi_sub_event_cb(change);
-	} else if (!strcmp(change->description, "Unsubscribe")) {
-		mwi_unsub_event_cb(change);
-	}
-}
-
-static int dump_cache(void *obj, void *arg, int flags)
+static void imap_close_subscribed_mailboxes(void)
 {
-	struct stasis_message *msg = obj;
-	mwi_event_cb(NULL, NULL, msg);
-	return 0;
+	ao2_callback(poll_list, OBJ_NODATA | OBJ_MULTIPLE, imap_close_subscribed_mailboxes_cb, NULL);
 }
+#endif
 
 static void start_poll_thread(void)
 {
 	int errcode;
-	mwi_sub_sub = stasis_subscribe(ast_mwi_topic_all(), mwi_event_cb, NULL);
-
-	if (mwi_sub_sub) {
-		struct ao2_container *cached = stasis_cache_dump(ast_mwi_state_cache(), stasis_subscription_change_type());
-		if (cached) {
-			ao2_callback(cached, OBJ_MULTIPLE | OBJ_NODATA, dump_cache, NULL);
-		}
-		ao2_cleanup(cached);
-	}
 
 	poll_thread_run = 1;
 
@@ -13269,8 +13168,6 @@ static void stop_poll_thread(void)
 {
 	poll_thread_run = 0;
 
-	mwi_sub_sub = stasis_unsubscribe_and_join(mwi_sub_sub);
-
 	ast_mutex_lock(&poll_lock);
 	ast_cond_signal(&poll_cond);
 	ast_mutex_unlock(&poll_lock);
@@ -13401,38 +13298,50 @@ static int append_vmu_info_astman(
 
 }
 
-static int manager_voicemail_refresh(struct mansession *s, const struct message *m)
+struct refresh_data {
+	const char *context;
+	const char *mailbox;
+};
+
+static int refresh_match(void *obj, void *arg, int gflags)
 {
-	const char *context = astman_get_header(m, "Context");
-	const char *mailbox = astman_get_header(m, "Mailbox");
-	struct mwi_sub *mwi_sub;
+	struct poll_state *poll_state = obj;
+	struct refresh_data *data = arg;
 	const char *at;
 
-	AST_RWLIST_RDLOCK(&mwi_subs);
-	AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
-		if (!ast_strlen_zero(mwi_sub->mailbox)) {
-			if (
-				/* First case: everything matches */
-				(ast_strlen_zero(context) && ast_strlen_zero(mailbox)) ||
-				/* Second case: match the mailbox only */
-				(ast_strlen_zero(context) && !ast_strlen_zero(mailbox) &&
-					(at = strchr(mwi_sub->mailbox, '@')) &&
-					strncmp(mailbox, mwi_sub->mailbox, at - mwi_sub->mailbox) == 0) ||
-				/* Third case: match the context only */
-				(!ast_strlen_zero(context) && ast_strlen_zero(mailbox) &&
-					(at = strchr(mwi_sub->mailbox, '@')) &&
-					strcmp(context, at + 1) == 0) ||
-				/* Final case: match an exact specified mailbox */
-				(!ast_strlen_zero(context) && !ast_strlen_zero(mailbox) &&
-					(at = strchr(mwi_sub->mailbox, '@')) &&
-					strncmp(mailbox, mwi_sub->mailbox, at - mwi_sub->mailbox) == 0 &&
-					strcmp(context, at + 1) == 0)
-			) {
-				poll_subscribed_mailbox(mwi_sub);
-			}
+	if (!ast_strlen_zero(poll_state->mailbox)) {
+		if (
+			/* First case: everything matches */
+			(ast_strlen_zero(data->context) && ast_strlen_zero(data->mailbox)) ||
+			/* Second case: match the mailbox only */
+			(ast_strlen_zero(data->context) && !ast_strlen_zero(data->mailbox) &&
+				(at = strchr(poll_state->mailbox, '@')) &&
+				strncmp(data->mailbox, poll_state->mailbox, at - poll_state->mailbox) == 0) ||
+			/* Third case: match the context only */
+			(!ast_strlen_zero(data->context) && ast_strlen_zero(data->mailbox) &&
+				(at = strchr(poll_state->mailbox, '@')) &&
+				strcmp(data->context, at + 1) == 0) ||
+			/* Final case: match an exact specified mailbox */
+			(!ast_strlen_zero(data->context) && !ast_strlen_zero(data->mailbox) &&
+				(at = strchr(poll_state->mailbox, '@')) &&
+				strncmp(data->mailbox, poll_state->mailbox, at - poll_state->mailbox) == 0 &&
+				strcmp(data->context, at + 1) == 0)
+		) {
+			poll_mailbox(poll_state, NULL, 0);
 		}
 	}
-	AST_RWLIST_UNLOCK(&mwi_subs);
+
+	return 0;
+}
+
+static int manager_voicemail_refresh(struct mansession *s, const struct message *m)
+{
+	struct refresh_data data = {
+		.context = astman_get_header(m, "Context"),
+		.mailbox = astman_get_header(m, "Mailbox"),
+	};
+
+	ao2_callback(poll_list, OBJ_NODATA | OBJ_MULTIPLE, refresh_match, (void *)&data);
 	astman_send_ack(s, m, "Refresh sent");
 	return RESULT_SUCCESS;
 }
@@ -13643,6 +13552,26 @@ static int load_config_from_memory(int reload, struct ast_config *cfg, struct as
 }
 #endif
 
+static int unmark_poll_state(void *obj, void*arg, int flags)
+{
+	struct poll_state *poll_state = obj;
+
+	poll_state->marked_used = 0;
+
+	return 0;
+}
+
+static int unmarked_poll_state(void *obj, void*arg, int flags)
+{
+	struct poll_state *poll_state = obj;
+
+	if (!poll_state->marked_used) {
+		return CMP_MATCH;
+	}
+
+	return 0;
+}
+
 static int actual_load_config(int reload, struct ast_config *cfg, struct ast_config *ucfg)
 {
 	struct ast_vm_user *current;
@@ -13653,8 +13582,6 @@ static int actual_load_config(int reload, struct ast_config *cfg, struct ast_con
 	int x;
 	unsigned int tmpadsi[4];
 	char secretfn[PATH_MAX] = "";
-	long tps_queue_low;
-	long tps_queue_high;
 
 #ifdef IMAP_STORAGE
 	ast_copy_string(imapparentfolder, "\0", sizeof(imapparentfolder));
@@ -13670,6 +13597,17 @@ static int actual_load_config(int reload, struct ast_config *cfg, struct ast_con
 	imap_close_subscribed_mailboxes();
 #endif
 
+	if (poll_thread != AST_PTHREADT_NULL) {
+		stop_poll_thread();
+	}
+
+	/*
+	 * Unmark all current poll states.  As mailboxes are (re)loaded,
+	 * the state will be marked as used.  Any not marked after the
+	 * (re)load, will be removed.
+	 */
+	ao2_callback(poll_list, OBJ_NODATA | OBJ_MULTIPLE, unmark_poll_state, NULL);
+
 	/* Free all the users structure */
 	free_vm_users();
 
@@ -14243,23 +14181,11 @@ static int actual_load_config(int reload, struct ast_config *cfg, struct ast_con
 			pagerbody = ast_strdup(substitute_escapes(val));
 		}
 
-		tps_queue_high = AST_TASKPROCESSOR_HIGH_WATER_LEVEL;
 		if ((val = ast_variable_retrieve(cfg, "general", "tps_queue_high"))) {
-			if (sscanf(val, "%30ld", &tps_queue_high) != 1 || tps_queue_high <= 0) {
-				ast_log(AST_LOG_WARNING, "Invalid the taskprocessor high water alert trigger level '%s'\n", val);
-				tps_queue_high = AST_TASKPROCESSOR_HIGH_WATER_LEVEL;
-			}
+			ast_log(LOG_NOTICE, "Parameter tps_queue_high is obsolete and will be ignored\n");
 		}
-		tps_queue_low = -1;
 		if ((val = ast_variable_retrieve(cfg, "general", "tps_queue_low"))) {
-			if (sscanf(val, "%30ld", &tps_queue_low) != 1 ||
-				tps_queue_low < -1 || tps_queue_high < tps_queue_low) {
-				ast_log(AST_LOG_WARNING, "Invalid the taskprocessor low water clear alert level '%s'\n", val);
-				tps_queue_low = -1;
-			}
-		}
-		if (ast_taskprocessor_alert_set_levels(mwi_subscription_tps, tps_queue_low, tps_queue_high)) {
-			ast_log(AST_LOG_WARNING, "Failed to set alert levels for voicemail taskprocessor.\n");
+			ast_log(LOG_NOTICE, "Parameter tps_queue_low is obsolete and will be ignored\n");
 		}
 
 		/* load mailboxes from users.conf */
@@ -14329,15 +14255,16 @@ static int actual_load_config(int reload, struct ast_config *cfg, struct ast_con
 		}
 
 		AST_LIST_UNLOCK(&users);
+		/* Remove any left over unmarked poll states */
+		ao2_callback(poll_list, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, unmarked_poll_state, NULL);
 
 		if (poll_mailboxes && poll_thread == AST_PTHREADT_NULL)
 			start_poll_thread();
-		if (!poll_mailboxes && poll_thread != AST_PTHREADT_NULL)
-			stop_poll_thread();;
 
 		return 0;
 	} else {
 		AST_LIST_UNLOCK(&users);
+		ao2_callback(poll_list, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, unmarked_poll_state, NULL);
 		ast_log(AST_LOG_WARNING, "Failed to load configuration file.\n");
 		return 0;
 	}
@@ -14558,7 +14485,6 @@ AST_TEST_DEFINE(test_voicemail_msgcount)
 {
 	int i, j, res = AST_TEST_PASS, syserr;
 	struct ast_vm_user *vmu;
-	struct ast_vm_user svm;
 	struct vm_state vms;
 #ifdef IMAP_STORAGE
 	struct ast_channel *chan = NULL;
@@ -14611,9 +14537,11 @@ AST_TEST_DEFINE(test_voicemail_msgcount)
 	}
 #endif
 
-	memset(&svm, 0, sizeof(svm));
-	if (!(vmu = find_user(&svm, testcontext, testmailbox)) &&
-		!(vmu = find_or_create(testcontext, testmailbox))) {
+	AST_LIST_LOCK(&users);
+	vmu = find_or_create(testcontext, testmailbox);
+	AST_LIST_UNLOCK(&users);
+
+	if (!vmu) {
 		ast_test_status_update(test, "Cannot create vmu structure\n");
 		ast_unreplace_sigchld();
 #ifdef IMAP_STORAGE
@@ -14641,8 +14569,8 @@ AST_TEST_DEFINE(test_voicemail_msgcount)
 #ifdef IMAP_STORAGE
 				chan = ast_channel_unref(chan);
 #endif
-				free_user(vmu);
-				return AST_TEST_FAIL;
+				res = AST_TEST_FAIL;
+				break;
 			}
 		}
 
@@ -14666,27 +14594,34 @@ AST_TEST_DEFINE(test_voicemail_msgcount)
 				res = AST_TEST_FAIL;
 			}
 		}
+		if (res) {
+			break;
+		}
 
 		new = old = urgent = 0;
 		if (ast_app_inboxcount(testspec, &new, &old)) {
 			ast_test_status_update(test, "inboxcount returned failure\n");
 			res = AST_TEST_FAIL;
+			break;
 		} else if (old != expected_results[i][3 + 0] || new != expected_results[i][3 + 2]) {
 			ast_test_status_update(test, "inboxcount(%s) returned old=%d (expected %d) and new=%d (expected %d)\n",
 				testspec, old, expected_results[i][3 + 0], new, expected_results[i][3 + 2]);
 			res = AST_TEST_FAIL;
+			break;
 		}
 
 		new = old = urgent = 0;
 		if (ast_app_inboxcount2(testspec, &urgent, &new, &old)) {
 			ast_test_status_update(test, "inboxcount2 returned failure\n");
 			res = AST_TEST_FAIL;
+			break;
 		} else if (old != expected_results[i][6 + 0] ||
 				urgent != expected_results[i][6 + 1] ||
 				   new != expected_results[i][6 + 2]    ) {
 			ast_test_status_update(test, "inboxcount2(%s) returned old=%d (expected %d), urgent=%d (expected %d), and new=%d (expected %d)\n",
 				testspec, old, expected_results[i][6 + 0], urgent, expected_results[i][6 + 1], new, expected_results[i][6 + 2]);
 			res = AST_TEST_FAIL;
+			break;
 		}
 
 		new = old = urgent = 0;
@@ -14697,6 +14632,9 @@ AST_TEST_DEFINE(test_voicemail_msgcount)
 				res = AST_TEST_FAIL;
 			}
 		}
+		if (res) {
+			break;
+		}
 	}
 
 	for (i = 0; i < 3; i++) {
@@ -14725,7 +14663,9 @@ AST_TEST_DEFINE(test_voicemail_msgcount)
 			syserr > 0 ? strerror(syserr) : "unable to fork()");
 	}
 
-	free_user(vmu);
+	/* restore config */
+	load_config(0); /* this might say "Failed to load configuration file." */
+
 	return res;
 }
 
@@ -14776,15 +14716,13 @@ AST_TEST_DEFINE(test_voicemail_notify_endl)
 	snprintf(attach, sizeof(attach), "%s/sounds/en/tt-weasels", ast_config_AST_DATA_DIR);
 	snprintf(attach2, sizeof(attach2), "%s/sounds/en/tt-somethingwrong", ast_config_AST_DATA_DIR);
 
-	if (!(vmu = find_user(&vmus, testcontext, testmailbox)) &&
-		!(vmu = find_or_create(testcontext, testmailbox))) {
-		ast_test_status_update(test, "Cannot create vmu structure\n");
-		return AST_TEST_NOT_RUN;
-	}
+	AST_LIST_LOCK(&users);
+	vmu = find_or_create(testcontext, testmailbox);
+	AST_LIST_UNLOCK(&users);
 
-	if (vmu != &vmus && !(vmu = find_user(&vmus, testcontext, testmailbox))) {
-		ast_test_status_update(test, "Cannot find vmu structure?!!\n");
-		return AST_TEST_NOT_RUN;
+	if (!vmu) {
+		ast_test_status_update(test, "Cannot create vmu structure\n");
+		return AST_TEST_FAIL;
 	}
 
 	populate_defaults(vmu);
@@ -14835,7 +14773,10 @@ AST_TEST_DEFINE(test_voicemail_notify_endl)
 		}
 	}
 	fclose(file);
-	free_user(vmu);
+
+	/* restore config */
+	load_config(0); /* this might say "Failed to load configuration file." */
+
 	return res;
 }
 
@@ -14909,7 +14850,7 @@ AST_TEST_DEFINE(test_voicemail_load_config)
 #undef CHECK
 
 	/* restore config */
-	load_config(1); /* this might say "Failed to load configuration file." */
+	load_config(0); /* this might say "Failed to load configuration file." */
 
 cleanup:
 	unlink(config_filename);
@@ -14965,8 +14906,11 @@ AST_TEST_DEFINE(test_voicemail_vm_info)
 		return AST_TEST_FAIL;
 	}
 
-	if (!(vmu = find_user(NULL, testcontext, testmailbox)) &&
-			!(vmu = find_or_create(testcontext, testmailbox))) {
+	AST_LIST_LOCK(&users);
+	vmu = find_or_create(testcontext, testmailbox);
+	AST_LIST_UNLOCK(&users);
+
+	if (!vmu) {
 		ast_test_status_update(test, "Cannot create vmu structure\n");
 		chan = ast_channel_unref(chan);
 		return AST_TEST_FAIL;
@@ -14996,7 +14940,10 @@ AST_TEST_DEFINE(test_voicemail_vm_info)
 	}
 
 	chan = ast_channel_unref(chan);
-	free_user(vmu);
+
+	/* restore config */
+	load_config(0); /* this might say "Failed to load configuration file." */
+
 	return res;
 }
 #endif /* defined(TEST_FRAMEWORK) */
@@ -15062,10 +15009,13 @@ static int unload_module(void)
 #endif
 	ao2_ref(inprocess_container, -1);
 
-	if (poll_thread != AST_PTHREADT_NULL)
+	if (poll_thread != AST_PTHREADT_NULL) {
 		stop_poll_thread();
+	}
+
+	ao2_container_unregister("voicemail_poll_list");
+	ao2_cleanup(poll_list);
 
-	mwi_subscription_tps = ast_taskprocessor_unreference(mwi_subscription_tps);
 	ast_unload_realtime("voicemail");
 	ast_unload_realtime("voicemail_data");
 
@@ -15077,6 +15027,18 @@ static int unload_module(void)
 	return res;
 }
 
+static void print_poll_state(void *v_obj, void *where, ao2_prnt_fn *prnt)
+{
+	struct poll_state *poll_state = v_obj;
+
+	if (!poll_state) {
+		return;
+	}
+	prnt(where, "Mailbox: %s New: %d  Old: %d  Urgent: %d  Marked Used: %d", poll_state->mailbox,
+		poll_state->old_new, poll_state->old_old, poll_state->old_urgent,
+		poll_state->marked_used);
+}
+
 /*!
  * \brief Load the module
  *
@@ -15101,13 +15063,23 @@ static int load_module(void)
 		return AST_MODULE_LOAD_DECLINE;
 	}
 
+	poll_list = ao2_container_alloc(POLL_LIST_BUCKETS, poll_state_hash_fn, poll_state_cmp_fn);
+	if (!poll_list) {
+		ast_log(LOG_ERROR, "Unable to create poll_list container\n");
+		ao2_cleanup(inprocess_container);
+		return AST_MODULE_LOAD_DECLINE;
+	}
+	res = ao2_container_register("voicemail_poll_list", poll_list, print_poll_state);
+	if (res) {
+		ast_log(LOG_ERROR, "Unable to register poll_list container\n");
+		ao2_cleanup(inprocess_container);
+		ao2_cleanup(poll_list);
+		return AST_MODULE_LOAD_DECLINE;
+	}
+
 	/* compute the location of the voicemail spool directory */
 	snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
 
-	if (!(mwi_subscription_tps = ast_taskprocessor_get("app_voicemail", 0))) {
-		ast_log(AST_LOG_WARNING, "failed to reference mwi subscription taskprocessor.  MWI will not work\n");
-	}
-
 	if ((res = load_config(0))) {
 		unload_module();
 		return AST_MODULE_LOAD_DECLINE;
diff --git a/configs/samples/voicemail.conf.sample b/configs/samples/voicemail.conf.sample
index e4130d356f6faa9b8b821106d3b7a2415f87a2e0..43325a24942324f9a6305afa9664b8a0f80bab6e 100644
--- a/configs/samples/voicemail.conf.sample
+++ b/configs/samples/voicemail.conf.sample
@@ -387,17 +387,6 @@ sendvoicemail=yes ; Allow the user to compose and send a voicemail while inside
 ; defaults to being off
 ; backupdeleted=100
 
-; Asterisk Task Processor Queue Size
-; On heavy loaded system you may need to increase 'app_voicemail' taskprocessor queue.
-; If the taskprocessor queue size reached high water level, the alert is triggered.
-; If the alert is set then some modules (for example pjsip) slow down its production
-; until the alert is cleared.
-; The alert is cleared when taskprocessor queue size drops to the low water clear level.
-; The next options set taskprocessor queue levels for this module.
-; tps_queue_high=500	; Taskprocessor high water alert trigger level.
-; tps_queue_low=450	; Taskprocessor low water clear alert level.
-			; The default is -1 for 90% of high water level.
-
 [zonemessages]
 ; Users may be located in different timezones, or may have different
 ; message announcements for their introductory message when they enter