diff --git a/CHANGES b/CHANGES
index 4b59519837b9f013a5b2f3ef4b978ea0365b7624..55f828ed5e50acace83dec5a4913c1295063dda4 100644
--- a/CHANGES
+++ b/CHANGES
@@ -11,6 +11,7 @@ OpenLDAP 2.4.16 Engineering
 	Fixed slapd ctxcsn race condition (ITS#6001)
 	Fixed slapd syncrepl newCookie sync messages (ITS#5972)
 	Fixed slapd syncrepl hang during shutdown (ITS#6011)
+	Fixed slapd syncrepl too many MMR messages (ITS#6020)
 	Fixed slapd-bdb/hdb cachesize handling (ITS#5860)
 	Fixed slapd-bdb/hdb with slapcat with empty dn (ITS#6006)
 	Fixed slapd-ldap incorrect referral handling (ITS#6003,ITS#5916)
@@ -19,6 +20,7 @@ OpenLDAP 2.4.16 Engineering
 	Fixed slapo-accesslog interaction with ppolicy (ITS#5979)
 	Fixed slapo-dynlist conversion to cn=config (ITS#6002)
 	Fixed slapo-syncprov newCookie sync messages (ITS#5972)
+	Fixed slapd-syncprov too many MMR messages (ITS#6020)
 	Build Environment
 		Cleaned up alloc/free functions for Windows (ITS#6005)
 	Documentation
diff --git a/servers/slapd/overlays/syncprov.c b/servers/slapd/overlays/syncprov.c
index 84fe37afcbcc98b0ffd8fd65944e9312a1839a94..345bcb251c26f80d0177c23a65e2d25d0616932e 100644
--- a/servers/slapd/overlays/syncprov.c
+++ b/servers/slapd/overlays/syncprov.c
@@ -147,7 +147,9 @@ typedef struct opcookie {
 	struct berval sndn;
 	struct berval suuid;	/* UUID of entry */
 	struct berval sctxcsn;
-	int sreference;	/* Is the entry a reference? */
+	short osid;	/* sid of op csn */
+	short rsid;	/* sid of relay */
+	short sreference;	/* Is the entry a reference? */
 } opcookie;
 
 typedef struct fbase_cookie {
@@ -790,9 +792,17 @@ syncprov_sendresp( Operation *op, opcookie *opc, syncops *so,
 	ctrls[1] = NULL;
 	csns[0] = opc->sctxcsn;
 	BER_BVZERO( &csns[1] );
-	slap_compose_sync_cookie( op, &cookie, csns, so->s_rid, so->s_sid );
+	slap_compose_sync_cookie( op, &cookie, csns, so->s_rid, slap_serverID ? slap_serverID : -1 );
 
-	Debug( LDAP_DEBUG_SYNC, "syncprov_sendresp: cookie=%s\n", cookie.bv_val, 0, 0 );
+#ifdef LDAP_DEBUG
+	if ( so->s_sid > 0 ) {
+		Debug( LDAP_DEBUG_SYNC, "syncprov_sendresp: to=%03x, cookie=%s\n",
+			so->s_sid, cookie.bv_val, 0 );
+	} else {
+		Debug( LDAP_DEBUG_SYNC, "syncprov_sendresp: cookie=%s\n",
+			cookie.bv_val, 0, 0 );
+	}
+#endif
 
 	e_uuid.e_attrs = &a_uuid;
 	a_uuid.a_desc = slap_schema.si_ad_entryUUID;
@@ -1021,12 +1031,7 @@ syncprov_qresp( opcookie *opc, syncops *so, int mode )
 		syncprov_info_t	*si = opc->son->on_bi.bi_private;
 
 		slap_compose_sync_cookie( NULL, &cookie, si->si_ctxcsn,
-			so->s_rid, so->s_sid);
-	} else if ( opc->sctxcsn.bv_len ) {
-		/* Don't send changes back to their originator */
-		int sid = slap_parse_csn_sid( &opc->sctxcsn );
-		if ( sid >= 0 && sid == so->s_sid )
-			return LDAP_SUCCESS;
+			so->s_rid, slap_serverID ? slap_serverID : -1);
 	}
 
 	srsize = sizeof(syncres) + opc->suuid.bv_len + 1 +
@@ -1217,6 +1222,24 @@ syncprov_matchops( Operation *op, opcookie *opc, int saveit )
 		if ( ss->s_op->o_abandon )
 			continue;
 
+		/* First time thru, check for possible skips */
+		if ( saveit || op->o_tag == LDAP_REQ_ADD ) {
+
+			/* Don't send ops back to the originator */
+			if ( opc->osid > 0 && opc->osid == ss->s_sid ) {
+				Debug( LDAP_DEBUG_SYNC, "syncprov_matchops: skipping original sid %03x\n",
+					opc->osid, 0, 0 );
+				continue;
+			}
+
+			/* Don't send ops back to the messenger */
+			if ( opc->rsid > 0 && opc->rsid == ss->s_sid ) {
+				Debug( LDAP_DEBUG_SYNC, "syncprov_matchops: skipping relayed sid %03x\n",
+					opc->rsid, 0, 0 );
+				continue;
+			}
+		}
+
 		/* validate base */
 		fc.fss = ss;
 		fc.fbase = 0;
@@ -1264,11 +1287,14 @@ syncprov_matchops( Operation *op, opcookie *opc, int saveit )
 			oh.oh_connid = ss->s_op->o_connid;
 			op2.o_hdr = &oh;
 			op2.o_extra = op->o_extra;
+			rc = test_filter( &op2, e, ss->s_op->ors_filter );
 		}
 
+		Debug( LDAP_DEBUG_TRACE, "syncprov_matchops: sid %03x fscope %d rc %d\n",
+			ss->s_sid, fc.fscope, rc );
+
 		/* check if current o_req_dn is in scope and matches filter */
-		if ( fc.fscope && test_filter( &op2, e, ss->s_op->ors_filter ) ==
-			LDAP_COMPARE_TRUE ) {
+		if ( fc.fscope && rc == LDAP_COMPARE_TRUE ) {
 			if ( saveit ) {
 				sm = op->o_tmpalloc( sizeof(syncmatches), op->o_tmpmemctx );
 				sm->sm_next = opc->smatches;
@@ -1624,7 +1650,7 @@ syncprov_playlog( Operation *op, SlapReply *rs, sessionlog *sl,
 
 		if ( delcsn[0].bv_len ) {
 			slap_compose_sync_cookie( op, &cookie, delcsn, srs->sr_state.rid,
-				srs->sr_state.sid );
+				slap_serverID ? slap_serverID : -1 );
 
 			Debug( LDAP_DEBUG_SYNC, "syncprov_playlog: cookie=%s\n", cookie.bv_val, 0, 0 );
 		}
@@ -1867,6 +1893,18 @@ syncprov_op_mod( Operation *op, SlapReply *rs )
 	cb->sc_next = op->o_callback;
 	op->o_callback = cb;
 
+	opc->osid = -1;
+	opc->rsid = -1;
+	if ( op->o_csn.bv_val ) {
+		opc->osid = slap_parse_csn_sid( &op->o_csn );
+	}
+	if ( op->o_controls ) {
+		struct sync_cookie *scook =
+		op->o_controls[slap_cids.sc_LDAPsync];
+		if ( scook )
+			opc->rsid = scook->sid;
+	}
+
 	/* If there are active persistent searches, lock this operation.
 	 * See seqmod.c for the locking logic on its own.
 	 */
@@ -1894,6 +1932,9 @@ syncprov_op_mod( Operation *op, SlapReply *rs )
 				 * Currently it's not an issue because there are
 				 * no dynamic config deletes...
 				 */
+				if ( slapd_shutdown )
+					return SLAPD_ABANDON;
+
 				if ( !ldap_pvt_thread_pool_pausecheck( &connection_pool ))
 					ldap_pvt_thread_yield();
 				ldap_pvt_thread_mutex_lock( &mt->mt_mutex );
@@ -2136,7 +2177,7 @@ syncprov_search_response( Operation *op, SlapReply *rs )
 		/* If we're in delta-sync mode, always send a cookie */
 		if ( si->si_nopres && si->si_usehint && a ) {
 			struct berval cookie;
-			slap_compose_sync_cookie( op, &cookie, a->a_nvals, srs->sr_state.rid, srs->sr_state.sid );
+			slap_compose_sync_cookie( op, &cookie, a->a_nvals, srs->sr_state.rid, slap_serverID ? slap_serverID : -1 );
 			rs->sr_err = syncprov_state_ctrl( op, rs, rs->sr_entry,
 				LDAP_SYNC_ADD, rs->sr_ctrls, 0, 1, &cookie );
 		} else {
@@ -2148,7 +2189,7 @@ syncprov_search_response( Operation *op, SlapReply *rs )
 
 		if ( ss->ss_flags & SS_CHANGED ) {
 			slap_compose_sync_cookie( op, &cookie, ss->ss_ctxcsn,
-				srs->sr_state.rid, srs->sr_state.sid );
+				srs->sr_state.rid, slap_serverID ? slap_serverID : -1 );
 
 			Debug( LDAP_DEBUG_SYNC, "syncprov_search_response: cookie=%s\n", cookie.bv_val, 0, 0 );
 		}
diff --git a/servers/slapd/syncrepl.c b/servers/slapd/syncrepl.c
index 111a427b774b5c1552e918c7cdef7edc899b214b..76b9ec1a97c4e11bbff14032787d0d678f1b9dac 100644
--- a/servers/slapd/syncrepl.c
+++ b/servers/slapd/syncrepl.c
@@ -863,6 +863,7 @@ do_syncrep2(
 							}
 						}
 					}
+					op->o_controls[slap_cids.sc_LDAPsync] = &syncCookie;
 				}
 			}
 			rc = 0;
@@ -969,6 +970,7 @@ do_syncrep2(
 					if ( !BER_BVISNULL( &syncCookie.octet_str ) )
 					{
 						slap_parse_sync_cookie( &syncCookie, NULL );
+						op->o_controls[slap_cids.sc_LDAPsync] = &syncCookie;
 					}
 				}
 				if ( ber_peek_tag( ber, &len ) == LDAP_TAG_REFRESHDELETES )
@@ -1047,6 +1049,7 @@ do_syncrep2(
 					}
 					if (!BER_BVISNULL( &syncCookie.octet_str ) ) {
 						slap_parse_sync_cookie( &syncCookie, NULL );
+						op->o_controls[slap_cids.sc_LDAPsync] = &syncCookie;
 					}
 					break;
 				case LDAP_TAG_SYNC_REFRESH_DELETE:
@@ -1077,6 +1080,7 @@ do_syncrep2(
 						if ( !BER_BVISNULL( &syncCookie.octet_str ) )
 						{
 							slap_parse_sync_cookie( &syncCookie, NULL );
+							op->o_controls[slap_cids.sc_LDAPsync] = &syncCookie;
 						}
 					}
 					/* Defaults to TRUE */
@@ -1112,6 +1116,7 @@ do_syncrep2(
 						if ( !BER_BVISNULL( &syncCookie.octet_str ) )
 						{
 							slap_parse_sync_cookie( &syncCookie, NULL );
+							op->o_controls[slap_cids.sc_LDAPsync] = &syncCookie;
 							compare_csns( &syncCookie_req, &syncCookie, &m );
 						}
 					}