diff --git a/res/res_pjsip_mwi.c b/res/res_pjsip_mwi.c
index 2ea5f89dd17050cf513e90708836a412d8bc5fb2..c89d383855a07bf32b89b0407a9e927656675fb6 100644
--- a/res/res_pjsip_mwi.c
+++ b/res/res_pjsip_mwi.c
@@ -42,6 +42,7 @@
 
 struct mwi_subscription;
 static struct ao2_container *unsolicited_mwi;
+static struct ao2_container *solicited_mwi;
 
 static char *default_voicemail_extension;
 
@@ -119,6 +120,8 @@ struct mwi_subscription {
 	char *aors;
 	/*! Is the MWI solicited (i.e. Initiated with an external SUBSCRIBE) ? */
 	unsigned int is_solicited;
+	/*! True if this subscription is to be terminated */
+	unsigned int terminate;
 	/*! Identifier for the subscription.
 	 * The identifier is the same as the corresponding endpoint's stasis ID.
 	 * Used as a hash key
@@ -665,7 +668,7 @@ static void send_mwi_notify(struct mwi_subscription *sub)
 
 		ao2_cleanup(aor);
 		ao2_cleanup(endpoint);
-		ast_sip_subscription_notify(sub->sip_sub, &data, 0);
+		ast_sip_subscription_notify(sub->sip_sub, &data, sub->terminate);
 
 		return;
 	}
@@ -676,18 +679,22 @@ static void send_mwi_notify(struct mwi_subscription *sub)
 static int unsubscribe_stasis(void *obj, void *arg, int flags)
 {
 	struct mwi_stasis_subscription *mwi_stasis = obj;
+
 	if (mwi_stasis->mwi_subscriber) {
 		ast_debug(3, "Removing stasis subscription to mailbox %s\n", mwi_stasis->mailbox);
 		mwi_stasis->mwi_subscriber = ast_mwi_unsubscribe_and_join(mwi_stasis->mwi_subscriber);
 	}
-
 	return CMP_MATCH;
 }
 
+static int create_unsolicited_mwi_subscriptions(struct ast_sip_endpoint *endpoint,
+		int recreate, int send_now);
+
 static void mwi_subscription_shutdown(struct ast_sip_subscription *sub)
 {
 	struct mwi_subscription *mwi_sub;
 	struct ast_datastore *mwi_datastore;
+	struct ast_sip_endpoint *endpoint = NULL;
 
 	mwi_datastore = ast_sip_subscription_get_datastore(sub, MWI_DATASTORE);
 	if (!mwi_datastore) {
@@ -695,10 +702,25 @@ static void mwi_subscription_shutdown(struct ast_sip_subscription *sub)
 	}
 
 	mwi_sub = mwi_datastore->data;
+
 	ao2_callback(mwi_sub->stasis_subs, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, unsubscribe_stasis, NULL);
 	ast_sip_subscription_remove_datastore(sub, MWI_DATASTORE);
+	endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", mwi_sub->id);
 
 	ao2_ref(mwi_datastore, -1);
+	ao2_unlink(solicited_mwi, mwi_sub);
+
+	/*
+	 * When a solicited subscription is removed it's possible an unsolicited one
+	 * needs to be [re-]created. Attempt to establish unsolicited MWI.
+	 */
+	if (unsolicited_mwi && endpoint) {
+		ao2_lock(unsolicited_mwi);
+		create_unsolicited_mwi_subscriptions(endpoint, 1, 1);
+		ao2_unlock(unsolicited_mwi);
+	}
+
+	ao2_cleanup(endpoint);
 }
 
 static void mwi_ds_destroy(void *data)
@@ -734,43 +756,165 @@ static int add_mwi_datastore(struct mwi_subscription *sub)
 }
 
 /*!
- * \brief Determines if an endpoint is receiving unsolicited MWI for a particular mailbox.
+ * \internal
+ * \brief Determine if an MWI subscription already exists for the given endpoint/mailbox
+ *
+ * Search the given container, and attempt to find out if the given endpoint has a
+ * current subscription within. If so pass back the associated mwi_subscription and
+ * mwi_stasis_subscription objects.
+ *
+ * \note If a subscription is located then the caller is responsible for removing the
+ * references to the passed back mwi_subscription and mwi_stasis_subscription objects.
+ *
+ * \note Must be called with the given container already locked.
  *
- * \param endpoint The endpoint to check
- * \param mailbox The candidate mailbox
- * \retval 0 The endpoint does not receive unsolicited MWI for this mailbox
- * \retval 1 The endpoint receives unsolicited MWI for this mailbox
+ * \param container The ao2_container to search
+ * \param endpoint The endpoint to find
+ * \param mailbox The mailbox potentially subscribed
+ * \param mwi_sub [out] May contain the located mwi_subscription
+ * \param mwi_stasis [out] May contain the located mwi_stasis_subscription
+ *
+ * \retval 1 if a subscription was located, 0 otherwise
  */
-static int endpoint_receives_unsolicited_mwi_for_mailbox(struct ast_sip_endpoint *endpoint,
-		const char *mailbox)
+static int has_mwi_subscription(struct ao2_container *container,
+		struct ast_sip_endpoint *endpoint, const char *mailbox,
+		struct mwi_subscription **mwi_sub, struct mwi_stasis_subscription **mwi_stasis)
 {
 	struct ao2_iterator *mwi_subs;
-	struct mwi_subscription *mwi_sub;
-	const char *endpoint_id = ast_sorcery_object_get_id(endpoint);
-	int ret = 0;
 
-	mwi_subs = ao2_find(unsolicited_mwi, endpoint_id, OBJ_SEARCH_KEY | OBJ_MULTIPLE);
+	*mwi_sub = NULL;
+	*mwi_stasis = NULL;
+
+	mwi_subs = ao2_find(container, ast_sorcery_object_get_id(endpoint),
+						OBJ_SEARCH_KEY | OBJ_MULTIPLE | OBJ_NOLOCK);
 	if (!mwi_subs) {
 		return 0;
 	}
 
-	for (; (mwi_sub = ao2_iterator_next(mwi_subs)) && !ret; ao2_cleanup(mwi_sub)) {
-		struct mwi_stasis_subscription *mwi_stasis;
-
-		mwi_stasis = ao2_find(mwi_sub->stasis_subs, mailbox, OBJ_SEARCH_KEY);
-		if (mwi_stasis) {
-			if (endpoint->subscription.mwi.subscribe_replaces_unsolicited) {
-				unsubscribe_stasis(mwi_stasis, NULL, 0);
-				ao2_unlink(mwi_sub->stasis_subs, mwi_stasis);
-			} else {
-				ret = 1;
-			}
-			ao2_cleanup(mwi_stasis);
+	while ((*mwi_sub = ao2_iterator_next(mwi_subs))) {
+		*mwi_stasis = ao2_find((*mwi_sub)->stasis_subs, mailbox, OBJ_SEARCH_KEY);
+		if (*mwi_stasis) {
+			/* If found then caller is responsible for unrefs of passed back objects */
+			break;
 		}
+		ao2_ref(*mwi_sub, -1);
 	}
 
 	ao2_iterator_destroy(mwi_subs);
-	return ret;
+	return *mwi_stasis ? 1 : 0;
+}
+
+/*!
+ * \internal
+ * \brief Allow and/or replace the unsolicited subscription
+ *
+ * Checks to see if solicited subscription is allowed. If allowed, and an
+ * unsolicited one exists then prepare for replacement by removing the
+ * current unsolicited subscription.
+ *
+ * \param endpoint The endpoint
+ * \param mailbox The mailbox
+ *
+ * \retval 1 if a solicited subscription is allowed for the endpoint/mailbox
+ *         0 otherwise
+ */
+static int allow_and_or_replace_unsolicited(struct ast_sip_endpoint *endpoint, const char *mailbox)
+{
+	struct mwi_subscription *mwi_sub;
+	struct mwi_stasis_subscription *mwi_stasis;
+
+	if (!has_mwi_subscription(unsolicited_mwi, endpoint, mailbox, &mwi_sub, &mwi_stasis)) {
+		/* If no unsolicited subscription then allow the solicited one */
+		return 1;
+	}
+
+	if (!endpoint->subscription.mwi.subscribe_replaces_unsolicited) {
+		/* Has unsolicited subscription and can't replace, so disallow */
+		ao2_ref(mwi_stasis, -1);
+		ao2_ref(mwi_sub, -1);
+		return 0;
+	}
+
+	/*
+	 * The unsolicited subscription exists, and it is allowed to be replaced.
+	 * So, first remove the unsolicited stasis subscription, and if aggregation
+	 * is not enabled then also remove the mwi_subscription object as well.
+	 */
+	ast_debug(1, "Unsolicited subscription being replaced by solicited for "
+			"endpoint '%s' mailbox '%s'\n", ast_sorcery_object_get_id(endpoint), mailbox);
+
+	unsubscribe_stasis(mwi_stasis, NULL, 0);
+	ao2_unlink(mwi_sub->stasis_subs, mwi_stasis);
+
+	if (!endpoint->subscription.mwi.aggregate) {
+		ao2_unlink(unsolicited_mwi, mwi_sub);
+	}
+
+	ao2_ref(mwi_stasis, -1);
+	ao2_ref(mwi_sub, -1);
+
+	/* This solicited subscription is replacing an unsolicited one, so allow */
+	return 1;
+}
+
+static int send_notify(void *obj, void *arg, int flags);
+
+/*!
+ * \internal
+ * \brief Determine if an unsolicited MWI subscription is allowed
+ *
+ * \param endpoint The endpoint
+ * \param mailbox The mailbox
+ *
+ * \retval 1 if an unsolicited subscription is allowed for the endpoint/mailbox
+ *         0 otherwise
+ */
+static int is_unsolicited_allowed(struct ast_sip_endpoint *endpoint, const char *mailbox)
+{
+	struct mwi_subscription *mwi_sub;
+	struct mwi_stasis_subscription *mwi_stasis;
+
+	if (ast_strlen_zero(mailbox)) {
+		return 0;
+	}
+
+	/*
+	 * First check if an unsolicited subscription exists. If it does then we don't
+	 * want to add another one.
+	 */
+	if (has_mwi_subscription(unsolicited_mwi, endpoint, mailbox, &mwi_sub, &mwi_stasis)) {
+		ao2_ref(mwi_stasis, -1);
+		ao2_ref(mwi_sub, -1);
+		return 0;
+	}
+
+	/*
+	 * If there is no unsolicited subscription, next check to see if a solicited
+	 * subscription exists for the endpoint/mailbox. If not, then allow.
+	 */
+	if (!has_mwi_subscription(solicited_mwi, endpoint, mailbox, &mwi_sub, &mwi_stasis)) {
+		return 1;
+	}
+
+	/*
+	 * If however, a solicited subscription does exist then we'll need to see if that
+	 * subscription is allowed to replace the unsolicited one. If is allowed to replace
+	 * then disallow the unsolicited one.
+	 */
+	if (endpoint->subscription.mwi.subscribe_replaces_unsolicited) {
+		ao2_ref(mwi_stasis, -1);
+		ao2_ref(mwi_sub, -1);
+		return 0;
+	}
+
+	/* Otherwise, shutdown the solicited subscription and allow the unsolicited */
+	mwi_sub->terminate = 1;
+	send_notify(mwi_sub, NULL, 0);
+
+	ao2_ref(mwi_stasis, -1);
+	ao2_ref(mwi_sub, -1);
+
+	return 1;
 }
 
 /*!
@@ -796,19 +940,23 @@ static int mwi_validate_for_aor(void *obj, void *arg, int flags)
 		return 0;
 	}
 
+	/* A reload could be taking place so lock while checking if allowed */
+	ao2_lock(unsolicited_mwi);
 	mailboxes = ast_strdupa(aor->mailboxes);
 	while ((mailbox = ast_strip(strsep(&mailboxes, ",")))) {
 		if (ast_strlen_zero(mailbox)) {
 			continue;
 		}
 
-		if (endpoint_receives_unsolicited_mwi_for_mailbox(endpoint, mailbox)) {
+		if (!allow_and_or_replace_unsolicited(endpoint, mailbox)) {
 			ast_debug(1, "Endpoint '%s' already configured for unsolicited MWI for mailbox '%s'. "
 					"Denying MWI subscription to %s\n", ast_sorcery_object_get_id(endpoint), mailbox,
 					ast_sorcery_object_get_id(aor));
+			ao2_unlock(unsolicited_mwi);
 			return -1;
 		}
 	}
+	ao2_unlock(unsolicited_mwi);
 
 	return 0;
 }
@@ -954,6 +1102,7 @@ static int mwi_subscription_established(struct ast_sip_subscription *sip_sub)
 		ast_sip_subscription_remove_datastore(sip_sub, MWI_DATASTORE);
 	}
 
+	ao2_link(solicited_mwi, sub);
 	ao2_cleanup(sub);
 	ao2_cleanup(endpoint);
 	return 0;
@@ -1090,12 +1239,25 @@ static void mwi_stasis_cb(void *userdata, struct stasis_subscription *sub,
 	}
 }
 
-/*! \note Called with the unsolicited_mwi container lock held. */
-static int create_mwi_subscriptions_for_endpoint(void *obj, void *arg, int flags)
+/*!
+ * \internal
+ * \brief Create unsolicited MWI subscriptions for an endpoint
+ *
+ * \note Call with the unsolicited_mwi container lock held.
+ *
+ * \param endpoint An endpoint object
+ * \param recreate Whether or not unsolicited subscriptions are potentially being recreated
+ * \param send_now Whether or not to send a notify once the subscription is created
+ *
+ * \retval 0
+ */
+static int create_unsolicited_mwi_subscriptions(struct ast_sip_endpoint *endpoint,
+		int recreate, int send_now)
 {
 	RAII_VAR(struct mwi_subscription *, aggregate_sub, NULL, ao2_cleanup);
-	struct ast_sip_endpoint *endpoint = obj;
-	char *mailboxes, *mailbox;
+	char *mailboxes;
+	char *mailbox;
+	int sub_added = 0;
 
 	if (ast_strlen_zero(endpoint->subscription.mwi.mailboxes)) {
 		return 0;
@@ -1104,45 +1266,83 @@ static int create_mwi_subscriptions_for_endpoint(void *obj, void *arg, int flags
 	if (endpoint->subscription.mwi.aggregate) {
 		const char *endpoint_id = ast_sorcery_object_get_id(endpoint);
 
-		/* Check if subscription exists */
+		/* Check if aggregate subscription exists */
 		aggregate_sub = ao2_find(unsolicited_mwi, endpoint_id, OBJ_SEARCH_KEY | OBJ_NOLOCK);
-		if (aggregate_sub) {
+
+		/*
+		 * If enabled there should only ever exist a single aggregate subscription object
+		 * for an endpoint. So if it exists just return unless subscriptions are potentially
+		 * being added back in. If that's the case then continue.
+		 */
+		if (aggregate_sub && !recreate) {
 			return 0;
 		}
-		aggregate_sub = mwi_subscription_alloc(endpoint, 0, NULL);
+
 		if (!aggregate_sub) {
-			return 0;
+			aggregate_sub = mwi_subscription_alloc(endpoint, 0, NULL);
+			if (!aggregate_sub) {
+				return 0; /* No MWI aggregation for you */
+			}
 		}
 	}
 
+	/* Lock solicited so we don't potentially add to both containers */
+	ao2_lock(solicited_mwi);
+
 	mailboxes = ast_strdupa(endpoint->subscription.mwi.mailboxes);
 	while ((mailbox = ast_strip(strsep(&mailboxes, ",")))) {
 		struct mwi_subscription *sub;
 		struct mwi_stasis_subscription *mwi_stasis_sub;
 
-		/* check if subscription exists */
-		if (ast_strlen_zero(mailbox) ||
-			(!aggregate_sub && endpoint_receives_unsolicited_mwi_for_mailbox(endpoint, mailbox))) {
+		if (!is_unsolicited_allowed(endpoint, mailbox)) {
 			continue;
 		}
 
 		sub = aggregate_sub ?: mwi_subscription_alloc(endpoint, 0, NULL);
+		if (!sub) {
+			continue;
+		}
+
 		mwi_stasis_sub = mwi_stasis_subscription_alloc(mailbox, sub);
 		if (mwi_stasis_sub) {
 			ao2_link(sub->stasis_subs, mwi_stasis_sub);
 			ao2_ref(mwi_stasis_sub, -1);
 		}
-		if (!aggregate_sub && sub) {
+		if (!aggregate_sub) {
 			ao2_link_flags(unsolicited_mwi, sub, OBJ_NOLOCK);
+			if (send_now) {
+				send_notify(sub, NULL, 0);
+			}
 			ao2_ref(sub, -1);
 		}
+
+		if (aggregate_sub && !sub_added) {
+			/* If aggregation track if at least one subscription has been added */
+			sub_added = 1;
+		}
 	}
+
 	if (aggregate_sub) {
-		ao2_link_flags(unsolicited_mwi, aggregate_sub, OBJ_NOLOCK);
+		if (ao2_container_count(aggregate_sub->stasis_subs)) {
+			ao2_link_flags(unsolicited_mwi, aggregate_sub, OBJ_NOLOCK);
+			if (send_now && sub_added) {
+				send_notify(aggregate_sub, NULL, 0);
+			}
+		} else {
+			/* No stasis subscriptions then no MWI data to aggregate */
+			ao2_ref(aggregate_sub, -1);
+		}
 	}
+
+	ao2_unlock(solicited_mwi);
 	return 0;
 }
 
+static int create_mwi_subscriptions_for_endpoint(void *obj, void *arg, int flags)
+{
+	return create_unsolicited_mwi_subscriptions(obj, 0, 0);
+}
+
 static int unsubscribe(void *obj, void *arg, int flags)
 {
 	struct mwi_subscription *mwi_sub = obj;
@@ -1347,11 +1547,20 @@ static int load_module(void)
 		ast_log(AST_LOG_WARNING, "Failed to create MWI serializer pool. The default SIP pool will be used for MWI\n");
 	}
 
+	solicited_mwi = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0, MWI_BUCKETS,
+		mwi_sub_hash, NULL, mwi_sub_cmp);
+	if (!solicited_mwi) {
+		mwi_serializer_pool_shutdown();
+		ast_sip_unregister_subscription_handler(&mwi_handler);
+		return AST_MODULE_LOAD_DECLINE;
+	}
+
 	unsolicited_mwi = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0, MWI_BUCKETS,
 		mwi_sub_hash, NULL, mwi_sub_cmp);
 	if (!unsolicited_mwi) {
 		mwi_serializer_pool_shutdown();
 		ast_sip_unregister_subscription_handler(&mwi_handler);
+		ao2_ref(solicited_mwi, -1);
 		return AST_MODULE_LOAD_DECLINE;
 	}
 
@@ -1384,6 +1593,8 @@ static int unload_module(void)
 	ao2_ref(unsolicited_mwi, -1);
 	unsolicited_mwi = NULL;
 
+	ao2_cleanup(solicited_mwi);
+
 	mwi_serializer_pool_shutdown();
 
 	ast_sip_unregister_subscription_handler(&mwi_handler);