To stop core auto-updates, add define( 'WP_AUTO_UPDATE_CORE', false ); to wp-config.php above the /* That's all, stop editing! */ line. To stop plugin and theme auto-updates as well, you need something else: that constant has no effect on them at all.
That is the part most guides for this query get wrong, and it is worth 30 seconds before you paste anything. WordPress does not have one auto-update switch.
It has four update types (core, plugins, themes, translations), core splits into three branches of its own, and each layer is decided by a different constant, option or filter.
The five things you might mean by "automatic updates"
Here is what the updater actually decides, each independently:
1. Core development versions. Only relevant if you run a nightly or beta build. Site option auto_update_core_dev, default enabled.
2. Core minor releases. The 6.9.1-style security and maintenance releases, site option auto_update_core_minor, default enabled. This is the one to think hardest about before disabling.
3. Core major releases. Site option auto_update_core_major, default unset, which means off. New installs on WordPress 5.6 and later opt in; older sites did not get switched on behind your back.
4. Plugins and themes. Off by default, per item, stored in the auto_update_plugins and auto_update_themes site options by the toggles added to the Plugins and Themes screens in WordPress 5.5.
5. Translations. On by default. Almost nobody means this one, and almost every "disable everything" snippet kills it.
All five defaults are read in Core_Upgrader::should_update_to_version() and WP_Automatic_Updater::should_update() in current core (wordpress-develop trunk, read 2026-10-22).
The exact wp-config.php lines
Core only, leaving security releases on
define( 'WP_AUTO_UPDATE_CORE', 'minor' );
This is the setting most sites want. Major releases wait for you, minor releases still land.
All core updates off
define( 'WP_AUTO_UPDATE_CORE', false );
The accepted values are true, false, 'minor', 'beta', 'rc', 'development' and 'branch-development'. Anything else, including the string 'false' with quotes, falls through every branch and leaves the defaults in place.
Everything off, including plugins, themes and translations
define( 'AUTOMATIC_UPDATER_DISABLED', true );
This is the only constant that covers all four update types. It is checked in WP_Automatic_Updater::is_disabled(), which should_update() calls before it looks at anything else.
One side effect core documents in that same method: it also stops the update notification emails. You will not be told that 6.9.2 exists.
Everything off, plus installs and the file editors
define( 'DISALLOW_FILE_MODS', true );
This is the blunt one, and it is the right choice on a deployed site where wp-content is in git. It blocks the updater, plugin and theme installs, and the built-in file editors, because wp_is_file_mod_allowed() gates all of them on this single constant (wp-includes/load.php line 1944, read 2026-10-22).
Why WP_AUTO_UPDATE_CORE does nothing to your plugins
Several of the top guides for this query say WP_AUTO_UPDATE_CORE covers core, themes and plugins. It does not.
Follow the code. should_update() branches on $type, and only the 'core' branch calls Core_Upgrader::should_update_to_version(), which is the only place WP_AUTO_UPDATE_CORE is read.
The 'plugin' and 'theme' branches never touch it. They read $item->autoupdate from the update offer and then the auto_update_plugins or auto_update_themes site option.
So if you set that constant to false and a plugin still updated itself overnight, nothing is broken. You turned off a different layer from the one that fired.
The precedence order, which nobody writes down
This matters because a filter and a constant can disagree, and people assume the constant wins. It does not.
Reading should_update() top to bottom, the order is:
DISALLOW_FILE_MODS, viawp_is_file_mod_allowed(). Nothing after this runs.AUTOMATIC_UPDATER_DISABLED, then theautomatic_updater_disabledfilter applied to its value. A filter returningfalsehere re-enables the updater even with the constant set totrue.- A version control check, covered below.
- The per-type decision:
WP_AUTO_UPDATE_COREand the core site options, or the per-item plugin and theme options. - The
auto_update_{$type}filter, last. Core's own comment on it reads "override any user-choice, but allow filters".
Step 5 is the one that bites. add_filter( 'auto_update_plugin', '__return_true' ); in a plugin or a must-use plugin overrides every toggle you clicked in the admin, and the Plugins screen will keep showing "Enable auto-updates" as if it were off.
If a site is auto-updating when you have told it not to, grep wp-content for auto_update_plugin and automatic_updater_disabled before you touch wp-config.php again. Must-use plugins are the usual hiding place, because they load before everything and are easy to forget.
Your auto-updates may already be off
If .git, .svn, .hg or .bzr exists anywhere in the WordPress directory or any directory above it, up to the filesystem root, the automatic updater disables itself.
That is WP_Automatic_Updater::is_vcs_checkout(), and the walk-up-to-root behaviour is the surprising part. A repository at /var/www switches off auto-updates for a WordPress install at /var/www/html/site, with no marker inside the install itself.
Worth checking before you debug a constant that was never the problem.
Doing it with WP-CLI instead
If you have shell access, this is faster and leaves a cleaner trail than editing the file by hand:
# core: majors wait, security releases still land
wp config set WP_AUTO_UPDATE_CORE minor
# everything off, including translations
wp config set AUTOMATIC_UPDATER_DISABLED true --raw
# plugins and themes, per item, matching the admin toggles
wp plugin auto-updates disable --all
wp theme auto-updates disable --all
# what is actually set right now
wp config get WP_AUTO_UPDATE_CORE
wp plugin auto-updates status
--raw matters on the second one. Without it you write the string 'true' instead of the boolean, and defined( 'AUTOMATIC_UPDATER_DISABLED' ) && AUTOMATIC_UPDATER_DISABLED is still truthy by accident, which works today and will confuse whoever reads the file next.
The --all flag on wp plugin auto-updates disable is documented on developer.wordpress.org (read 2026-10-22). WP-CLI is preinstalled on every SandyWP sandbox, so you can try all of this on a copy first: see SSH and SFTP access.
The honest answer: do not disable minor core updates
Minor WordPress releases are security releases. Turning them off means a disclosed vulnerability stays open on your site until a human remembers.
Almost every real reason people reach for this is actually one of three narrower problems:
"A plugin update broke the site once." That is an argument for testing plugin updates, not for stopping core security patches. Disable auto-updates for the one plugin that broke, and leave the rest alone.
"We deploy from git and updates cause conflicts." Use DISALLOW_FILE_MODS, not WP_AUTO_UPDATE_CORE. You want installs and the file editors gone too, and in a checkout the updater is already refusing to run.
"We need to approve every change." Then you need somewhere to approve it. That means a copy of the site you can apply the update to, which is a different piece of work from switching the updater off.
The thing to do instead of switching it off
Clone the site, run the update on the clone, look at the pages that matter, then let the real update happen.
That is the whole workflow, and it is what a sandbox is for. The SandyWP Cloner plugin copies a live site into a disposable sandbox without touching production, and the sandbox is where you break things instead.
With a copy in front of you, the update stops being a gamble you avoid and becomes a check you run. More on that in upgrade testing and how to test a plugin update without breaking your live site.
Keep minor core updates on. Hold majors, test them, then let them through.
Checking it worked
Do not trust the file, check what the updater reports. Tools then Site Health, Status tab, has a "Background updates" test that reports the constants, the filesystem writability check and the version control check together.
That is the fastest way to find out that a .git directory two levels up was the reason all along. More on reading that screen in WordPress Site Health.
From the shell, confirm what is actually defined rather than what you think you wrote:
wp config get WP_AUTO_UPDATE_CORE
wp config get AUTOMATIC_UPDATER_DISABLED
wp config get DISALLOW_FILE_MODS
wp plugin auto-updates status
If you want to see the whole decision tree without risking anything, do it on a throwaway install: set the constant, drop a filter in a must-use plugin, and watch which one wins.
