diff --git a/doc/release-notes-5853.md b/doc/release-notes-5853.md
new file mode 100644
index 0000000000000..f2a52635a5a1d
--- /dev/null
+++ b/doc/release-notes-5853.md
@@ -0,0 +1,6 @@
+Added RPC
+--------
+
+- `quorum dkginfo` RPC returns information about DKGs:
+  - `active_dkgs`: Total number of active DKG sessions this node is participating in right now.
+  - `next_dkg`: The number of blocks until the next potential DKG session.
diff --git a/src/rpc/quorums.cpp b/src/rpc/quorums.cpp
index 37059788f1fbf..82ca73c9e26d3 100644
--- a/src/rpc/quorums.cpp
+++ b/src/rpc/quorums.cpp
@@ -789,6 +789,49 @@ static UniValue quorum_rotationinfo(const JSONRPCRequest& request, const LLMQCon
     return quorumRotationInfoRet.ToJson();
 }
 
+static void quorum_dkginfo_help(const JSONRPCRequest& request)
+{
+    RPCHelpMan{
+        "quorum dkginfo",
+        "Return information regarding DKGs.\n",
+        {
+            {},
+        },
+        RPCResult{
+            RPCResult::Type::OBJ, "", "",
+            {
+                {RPCResult::Type::NUM, "active_dkgs", "Total number of active DKG sessions this node is participating in right now"},
+                {RPCResult::Type::NUM, "next_dkg", "The number of blocks until the next potential DKG session"},
+            }
+        },
+        RPCExamples{""},
+    }.Check(request);
+}
+
+static UniValue quorum_dkginfo(const JSONRPCRequest& request, const LLMQContext& llmq_ctx, const ChainstateManager& chainman)
+{
+    quorum_dkginfo_help(request);
+
+    llmq::CDKGDebugStatus status;
+    llmq_ctx.dkg_debugman->GetLocalDebugStatus(status);
+    UniValue ret(UniValue::VOBJ);
+    ret.pushKV("active_dkgs", int(status.sessions.size()));
+
+    const int nTipHeight{WITH_LOCK(cs_main, return chainman.ActiveChain().Height())};
+    auto minNextDKG = [](const Consensus::Params& consensusParams, int nTipHeight) {
+        int minDkgWindow{std::numeric_limits<int>::max()};
+        for (const auto& params: consensusParams.llmqs) {
+            if (params.useRotation && (nTipHeight % params.dkgInterval <= params.signingActiveQuorumCount)) {
+                return 1;
+            }
+            minDkgWindow = std::min(minDkgWindow, params.dkgInterval - (nTipHeight % params.dkgInterval));
+        }
+        return minDkgWindow;
+    };
+    ret.pushKV("next_dkg", minNextDKG(Params().GetConsensus(), nTipHeight));
+
+    return ret;
+}
 
 [[ noreturn ]] static void quorum_help()
 {
@@ -801,6 +844,7 @@ static UniValue quorum_rotationinfo(const JSONRPCRequest& request, const LLMQCon
             "  list              - List of on-chain quorums\n"
             "  listextended      - Extended list of on-chain quorums\n"
             "  info              - Return information about a quorum\n"
+            "  dkginfo           - Return information about DKGs\n"
             "  dkgsimerror       - Simulates DKG errors and malicious behavior\n"
             "  dkgstatus         - Return the status of the current DKG process\n"
             "  memberof          - Checks which quorums the given masternode is a member of\n"
@@ -836,6 +880,8 @@ static UniValue _quorum(const JSONRPCRequest& request)
         return quorum_list_extended(new_request, chainman, llmq_ctx);
     } else if (command == "quoruminfo") {
         return quorum_info(new_request, llmq_ctx);
+    } else if (command == "quorumdkginfo") {
+        return quorum_dkginfo(new_request, llmq_ctx, chainman);
     } else if (command == "quorumdkgstatus") {
         return quorum_dkgstatus(new_request, chainman, llmq_ctx);
     } else if (command == "quorummemberof") {
diff --git a/test/functional/feature_llmq_rotation.py b/test/functional/feature_llmq_rotation.py
index 117f36666b596..568358a4ca6dd 100755
--- a/test/functional/feature_llmq_rotation.py
+++ b/test/functional/feature_llmq_rotation.py
@@ -76,6 +76,13 @@ def run_test(self):
 
         b_h_0 = self.nodes[0].getbestblockhash()
 
+        tip = self.nodes[0].getblockcount()
+        next_dkg = 24 - (tip % 24)
+        for node in self.nodes:
+            dkg_info = node.quorum("dkginfo")
+            assert_equal(dkg_info['active_dkgs'], 0)
+            assert_equal(dkg_info['next_dkg'], next_dkg)
+
         #Mine 2 quorums so that Chainlocks can be available: Need them to include CL in CbTx as soon as v20 activates
         self.log.info("Mining 2 quorums")
         h_0 = self.mine_quorum()
@@ -93,6 +100,18 @@ def run_test(self):
 
         b_h_1 = self.nodes[0].getbestblockhash()
 
+        tip = self.nodes[0].getblockcount()
+        next_dkg = 24 - (tip % 24)
+        assert next_dkg < 24
+        nonzero_dkgs = 0
+        for i in range(len(self.nodes)):
+            dkg_info = self.nodes[i].quorum("dkginfo")
+            if i == 0:
+                assert_equal(dkg_info['active_dkgs'], 0)
+            nonzero_dkgs += dkg_info['active_dkgs']
+            assert_equal(dkg_info['next_dkg'], next_dkg)
+        assert_equal(nonzero_dkgs, 11) # 2 quorums 4 nodes each and 1 quorum of 3 nodes
+
         expectedDeleted = []
         expectedNew = [h_100_0, h_106_0, h_104_0, h_100_1, h_106_1, h_104_1]
         quorumList = self.test_getmnlistdiff_quorums(b_h_0, b_h_1, {}, expectedDeleted, expectedNew, testQuorumsCLSigs=False)