vimtricks.wiki Concise Vim tricks, one at a time.

How do I schedule a Lua callback to run after a delay in Neovim for deferred or non-blocking initialization?

Answer

vim.defer_fn()

Explanation

vim.defer_fn(fn, timeout) schedules a Lua function to run after timeout milliseconds. It is the simplest way to defer work in Neovim without blocking the editor startup or the current event loop iteration.

How it works

  • vim.defer_fn(fn, timeout) takes a zero-argument function and a delay in milliseconds
  • The callback runs on the main Neovim event loop after the timeout expires
  • It is backed by vim.uv.new_timer() internally but handles cleanup automatically — no need to call timer:close()
  • Passing 0 as the timeout defers to the next event loop iteration without any real delay

Example

Deferring a notification until after startup completes:

vim.defer_fn(function()
  vim.notify('Neovim is ready!', vim.log.levels.INFO)
end, 200)

Delay a heavy autocmd setup so it doesn't slow startup:

vim.defer_fn(function()
  require('my-heavy-plugin').setup()
end, 0)  -- next event loop tick

Tips

  • For repeating timers or precise control, use vim.uv.new_timer() instead
  • vim.defer_fn does not return a cancellable handle — use vim.uv.new_timer() if you need to cancel before firing
  • Useful in VimEnter callbacks to avoid blocking the initial render

Next

How do I enable matchit so % jumps between if/else/end style pairs?