diff --git a/lua/lazy/core/handler/event.lua b/lua/lazy/core/handler/event.lua
index dd1a38f..018d04b 100644
--- a/lua/lazy/core/handler/event.lua
+++ b/lua/lazy/core/handler/event.lua
@@ -64,10 +64,11 @@ end
 
 ---@param plugin LazyPlugin
 function M:values(plugin)
+  local Plugin = require("lazy.core.plugin")
   ---@type table<string,any>
   local values = {}
   ---@diagnostic disable-next-line: no-unknown
-  for _, value in ipairs(plugin[self.type] or {}) do
+  for _, value in ipairs(Plugin.values(plugin, self.type, true)) do
     local event = self:parse(value)
     values[event.id] = event
   end
diff --git a/lua/lazy/core/handler/init.lua b/lua/lazy/core/handler/init.lua
index 127ccae..8a5179d 100644
--- a/lua/lazy/core/handler/init.lua
+++ b/lua/lazy/core/handler/init.lua
@@ -39,6 +39,10 @@ end
 
 ---@param plugin LazyPlugin
 function M.disable(plugin)
+  if not plugin._.handlers_enabled then
+    return
+  end
+  plugin._.handlers_enabled = false
   for type, handler in pairs(M.handlers) do
     if plugin[type] then
       handler:del(plugin)
@@ -49,11 +53,15 @@ end
 ---@param plugin LazyPlugin
 function M.enable(plugin)
   if not plugin._.loaded then
+    if plugin._.handlers_enabled then
+      return
+    end
     for type, handler in pairs(M.handlers) do
       if plugin[type] then
         handler:add(plugin)
       end
     end
+    plugin._.handlers_enabled = true
   end
 end
 
@@ -80,10 +88,11 @@ function M:_del(_value) end
 
 ---@param plugin LazyPlugin
 function M:values(plugin)
+  local Plugin = require("lazy.core.plugin")
   ---@type table<string,any>
   local values = {}
   ---@diagnostic disable-next-line: no-unknown
-  for _, value in ipairs(plugin[self.type] or {}) do
+  for _, value in ipairs(Plugin.values(plugin, self.type, true)) do
     values[value] = value
   end
   return values
diff --git a/lua/lazy/core/handler/keys.lua b/lua/lazy/core/handler/keys.lua
index 9a87128..a7f7f68 100644
--- a/lua/lazy/core/handler/keys.lua
+++ b/lua/lazy/core/handler/keys.lua
@@ -52,7 +52,8 @@ end
 
 ---@param plugin LazyPlugin
 function M:values(plugin)
-  return M.resolve(plugin.keys)
+  local Plugin = require("lazy.core.plugin")
+  return M.resolve(Plugin.values(plugin, "keys", true))
 end
 
 ---@param spec? (string|LazyKeysSpec)[]
diff --git a/lua/lazy/core/plugin.lua b/lua/lazy/core/plugin.lua
index a51806e..9c36f71 100644
--- a/lua/lazy/core/plugin.lua
+++ b/lua/lazy/core/plugin.lua
@@ -42,15 +42,6 @@ end
 function Spec:parse(spec)
   self:normalize(spec)
   self:fix_disabled()
-
-  -- calculate handlers
-  for _, plugin in pairs(self.plugins) do
-    for _, handler in pairs(Handler.types) do
-      if plugin[handler] then
-        plugin[handler] = M.values(plugin, handler, true)
-      end
-    end
-  end
 end
 
 -- PERF: optimized code to get package name without using lua patterns
@@ -609,8 +600,26 @@ end
 ---@param prop string
 ---@param is_list? boolean
 function M.values(plugin, prop, is_list)
+  if not plugin[prop] then
+    return {}
+  end
+  plugin._.values = plugin._.values or {}
+  local key = prop .. (is_list and "_list" or "")
+  if plugin._.values[key] == nil then
+    plugin[prop] = M._values(plugin, prop, is_list)
+    plugin._.values[key] = true
+  end
+  return plugin[prop] or {}
+end
+
+-- Merges super values or runs the values function to override values or return new ones
+-- Used for opts, cmd, event, ft and keys
+---@param plugin LazyPlugin
+---@param prop string
+---@param is_list? boolean
+function M._values(plugin, prop, is_list)
   ---@type table
-  local ret = plugin._.super and M.values(plugin._.super, prop, is_list) or {}
+  local ret = plugin._.super and M._values(plugin._.super, prop, is_list) or {}
   local values = rawget(plugin, prop)
 
   if not values then
diff --git a/lua/lazy/types.lua b/lua/lazy/types.lua
index dcbcf18..346d8e4 100644
--- a/lua/lazy/types.lua
+++ b/lua/lazy/types.lua
@@ -20,6 +20,8 @@
 ---@field module? string
 ---@field dir? string Explicit dir or dev set for this plugin
 ---@field rtp_loaded? boolean
+---@field values? table<string,boolean>
+---@field handlers_enabled? boolean
 
 ---@alias PluginOpts table|fun(self:LazyPlugin, opts:table):table?
 
diff --git a/lua/lazy/view/render.lua b/lua/lazy/view/render.lua
index b5d83a0..df37b74 100644
--- a/lua/lazy/view/render.lua
+++ b/lua/lazy/view/render.lua
@@ -415,7 +415,7 @@ function M:plugin(plugin)
   else
     self:append(" ")
     local reason = {}
-    if plugin._.kind ~= "disabled" then
+    if plugin._.kind ~= "disabled" and plugin._.handlers_enabled then
       for handler in pairs(Handler.types) do
         if plugin[handler] then
           local values = Handler.handlers[handler]:values(plugin)
@@ -542,17 +542,19 @@ function M:details(plugin)
     end
   end)
 
-  for handler in pairs(Handler.types) do
-    if plugin[handler] then
-      table.insert(props, {
-        handler,
-        function()
-          for _, value in ipairs(plugin[handler]) do
-            self:reason({ [handler] = value })
-            self:append(" ")
-          end
-        end,
-      })
+  if plugin._.handlers_enabled then
+    for handler in pairs(Handler.types) do
+      if plugin[handler] then
+        table.insert(props, {
+          handler,
+          function()
+            for _, value in ipairs(Plugin.values(plugin, handler, true)) do
+              self:reason({ [handler] = value })
+              self:append(" ")
+            end
+          end,
+        })
+      end
     end
   end
   self:props(props, { indent = 6 })