Why Senior Developers Are Moving to Neovim in 2024
TL;DR — Neovim 0.9.5 ships with built-in LSP, Treesitter, and a mature Lua API. Senior devs aren’t switching for vibes, they’re switching because the editor finally matches the way experienced engineers actually think. The plugin ecosystem (lazy.nvim, telescope, mason) closed the last gaps with VS Code in 2023.
I’ve spent the better part of a decade in JetBrains IDEs and VS Code. Last year I moved my daily backend work to Neovim, and I’m not the only one. Walk into any infra-heavy team in 2024 and you’ll find a non-trivial slice of the senior engineers running nvim in a tmux pane.
This isn’t nostalgia. The 0.7 → 0.9 release cycle changed the editor in concrete ways, and the plugin ecosystem caught up faster than most people expected. If you bounced off Neovim in 2021, the experience in April 2024 is genuinely different.
What follows is a sober look at why. I’ll skip the religious war and focus on what’s measurably better, where it still hurts, and who shouldn’t bother switching.
The Editor Finally Has First-Class Tooling
The single biggest change is that Neovim now ships features that previously required a Frankenstein stack of plugins. Built-in LSP arrived in 0.5 and matured through 0.9. Treesitter integration moved from experimental to default for most language parsers. The Lua API replaced Vimscript for any configuration that touches the editor’s internals.
In practice, that means a working setup looks like this in 2024:
-- init.lua
vim.lsp.start({
name = 'gopls',
cmd = { 'gopls' },
root_dir = vim.fs.dirname(vim.fs.find({ 'go.mod' }, { upward = true })[1]),
})
vim.api.nvim_create_autocmd('LspAttach', {
callback = function(args)
local bufnr = args.buf
vim.keymap.set('n', 'gd', vim.lsp.buf.definition, { buffer = bufnr })
vim.keymap.set('n', 'gr', vim.lsp.buf.references, { buffer = bufnr })
vim.keymap.set('n', 'K', vim.lsp.buf.hover, { buffer = bufnr })
end,
})
That’s the entire LSP wiring for Go. No external plugin required. You can run Neovim with zero plugins and still get go-to-definition, hover, and rename, provided you have a language server installed.
Most people layer nvim-lspconfig, mason.nvim, and a completion engine on top, and that’s fine. The point is that the foundation is solid enough that the plugins are conveniences, not load-bearing dependencies.
Treesitter Changed What “Syntax” Means
The other foundational shift is Treesitter. Old Vim syntax highlighting was a regex tower. Treesitter parses your code into an actual AST and queries it. That sounds academic until you realize what it enables: structural selection, accurate folding, language-aware indentation, and the kind of refactoring tools that used to live only in JetBrains.
I covered this in detail in Treesitter for real refactoring, but the short version is that nvim-treesitter with text objects gives you operations like “delete this function” or “swap these two arguments” that work across 40+ languages with the same keybindings.
The Plugin Ecosystem Stopped Being Fragile
If you tried Neovim in 2019, your plugin manager was probably vim-plug and your config was a mix of Vimscript and Lua glued together with apologies. Updating plugins broke things weekly.
That’s gone. lazy.nvim arrived in late 2022 and basically settled the plugin manager debate. It does lazy loading correctly (which means startup times under 50ms even with 60+ plugins), it locks versions in a lazy-lock.json, and the spec format is declarative enough that you can read someone else’s config and immediately know what loads when.
-- A real lazy.nvim spec
{
'nvim-telescope/telescope.nvim',
tag = '0.1.5',
dependencies = { 'nvim-lua/plenary.nvim' },
cmd = 'Telescope',
keys = {
{ '<leader>ff', '<cmd>Telescope find_files<cr>' },
{ '<leader>fg', '<cmd>Telescope live_grep<cr>' },
},
}
The cmd and keys fields mean telescope doesn’t load until you actually use it. Multiply that across your config and startup stays fast no matter how much you pile on.
Mason solved the other half of the problem, which is installing language servers, formatters, and DAP adapters. :MasonInstall gopls pyright stylua is now the answer to “how do I set up a language.” It’s not as integrated as code --install-extension, but it’s close, and it’s cross-platform in a way that homebrew/apt scripts never were.
What Senior Devs Actually Get Out of It
The selling point isn’t speed for its own sake. It’s that the editor stops being a thing you operate and becomes a thing you compose. A few examples from my daily work.
Buffer-local config. When I’m reviewing a 4000-line legacy file, I can set vim.opt_local.foldmethod = 'indent' and fold everything down without affecting other buffers. That’s a one-liner. In VS Code, this is a setting hunt.
Composable text objects. ci( changes inside parentheses. dap deletes around a paragraph. With Treesitter text objects, vaf selects an entire function. These compose. ci" works inside strings; daf deletes a whole function. Once it’s in muscle memory, you stop thinking about cursor position.
Real scripting. Need a custom command that runs go test for the function under the cursor? It’s 15 lines of Lua. Need it to send output to a floating window? Another 10. The editor is a Lua runtime, not a configuration target.
vim.api.nvim_create_user_command('GoTestFunc', function()
local node = vim.treesitter.get_node()
while node and node:type() ~= 'function_declaration' do
node = node:parent()
end
if not node then return vim.notify('not in a function', vim.log.levels.WARN) end
local name_node = node:field('name')[1]
local name = vim.treesitter.get_node_text(name_node, 0)
vim.cmd('split | terminal go test -run ^' .. name .. '$ -v ./...')
end, {})
That’s the kind of thing that would be a VS Code extension. In Neovim it’s a snippet you paste into your config.
Where It Still Hurts
I owe you the downsides. They’re real.
The remote dev story is weak. VS Code’s Remote-SSH and Dev Containers extensions are genuinely excellent and Neovim has nothing equivalent. You can run nvim over SSH (it’s just a TUI), but if your workflow depends on transparent container or WSL integration, you’ll feel the gap.
Debugging is rougher than VS Code. nvim-dap works, and I use it for Go and Python daily, but the UX requires more configuration than clicking “Run and Debug.” If you live in a debugger, factor that in.
Onboarding is slow. The “30 days to productive” claim is roughly accurate, but those 30 days are non-trivial. If you’re under deadline pressure, this isn’t the week to switch.
GUI features (inline images, notebook cells, full-fidelity markdown previews) are weaker. There are workarounds, but they’re workarounds.
Common Pitfalls
A few traps I see senior devs hit when they switch.
- Copying someone else’s
init.luawholesale. Don’t. Read it, understand what each plugin does, and build your own. You’ll thank yourself when something breaks at 2 AM. - Installing too many plugins on day one. A working Neovim setup is maybe 15 plugins. Resist the LunarVim/AstroNvim “starter” temptation if you want to actually learn the editor.
- Skipping
:Tutor. Even with years of Vim experience, the built-in tutorial covers Neovim-specific behavior worth knowing. - Ignoring the LSP logs. When LSP misbehaves,
:LspLogtells you exactly what went wrong. Most “neovim is broken” complaints are actually misconfigured language servers. - Editing inside the wrong runtime path. If you copy a plugin’s file into
~/.local/share/nvim/lazy/to “fix” something, your fix gets overwritten on next update. Use the plugin’s config hooks instead.
Wrapping Up
Neovim in 2024 isn’t a hair-shirt editor for purists. It’s a serious tool that competes head-to-head with VS Code for backend work, infra work, and any environment where you spend more time reading code than scrolling through it. The 0.9.5 release plus the modern plugin ecosystem closed the gap that existed even two years ago.
If you’ve been curious, this is the right year to try. Give yourself 30 days, don’t copy a mega-config, and start from a minimal init.lua. The official Neovim documentation is excellent, and the neovim GitHub repository tracks the project transparently if you want to follow where it’s going.
For me, the switch stuck because the editor stopped getting in the way. That’s the whole pitch.