diff --git a/assignment-client/src/audio/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h
index e542d82a6a..ed3a5b0541 100644
--- a/assignment-client/src/audio/AudioMixer.h
+++ b/assignment-client/src/audio/AudioMixer.h
@@ -51,6 +51,11 @@ public:
     static const QVector<ReverbSettings>& getReverbSettings() { return _zoneReverbSettings; }
     static const std::pair<QString, CodecPluginPointer> negotiateCodec(std::vector<QString> codecs);
 
+    static bool shouldReplicateTo(const Node& from, const Node& to) {
+        return to.getType() == NodeType::DownstreamAudioMixer &&
+               to.getPublicSocket() != from.getPublicSocket() &&
+               to.getLocalSocket() != from.getLocalSocket();
+    }
 public slots:
     void run() override;
     void sendStatsPacket() override;
diff --git a/assignment-client/src/audio/AudioMixerClientData.cpp b/assignment-client/src/audio/AudioMixerClientData.cpp
index 0467b82d40..8befaff9c2 100644
--- a/assignment-client/src/audio/AudioMixerClientData.cpp
+++ b/assignment-client/src/audio/AudioMixerClientData.cpp
@@ -146,7 +146,7 @@ void AudioMixerClientData::optionallyReplicatePacket(ReceivedMessage& message, c
 
         // enumerate the downstream audio mixers and send them the replicated version of this packet
         nodeList->unsafeEachNode([&](const SharedNodePointer& downstreamNode) {
-            if (downstreamNode->getType() == NodeType::DownstreamAudioMixer) {
+            if (AudioMixer::shouldReplicateTo(node, *downstreamNode)) {
                 // construct the packet only once, if we have any downstream audio mixers to send to
                 if (!packet) {
                     // construct an NLPacket to send to the replicant that has the contents of the received packet
diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp
index 40cc3a1c0e..3a5116a2e9 100644
--- a/assignment-client/src/avatars/AvatarMixer.cpp
+++ b/assignment-client/src/avatars/AvatarMixer.cpp
@@ -143,8 +143,8 @@ void AvatarMixer::optionallyReplicatePacket(ReceivedMessage& message, const Node
         std::unique_ptr<NLPacket> packet;
 
         auto nodeList = DependencyManager::get<NodeList>();
-        nodeList->eachMatchingNode([&](const SharedNodePointer& node) {
-            return node->getType() == NodeType::DownstreamAvatarMixer;
+        nodeList->eachMatchingNode([&](const SharedNodePointer& downstreamNode) {
+            return shouldReplicateTo(node, *downstreamNode);
         }, [&](const SharedNodePointer& node) {
             if (!packet) {
                 // construct an NLPacket to send to the replicant that has the contents of the received packet
@@ -424,8 +424,8 @@ void AvatarMixer::nodeKilled(SharedNodePointer killedNode) {
         nodeList->eachMatchingNode([&](const SharedNodePointer& node) {
             // we relay avatar kill packets to agents that are not upstream
             // and downstream avatar mixers, if the node that was just killed was being replicated
-            return (node->getType() == NodeType::Agent && !node->isUpstream())
-                || (killedNode->isReplicated() && node->getType() == NodeType::DownstreamAvatarMixer);
+            return (node->getType() == NodeType::Agent && !node->isUpstream()) ||
+                   (killedNode->isReplicated() && shouldReplicateTo(*killedNode, *node));
         }, [&](const SharedNodePointer& node) {
             if (node->getType() == NodeType::Agent) {
                 if (!killPacket) {
diff --git a/assignment-client/src/avatars/AvatarMixer.h b/assignment-client/src/avatars/AvatarMixer.h
index ecff7597f6..610da8ad57 100644
--- a/assignment-client/src/avatars/AvatarMixer.h
+++ b/assignment-client/src/avatars/AvatarMixer.h
@@ -28,6 +28,13 @@ class AvatarMixer : public ThreadedAssignment {
     Q_OBJECT
 public:
     AvatarMixer(ReceivedMessage& message);
+
+    static bool shouldReplicateTo(const Node& from, const Node& to) {
+        return to.getType() == NodeType::DownstreamAvatarMixer &&
+               to.getPublicSocket() != from.getPublicSocket() &&
+               to.getLocalSocket() != from.getLocalSocket();
+    }
+
 public slots:
     /// runs the avatar mixer
     void run() override;
diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp
index b2c6b6a341..bbf68f0e22 100644
--- a/assignment-client/src/avatars/AvatarMixerSlave.cpp
+++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp
@@ -79,13 +79,13 @@ int AvatarMixerSlave::sendIdentityPacket(const AvatarMixerClientData* nodeData,
     }
 }
 
-int AvatarMixerSlave::sendReplicatedIdentityPacket(const AvatarMixerClientData* nodeData, const SharedNodePointer& destinationNode) {
-    if (destinationNode->getType() == NodeType::DownstreamAvatarMixer) {
+int AvatarMixerSlave::sendReplicatedIdentityPacket(const Node& agentNode, const AvatarMixerClientData* nodeData, const Node& destinationNode) {
+    if (AvatarMixer::shouldReplicateTo(agentNode, destinationNode)) {
         QByteArray individualData = nodeData->getConstAvatarData()->identityByteArray();
         individualData.replace(0, NUM_BYTES_RFC4122_UUID, nodeData->getNodeID().toRfc4122()); // FIXME, this looks suspicious
         auto identityPacket = NLPacketList::create(PacketType::ReplicatedAvatarIdentity, QByteArray(), true, true);
         identityPacket->write(individualData);
-        DependencyManager::get<NodeList>()->sendPacketList(std::move(identityPacket), *destinationNode);
+        DependencyManager::get<NodeList>()->sendPacketList(std::move(identityPacket), destinationNode);
         _stats.numIdentityPackets++;
         return individualData.size();
     } else {
@@ -453,6 +453,10 @@ void AvatarMixerSlave::broadcastAvatarDataToDownstreamMixer(const SharedNodePoin
     nodeData->resetNumAvatarsSentLastFrame();
 
     std::for_each(_begin, _end, [&](const SharedNodePointer& agentNode) {
+        if (!AvatarMixer::shouldReplicateTo(*agentNode, *node)) {
+            return;
+        }
+        
         // collect agents that we have avatar data for that we are supposed to replicate
         if (agentNode->getType() == NodeType::Agent && agentNode->getLinkedData() && agentNode->isReplicated()) {
             const AvatarMixerClientData* agentNodeData = reinterpret_cast<const AvatarMixerClientData*>(agentNode->getLinkedData());
@@ -479,7 +483,7 @@ void AvatarMixerSlave::broadcastAvatarDataToDownstreamMixer(const SharedNodePoin
             auto lastBroadcastTime = nodeData->getLastBroadcastTime(agentNode->getUUID());
             if (lastBroadcastTime <= agentNodeData->getIdentityChangeTimestamp()
                 || (start - lastBroadcastTime) >= REBROADCAST_IDENTITY_TO_DOWNSTREAM_EVERY_US) {
-                sendReplicatedIdentityPacket(agentNodeData, node);
+                sendReplicatedIdentityPacket(*agentNode, agentNodeData, *node);
                 nodeData->setLastBroadcastTime(agentNode->getUUID(), start);
             }
 
diff --git a/assignment-client/src/avatars/AvatarMixerSlave.h b/assignment-client/src/avatars/AvatarMixerSlave.h
index 69c707bbf1..bdddd5ceab 100644
--- a/assignment-client/src/avatars/AvatarMixerSlave.h
+++ b/assignment-client/src/avatars/AvatarMixerSlave.h
@@ -95,7 +95,7 @@ public:
 
 private:
     int sendIdentityPacket(const AvatarMixerClientData* nodeData, const SharedNodePointer& destinationNode);
-    int sendReplicatedIdentityPacket(const AvatarMixerClientData* nodeData, const SharedNodePointer& destinationNode);
+    int sendReplicatedIdentityPacket(const Node& agentNode, const AvatarMixerClientData* nodeData, const Node& destinationNode);
 
     void broadcastAvatarDataToAgent(const SharedNodePointer& node);
     void broadcastAvatarDataToDownstreamMixer(const SharedNodePointer& node);