diff --git a/command.c b/command.c
index 4d0b1044e8..17ebcc58d9 100644
--- a/command.c
+++ b/command.c
@@ -2020,12 +2020,6 @@ bool command_event(enum event_command cmd, void *data)
          {
 #ifdef HAVE_CHEEVOS
             settings_t *settings      = config_get_ptr();
-#endif
-#ifdef HAVE_NETWORKING
-            if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL))
-               return false;
-#endif
-#ifdef HAVE_CHEEVOS
             if (settings->cheevos.hardcore_mode_enable)
                return false;
 #endif
@@ -2041,13 +2035,8 @@ bool command_event(enum event_command cmd, void *data)
                return false;
 #endif
 
-#ifdef HAVE_NETWORKING
-            if (!netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL))
-#endif
-            {
-               if (settings->rewind_enable)
-                  state_manager_event_init((unsigned)settings->rewind_buffer_size);
-            }
+            if (settings->rewind_enable)
+               state_manager_event_init((unsigned)settings->rewind_buffer_size);
          }
          break;
       case CMD_EVENT_REWIND_TOGGLE:
diff --git a/managers/state_manager.c b/managers/state_manager.c
index 39a55c236f..8ab2563ae0 100644
--- a/managers/state_manager.c
+++ b/managers/state_manager.c
@@ -31,6 +31,10 @@
 #include "../verbosity.h"
 #include "../audio/audio_driver.h"
 
+#ifdef HAVE_NETWORKING
+#include "../network/netplay/netplay.h"
+#endif
+
 /* This makes Valgrind throw errors if a core overflows its savestate size. */
 /* Keep it off unless you're chasing a core bug, it slows things down. */
 #define STRICT_BUF_SIZE 0
@@ -687,9 +691,11 @@ bool state_manager_check_rewind(bool pressed,
 {
    bool ret             = false;
    static bool first    = true;
+   bool was_reversed    = false;
 
    if (state_manager_frame_is_reversed())
    {
+      was_reversed = true;
       audio_driver_frame_is_reverse();
       state_manager_set_frame_is_reversed(false);
    }
@@ -711,6 +717,14 @@ bool state_manager_check_rewind(bool pressed,
       {
          retro_ctx_serialize_info_t serial_info;
 
+#ifdef HAVE_NETWORKING
+         if (!was_reversed)
+         {
+            /* Make sure netplay isn't confused */
+            netplay_driver_ctl(RARCH_NETPLAY_CTL_DESYNC_PUSH, NULL);
+         }
+#endif
+
          state_manager_set_frame_is_reversed(true);
 
          audio_driver_setup_rewind();
@@ -735,6 +749,14 @@ bool state_manager_check_rewind(bool pressed,
          serial_info.size       = rewind_state.size;
          core_unserialize(&serial_info);
 
+#ifdef HAVE_NETWORKING
+         if (was_reversed)
+         {
+            /* Tell netplay we're done */
+            netplay_driver_ctl(RARCH_NETPLAY_CTL_DESYNC_POP, NULL);
+         }
+#endif
+
          strlcpy(s, 
                msg_hash_to_str(MSG_REWIND_REACHED_END),
                len);
@@ -747,6 +769,14 @@ bool state_manager_check_rewind(bool pressed,
    {
       static unsigned cnt      = 0;
 
+#ifdef HAVE_NETWORKING
+      if (was_reversed)
+      {
+         /* Tell netplay we're done */
+         netplay_driver_ctl(RARCH_NETPLAY_CTL_DESYNC_POP, NULL);
+      }
+#endif
+
       cnt = (cnt + 1) % (rewind_granularity ?
             rewind_granularity : 1); /* Avoid possible SIGFPE. */
 
diff --git a/network/netplay/netplay.h b/network/netplay/netplay.h
index 8a22bc12dd..38b04326ab 100644
--- a/network/netplay/netplay.h
+++ b/network/netplay/netplay.h
@@ -46,7 +46,9 @@ enum rarch_netplay_ctl_state
    RARCH_NETPLAY_CTL_LOAD_SAVESTATE,
    RARCH_NETPLAY_CTL_RESET,
    RARCH_NETPLAY_CTL_DISCONNECT,
-   RARCH_NETPLAY_CTL_FINISHED_NAT_TRAVERSAL
+   RARCH_NETPLAY_CTL_FINISHED_NAT_TRAVERSAL,
+   RARCH_NETPLAY_CTL_DESYNC_PUSH,
+   RARCH_NETPLAY_CTL_DESYNC_POP
 };
 
 int16_t input_state_net(unsigned port, unsigned device,
diff --git a/network/netplay/netplay_frontend.c b/network/netplay/netplay_frontend.c
index 1327354d13..0f0e941026 100644
--- a/network/netplay/netplay_frontend.c
+++ b/network/netplay/netplay_frontend.c
@@ -996,6 +996,10 @@ void netplay_load_savestate(netplay_t *netplay,
       }
    }
 
+   /* Don't send it if we're expected to be desynced */
+   if (netplay->desync)
+      return;
+
    /* If we can't send it to the peer, loading a state was a bad idea */
    if (netplay->quirks & (
               NETPLAY_QUIRK_NO_SAVESTATES
@@ -1319,6 +1323,17 @@ bool netplay_driver_ctl(enum rarch_netplay_ctl_state state, void *data)
          netplay_announce_nat_traversal(netplay_data);
 #endif
          goto done;
+      case RARCH_NETPLAY_CTL_DESYNC_PUSH:
+         netplay_data->desync++;
+         break;
+      case RARCH_NETPLAY_CTL_DESYNC_POP:
+         if (netplay_data->desync)
+         {
+            netplay_data->desync--;
+            if (!netplay_data->desync)
+               netplay_load_savestate(netplay_data, NULL, true);
+         }
+         break;
       default:
       case RARCH_NETPLAY_CTL_NONE:
          ret = false;
diff --git a/network/netplay/netplay_private.h b/network/netplay/netplay_private.h
index fc4a7bd751..272c96cfae 100644
--- a/network/netplay/netplay_private.h
+++ b/network/netplay/netplay_private.h
@@ -354,6 +354,10 @@ struct netplay
     * connected_players) */
    uint32_t connected_slaves;
 
+   /* Number of desync operations we're currently performing. If set, we don't
+    * attempt to stay in sync. */
+   uint32_t desync;
+
    /* Maximum player number */
    uint32_t player_max;
 
diff --git a/network/netplay/netplay_sync.c b/network/netplay/netplay_sync.c
index cf624c81de..bcaedb364e 100644
--- a/network/netplay/netplay_sync.c
+++ b/network/netplay/netplay_sync.c
@@ -389,9 +389,10 @@ void netplay_sync_post_frame(netplay_t *netplay, bool stalled)
       netplay->self_frame_count++;
    }
 
-   /* Only relevant if we're connected */
+   /* Only relevant if we're connected and not in a desynching operation */
    if ((netplay->is_server && !netplay->connected_players) ||
-       (netplay->self_mode < NETPLAY_CONNECTION_CONNECTED))
+       (netplay->self_mode < NETPLAY_CONNECTION_CONNECTED) ||
+       (netplay->desync))
    {
       netplay->other_frame_count = netplay->self_frame_count;
       netplay->other_ptr = netplay->self_ptr;