diff --git a/src/openvpn/init.c b/src/openvpn/init.c
index 3c2ebf9..06effe2 100644
--- a/src/openvpn/init.c
+++ b/src/openvpn/init.c
@@ -3286,6 +3286,7 @@
     to.packet_timeout = options->tls_timeout;
     to.renegotiate_bytes = options->renegotiate_bytes;
     to.renegotiate_packets = options->renegotiate_packets;
+    to.aead_usage_limit_override = options->aead_usage_limit_override;
     if (options->renegotiate_seconds_min < 0)
     {
         /* Add 10% jitter to reneg-sec by default (server side only) */
diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index 7fc8614..1630731 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -7609,6 +7609,20 @@
             options->renegotiate_seconds_min = positive_atoi(p[2], msglevel);
         }
     }
+#ifdef ENABLE_DEBUG
+    else if (streq(p[0], "debug-aead-usage-limit-override"))
+    {
+        /* This option is undocumented since it should not be used by normal
+         * users */
+        VERIFY_PERMISSION(OPT_P_TLS_PARMS);
+        if (!positive_atoll(p[1], &options->aead_usage_limit_override, p[0], msglevel))
+        {
+            msg(M_VERB0, "Warning: --debug-aead-usage-limit-override should "
+                         "only be used by developers and in specific tests.");
+            goto err;
+        }
+    }
+#endif
     else if (streq(p[0], "hand-window") && p[1] && !p[2])
     {
         VERIFY_PERMISSION(OPT_P_TLS_PARMS);
diff --git a/src/openvpn/options.h b/src/openvpn/options.h
index d347830..693d9cf 100644
--- a/src/openvpn/options.h
+++ b/src/openvpn/options.h
@@ -647,6 +647,9 @@
     int renegotiate_seconds;
     int renegotiate_seconds_min;
 
+    /** Debug override to trigger AEAD usage limit early */
+    int64_t aead_usage_limit_override;
+
     /* Data channel key handshake must finalize
      * within n seconds of handshake initiation. */
     int handshake_window;
diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
index 3594871..3fd52f0 100644
--- a/src/openvpn/ssl.c
+++ b/src/openvpn/ssl.c
@@ -126,11 +126,11 @@
 }
 
 static uint64_t
-tls_get_limit_aead(const char *ciphername)
+tls_get_limit_aead(const char *ciphername, uint64_t override)
 {
     uint64_t limit = cipher_get_aead_limits(ciphername);
 
-    if (limit == 0)
+    if (limit == 0 && override == 0)
     {
         return 0;
     }
@@ -139,6 +139,11 @@
      * we go over the limit */
     limit = limit / 8 * 7;
 
+    if (override > 0)
+    {
+        limit = override;
+    }
+
     msg(D_SHOW_KEYS,
         "Note: AEAD cipher %s will trigger a renegotiation"
         " at a sum of %" PRIi64 " blocks and packets.",
@@ -1397,6 +1402,11 @@
      * */
     epoch_init_key_ctx(co, key_type, &e1_send, &e1_recv, future_key_count);
 
+    if (multi->opt.aead_usage_limit_override)
+    {
+        co->aead_usage_limit = multi->opt.aead_usage_limit_override;
+    }
+
     secure_memzero(&e1_send, sizeof(e1_send));
     secure_memzero(&e1_recv, sizeof(e1_recv));
 }
@@ -1619,7 +1629,7 @@
     }
     tls_limit_reneg_bytes(session->opt->key_type.cipher, &session->opt->renegotiate_bytes);
 
-    session->opt->aead_usage_limit = tls_get_limit_aead(session->opt->key_type.cipher);
+    session->opt->aead_usage_limit = tls_get_limit_aead(session->opt->key_type.cipher, session->opt->aead_usage_limit_override);
 
     /* set the state of the keys for the session to generated */
     ks->state = S_GENERATED_KEYS;
diff --git a/src/openvpn/ssl_common.h b/src/openvpn/ssl_common.h
index f6392f9..579f46c 100644
--- a/src/openvpn/ssl_common.h
+++ b/src/openvpn/ssl_common.h
@@ -346,6 +346,11 @@
     /** limit for AEAD cipher when not running in epoch data key mode,
      *  this is the sum of packets + blocks that are allowed to be used */
     uint64_t aead_usage_limit;
+    /**
+     * Debug only option that allows overriding the usage limit
+     * This allows testing key rotation by using very small limits
+     */
+    uint64_t aead_usage_limit_override;
     interval_t renegotiate_seconds;
 
     /* cert verification parms */
