Skip to main content

Use setopt for user options (defcustom)

Introduced in Emacs 29. Preferred for all defcustom variables in your init file.
Why: setopt runs the :set callback defined by defcustom and validates the value against its :type. Using setq on a defcustom variable bypasses both, which can silently break packages that depend on the setter to update internal state. Caveat: slower than setq because it goes through the Customize machinery. Don’t use it for regular variables in hot paths. Works in early-init.el: setopt is autoloaded (via loaddefs.el, which is part of the Emacs dump), so it is available during early-init.el. The first use triggers loading cus-edit.el slightly earlier than normal — negligible overhead for a few variables.

Use setq for regular variables

The standard way to set any variable. Use for internal/non-customizable variables.
Note: setq sets the current binding (lexical or dynamic). Inside a let, it modifies the local binding, not the global one.

Use setq-default for buffer-local defaults

Sets the default value for buffer-local variables. The value applies to buffers that haven’t set their own local value.

Use setq-local for buffer-local values

Sets a variable’s value in the current buffer only.

Use set when the variable name is computed

A function (not a special form) — evaluates its first argument to get the symbol to set.
Rarely needed in init files.

Quick decision table

Sources

Last modified on August 24, 2026