"Updating Drupal core" sounds like a small task, and for a patch release, it usually is. But it's also the step where a rushed process can take a production site down for an afternoon. Here's a solid, repeatable process for keeping Drupal core current without drama.
Know what kind of update you're doing
Drupal core uses semantic versioning: major.minor.patch. A patch release (say, 11.2.3 to 11.2.4) is safe by design — no new features, no breaking changes, just bug and security fixes. A minor release (11.2.x to 11.3.0) can add new features and deprecate old APIs, but shouldn't break backward compatibility for public APIs. A major release (10.x to 11.x) is where breaking changes are allowed, and deprecated code from the previous major gets removed entirely.
That distinction matters because it tells you how much testing to budget. Patch updates can often go out with a quick smoke test. Minor updates deserve a proper check of your contributed modules. Major updates need the full process (see the companion piece on Drupal 10 to 11 for that).
This post covers patch and minor core updates — the routine maintenance every Drupal site should be doing monthly.
Step 1: Back up first, no exceptions
Before touching anything on production:
drush archive:dump
This bundles your code, files, and database into a single archive. If you're on a hosting platform with its own backup/snapshot tooling, use that instead — the point is having a known-good rollback point.
Step 2: Check what's actually outdated
composer outdated "drupal/*"
This lists every Drupal package with a newer version available, so you know exactly what you're about to update rather than updating blind.
Step 3: Put the site in maintenance mode
drush state:set system.maintenance_mode 1
drush cache:rebuild
Not strictly required for every update, but recommended for anything beyond a trivial patch, especially on a busy site.
Step 4: Update core with Composer
The standard command, which works whether you're on drupal/core or drupal/core-recommended:
composer update "drupal/core-*" --with-all-dependencies
If you only want the latest patch within your current minor version (not the newest minor), pin the constraint accordingly in composer.json first, or add --with= flags to lock specific packages to a version range.
Step 5: Run database updates and rebuild caches
drush updatedb
drush cache:rebuild
updatedb runs any pending update hooks from core or contributed modules — schema changes that need to happen alongside the code update. Don't skip this; a code update without a corresponding database update is a common source of "why is this suddenly broken" bugs.
Step 6: Export configuration changes
If you're using configuration management (and you should be):
drush config:export --diff
Some core updates introduce new default configuration values or restructure existing config. Reviewing the diff before committing it is worth the extra thirty seconds.
Step 7: Turn maintenance mode back off and verify
drush state:set system.maintenance_mode 0
drush cache:rebuild
Then actually look at the site. Check the Status Report page under Reports for new errors or warnings. If Database Logging is enabled, click around a bit and check the recent log messages. Test as an anonymous, logged-out visitor too — not just as an admin.
Step 8: Commit the lock file
composer.lock is what guarantees your production deploy installs exactly the same package versions you just tested locally. Commit it, and on production run:
composer install --no-dev
rather than composer update — you want to install exactly what's in the lock file, not re-resolve dependencies on a live server.
A note on minor version jumps
When you're updating across a minor version (say 11.2 to 11.3), read the release notes first. Minor releases can deprecate contributed module APIs, and some modules or themes may need their own update to stay compatible. Patch releases shouldn't require this, which is exactly why they're safer to apply quickly.
Keeping core current isn't glamorous work, but treating it as a routine, scripted process — rather than a special event — is what keeps a Drupal site both secure and boring in the best possible way.