diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h
index f87e21df2cb498c48a2f1714b7f98852f07652c5..425508c53ea933f9e101266f8260bcefee6ce50f 100644
--- a/include/afl-fuzz.h
+++ b/include/afl-fuzz.h
@@ -399,7 +399,7 @@ typedef struct afl_env_vars {
       afl_cycle_schedules, afl_expand_havoc, afl_statsd, afl_cmplog_only_new,
       afl_exit_on_seed_issues, afl_try_affinity, afl_ignore_problems,
       afl_keep_timeouts, afl_no_crash_readme, afl_ignore_timeouts,
-      afl_no_startup_calibration, afl_no_warn_instability;
+      afl_no_startup_calibration, afl_no_warn_instability, afl_serialize_exec;
 
   u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path,
       *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload,
@@ -596,7 +596,7 @@ typedef struct afl_state {
       longest_find_time,                /* Longest time taken for a find    */
       exit_on_time,                     /* Delay to exit if no new paths    */
       sync_time,                        /* Sync time (ms)                   */
-      sync_delay;                       /* Sync delay (ms)                   */
+      sync_delay;                       /* Sync delay (ms)                  */
 
   u32 slowest_exec_ms,                  /* Slowest testcase non hang in ms  */
       subseq_tmouts;                    /* Number of timeouts in a row      */
diff --git a/include/envs.h b/include/envs.h
index 942aab669c1d1196fd5ab0d4c7c908c8c637936c..9b13295b04586e3ad2336d3f326ceeeda71d38a8 100644
--- a/include/envs.h
+++ b/include/envs.h
@@ -211,6 +211,7 @@ static char *afl_environment_variables[] = {
     "AFL_QUIET",
     "AFL_RANDOM_ALLOC_CANARY",
     "AFL_REAL_PATH",
+    "AFL_SERIALIZE_EXEC",
     "AFL_SHUFFLE_QUEUE",
     "AFL_SKIP_BIN_CHECK",
     "AFL_SKIP_CPUFREQ",
diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c
index 60206b4a7e66b385bb7654a56c1fc78fe974b63b..1b47cc0046a1b3d925ff5ba07075444bc009aa41 100644
--- a/src/afl-fuzz-state.c
+++ b/src/afl-fuzz-state.c
@@ -584,6 +584,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
 
             }
 
+          } else if (!strncmp(env, "AFL_SERIALIZE_EXEC",
+
+                              afl_environment_variable_len)) {
+
+            afl->afl_env.afl_serialize_exec =
+                get_afl_env(afl_environment_variables[i]) ? 1 : 0;
+
           } else if (!strncmp(env, "AFL_FUZZER_STATS_UPDATE_INTERVAL",
 
                               afl_environment_variable_len)) {
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index b93b04efc83442538e4ad2bd483a0f75e0f33d00..58f90669a0a50eb0f08f0d0371923bea2908253b 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -453,6 +453,12 @@ int main(int argc, char **argv_orig, char **envp) {
   struct timeval  tv;
   struct timezone tz;
 
+  u8* syncpath = NULL;
+  s32 sync_fd;
+  struct flock synclock = { F_UNLCK, SEEK_SET, 0, 0, 0 };
+  u64 sync_work = 0, sleep_start = 0, tot_sleep = 0;
+  u8 done_work = 0;
+
   #if defined USE_COLOR && defined ALWAYS_COLORED
   if (getenv("AFL_NO_COLOR") || getenv("AFL_NO_COLOUR")) {
 
@@ -1406,6 +1412,18 @@ int main(int argc, char **argv_orig, char **envp) {
 
     fix_up_sync(afl);
 
+    if (afl->afl_env.afl_serialize_exec) {
+
+      syncpath = alloc_printf("%s/.serialize", afl->sync_dir);
+
+      sync_fd = open(syncpath, O_RDWR | O_CREAT, 0644);
+
+      if (sync_fd < 0) {
+        PFATAL("Unable to open fuzzer serialization file.");
+      }
+
+    }
+
   }
 
   if (!strcmp(afl->in_dir, afl->out_dir)) {
@@ -2506,6 +2524,61 @@ int main(int argc, char **argv_orig, char **envp) {
 
     do {
 
+      if (afl->sync_id && afl->afl_env.afl_serialize_exec) {
+
+        // Acquire lock on serialization sync file
+        if (synclock.l_type == F_UNLCK) {
+
+          synclock.l_type = F_WRLCK;
+          if (fcntl(sync_fd, F_SETLKW, &synclock) < 0) {
+              PFATAL("Unable to fcntl() fuzzer serialization file.");
+          }
+
+          if (sleep_start) {
+            tot_sleep += get_cur_time() - sleep_start;
+          }
+
+          s64 res;
+
+          if (lseek(sync_fd, 0, SEEK_SET) < 0 ||
+              (res = read(sync_fd, &sync_work, sizeof(sync_work))) < 0) {
+            PFATAL("Unable to read fuzzer serialization file.");
+          }
+
+          if (res == 0) {
+            sync_work = 0;
+          }
+
+        }
+
+        u64 tot_work = get_cur_time() - afl->start_time - tot_sleep;
+
+        if (done_work && sync_work + 1000 < tot_work) {
+
+          if (lseek(sync_fd, 0, SEEK_SET) < 0 ||
+              write(sync_fd, &tot_work, sizeof(tot_work)) < 0) {
+            PFATAL("Unable to write to fuzzer serialization file.");
+          }
+
+          sleep_start = get_cur_time();
+          done_work = 0;
+
+          // Release lock
+          synclock.l_type = F_UNLCK;
+          if (fcntl(sync_fd, F_SETLK, &synclock) < 0) {
+            PFATAL("Unable to fcntl() fuzzer serialization file.");
+          }
+
+          // Yield execution
+          usleep(1000);
+
+          continue;
+        }
+
+        done_work = 1;
+
+      }
+
       if (likely(!afl->old_seed_selection)) {
 
         if (unlikely(prev_queued_items < afl->queued_items ||
@@ -2695,6 +2768,19 @@ stop_fuzzing:
 
   }
 
+  if (afl->sync_id && afl->afl_env.afl_serialize_exec) {
+
+    /* TODO: This only works as intended when all fuzzer instances shut down
+       sequentially. Will break if one instance exits and another one joins
+       before all others have shut down. (Running instances keep references to
+       inode until all fds have been closed.)*/
+
+    close(sync_fd);
+    unlink(syncpath);
+    free(syncpath);
+
+  }
+
   if (frida_afl_preload) { ck_free(frida_afl_preload); }
 
   fclose(afl->fsrv.plot_file);