diff --git a/changelog.d/10223.bugfix b/changelog.d/10223.bugfix
new file mode 100644
index 0000000000000000000000000000000000000000..4e42f6b6087fb0484027eb256a70130ca7848b7e
--- /dev/null
+++ b/changelog.d/10223.bugfix
@@ -0,0 +1 @@
+Fix a long-standing bug which meant that invite rejections and knocks were not sent out over federation in a timely manner.
diff --git a/scripts-dev/complement.sh b/scripts-dev/complement.sh
index ba060104c3aabee339c90993700bd116bd7681b0..aca32edc176e210a24b37fcab467afc469c73c30 100755
--- a/scripts-dev/complement.sh
+++ b/scripts-dev/complement.sh
@@ -65,4 +65,4 @@ if [[ -n "$1" ]]; then
 fi
 
 # Run the tests!
-go test -v -tags synapse_blacklist,msc2946,msc3083,msc2716 -count=1 $EXTRA_COMPLEMENT_ARGS ./tests
+go test -v -tags synapse_blacklist,msc2946,msc3083,msc2716,msc2403 -count=1 $EXTRA_COMPLEMENT_ARGS ./tests
diff --git a/synapse/handlers/federation.py b/synapse/handlers/federation.py
index 1b566dbf2dad304e31a1ea02e3f4025e7126cb2c..74d169a2ac973450110e0dbc53686130b87ad21a 100644
--- a/synapse/handlers/federation.py
+++ b/synapse/handlers/federation.py
@@ -1980,6 +1980,13 @@ class FederationHandler(BaseHandler):
 
         event.internal_metadata.outlier = False
 
+        # Send this event on behalf of the other server.
+        #
+        # The remote server isn't a full participant in the room at this point, so
+        # may not have an up-to-date list of the other homeservers participating in
+        # the room, so we send it on their behalf.
+        event.internal_metadata.send_on_behalf_of = origin
+
         context = await self.state_handler.compute_event_context(event)
         await self._auth_and_persist_event(origin, event, context)
 
@@ -2084,6 +2091,13 @@ class FederationHandler(BaseHandler):
 
         event.internal_metadata.outlier = False
 
+        # Send this event on behalf of the other server.
+        #
+        # The remote server isn't a full participant in the room at this point, so
+        # may not have an up-to-date list of the other homeservers participating in
+        # the room, so we send it on their behalf.
+        event.internal_metadata.send_on_behalf_of = origin
+
         context = await self.state_handler.compute_event_context(event)
 
         event_allowed = await self.third_party_event_rules.check_event_allowed(