← blog blog / neovim-vim-pack-vs-lazy-nvim.md

Neovim 0.12's Built-in Plugin Manager — Should You Ditch lazy.nvim?

Neovim 0.12 shipped vim.pack, a built-in plugin manager. I've been running lazy.nvim for two years — here's whether it's actually worth migrating.

Neovim 0.12's Built-in Plugin Manager — Should You Ditch lazy.nvim?

Neovim 0.12 shipped a built-in plugin manager. I’ve been running lazy.nvim for two years. Here’s my honest take on whether it’s worth switching.

What vim.pack Actually Is

vim.pack is part of Neovim core — written in Lua, maintained by the Neovim team, zero external dependencies. The API is minimal:

-- shorthand (GitHub)
vim.pack.add("nvim-lua/plenary.nvim")

-- table spec
vim.pack.add({
  "nvim-treesitter/nvim-treesitter",
  type = "opt",  -- load manually with :packadd
})

Versions are locked in $XDG_CONFIG_HOME/nvim/nvim-pack-lock.json. :Pack install syncs, :Pack update pulls new versions. That’s basically the full API surface.

The start/opt Thing

Plugins are either start (loaded at startup automatically) or opt (you call :packadd pluginname yourself). This distinction isn’t new — it’s the same packpath split Vim has had forever. vim.pack just wraps it with a cleaner Lua API and an actual lockfile.

opt plugins are the closest thing to lazy loading you get here. But that’s the problem.

The Deal-Breaker

vim.pack has no event/filetype/command-based lazy loading. None. You either load at startup or you manually call :packadd in your config yourself.

lazy.nvim’s event = "BufReadPost", ft = "typescript", cmd = "Telescope" — that whole system is what keeps a 30+ plugin config snappy. My config loads in ~60ms. Without lazy loading, it’d be pushing 200ms+.

ApproachStartup (~30 plugins)
lazy.nvim (event/ft/cmd)~55–70ms
vim.pack (start only)~180–250ms

If startup time matters to you — and if you’ve spent any time optimizing your config, it does — this is the blocker.

What It IS Good For

That said, I’ll give it credit where it’s due. vim.pack makes sense if you’re:

  • Starting a fresh config and don’t want to think about plugin manager churn (Packer → lazy.nvim → now vim.pack?)
  • Running a minimal config, fewer than 15 plugins
  • Distributing a config that should bootstrap with zero setup code

The lockfile works, the API is clean, and vim.pack.add("user/repo") reads like a real dependency declaration — not boilerplate.

Before/After

Three plugins converted from lazy.nvim to vim.pack:

-- lazy.nvim
{ "nvim-treesitter/nvim-treesitter", event = "BufReadPost" },
{ "nvim-telescope/telescope.nvim", cmd = "Telescope",
  dependencies = { "nvim-lua/plenary.nvim" } },
{ "tpope/vim-surround" },
-- vim.pack
vim.pack.add("nvim-lua/plenary.nvim")
vim.pack.add("nvim-treesitter/nvim-treesitter")
vim.pack.add("nvim-telescope/telescope.nvim")
vim.pack.add("tpope/vim-surround")

Cleaner, kinda. But notice what’s gone — event = "BufReadPost" and cmd = "Telescope" just disappear. Everything loads at startup now.

My Take

Don’t migrate. If you’ve got a working lazy.nvim config — even a messy one — the only thing you’d gain is removing a bootstrapping dependency in exchange for slower startups and less control. That’s a bad trade.

I’d try vim.pack if I were starting fresh today, purely to avoid the migration fatigue saga. But mid-config? Not worth it. The lazy loading alone earns lazy.nvim its keep. And if you’re wiring in AI plugins on top of all this, you really don’t want the startup hit.

Maybe revisit when vim.pack gets lazy loading — which feels inevitable — but that’s not today.

Thanks for reading!

I write about frontend craft, React, TypeScript, and the web. Found this useful? Let me know.

@samuellawrentz →

$ echo "enjoyed this post?" · subscribe via rss ↗

$ git log --oneline --grep="neovim"

More articles

cd ../blog →
  1. c7b93aa LazyVim: The Neovim Distro I Wish I'd Started With

    Apr 09, 2026 3 min read tag: neovimtag: vim

    LazyVim: The Neovim Distro I Wish I'd Started With
  2. b50fa60 nvim-treesitter Was Archived. Here's What You Actually Need to Do.

    Apr 13, 2026 3 min read tag: neovimtag: vim

    nvim-treesitter Was Archived. Here's What You Actually Need to Do.
  3. 270b014 avante.nvim vs CodeCompanion - AI Inside Neovim in 2026

    Mar 26, 2026 3 min read tag: neovimtag: ai

    avante.nvim vs CodeCompanion - AI Inside Neovim in 2026
  4. dc7792e My Neovim Config - Opinionated, Minimal, and Actually Usable

    Mar 15, 2026 5 min read tag: neovimtag: vim

    My Neovim Config - Opinionated, Minimal, and Actually Usable

$ giscus --load ./comments

00:00

This helps me increase the session time of my site. Thank you!

Can you stay a bit longer?