Choosing Neovim’s Built-in LSP vs External Plugins
Decision guide comparing Neovim’s built-in LSP client with external plugin stacks, including a minimal Lua validation example.
13 May 2026, 18:38 UTC

Problem and takeaway
You need language support in Neovim without spending time configuring a full plugin stack. The useful takeaway: Neovim ≥ 0.5 with Lua includes a built-in LSP client that starts quickly and works out-of-the-box for basic diagnostics, completion, and goto-definition. If you need rich fuzzy completion, snippets, or advanced code actions, an external plugin such as nvim-lspconfig plus nvim-cmp gives you that UI at the cost of extra bundle size and a Node.js dependency.
Decision and constraints
Before adding any code, check two constraints:
- Neovim version: run
nvim --versionand confirm+luaand+client-serverfeatures are listed. Older releases (< 0.5) lack the built-in client. - Lua availability: the built-in client is driven from Lua; if your Neovim was compiled without
+luayou must rebuild or use Vimscript fallbacks.
If both are present you can enable the built-in client immediately; otherwise you will need the external stack.
Comparison table
| Feature | Built-in LSP client | External plugins (nvim-lspconfig + nvim-cmp) |
|---|---|---|
| Startup latency | Low – client starts with Neovim, no extra process launch | Higher – each language server starts on demand; plugin loading adds a few milliseconds |
| Completion UI | Minimal – default completion list, no fuzzy matching | Rich – fuzzy matching, icon picker, snippet insertion via nvim-cmp |
| Snippet support | None built-in | Yes – via nvim-cmp source snippets |
| Lifecycle management | Neovim starts/stops the language server automatically | Plugins manage startup, shutdown, and per-language configuration |
| Configuration effort | Lua API calls or :LspStart command | Typical lspconfig setup tables plus cmp mapping |
| Bundle size | Core Neovim only | Adds lspconfig, cmp, and often Node.js runtime |
Trade-offs
Choose the built-in client when you want quick setup, low resource usage, and you are comfortable with basic completion lists. It stays in sync with core releases, so you rarely need to update a plugin. Pick the external stack when your workflow depends on fuzzy completion, snippet expansion, or you want fine-grained control over server arguments and auto-installation. Note that running two LSP clients simultaneously can cause conflicts; keep only one active per buffer.
Concrete implementation
Below is a minimal Lua snippet that activates the built-in LSP for Python files. Place it in ~/.config/nvim/init.lua:
-- Enable the built-in LSP client for Python
vim.api.nvim_create_autocmd('FileType', {
pattern = 'python',
callback = function()
-- Start the language server if it isn't already running
if not vim.lsp.get_active_clients({ bufnr = 0 })[1] then
vim.cmd('LspStart python')
end
end,
})
After saving the config, open a Python file and run :LspStart python (or let the autocmd do it). Diagnostics appear in the Messages area, and you can navigate errors with ]e and [e. To verify the client is active, run :LspInfo; the output lists the attached language server and its capabilities.
Verification steps
- Run
nvim --versionand confirm+luaand+client-serverappear. - Open a Python file.
- Execute
:LspStart python. - Check that diagnostics are shown with
:messagesor the sign column. - Run
:LspInfoto see the server name and supported features.
If you are using an external plugin stack, install nvim-lspconfig and nvim-cmp via your package manager, then consult their respective READMEs for server-specific setup. Compare completion latency and UI richness subjectively.
Limitations
The built-in client does not expose every language-server feature. Code actions, advanced type-hierarchy traversal, and some diagnostic codes may be missing or limited. Additionally, the client's completion source is not fuzzy-matched; you will not get the 'fuzzy-find-as-you-type' experience without nvim-cmp. Finally, if you have multiple language servers attached to the same buffer, Neovim may prompt you to choose one; keep your configuration focused on a single language per file type to avoid ambiguity.
Wrap-up
For most day-to-day editing, the built-in LSP client provides enough functionality to replace a full plugin stack while keeping Neovim lean. When you need richer completion, snippets, or programmatic control over server lifecycle, add nvim-lspconfig and nvim-cmp deliberately. The Lua snippet above gets you started with the built-in client in under a minute.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.