Drush: A Practical Operations Toolkit for Drupal Sites

Illustrated infographic summarizing: Drush: A Practical Operations Layer for Drupal Sites

By Greg Nowak. Drush is useful because it makes routine Drupal work repeatable. When an agency takes over a site or an operations lead asks whether a release is ready, the team needs more than a collection of commands: it needs to know which site it is touching, what will change, and how it will recover if something goes wrong.

Used with a short runbook, Drush helps answer those questions. It can establish a baseline, make staging and live targets explicit, and run a consistent deployment sequence. The commands below are a starting point for a team workflow, not a substitute for deciding who owns backups, approvals, and post-release checks.

Keep Drush with the Drupal project

For a Composer-managed site, install Drush as a project dependency and run the binary from the project root. That keeps its version recorded alongside the code in composer.lock. Check the official compatibility table before changing Drupal, PHP, and Drush together: Drush 14 requires PHP 8.3 or newer and is recommended for Drupal 11.3 and later; Drush 13 is recommended for Drupal 10.2 and later and also supports Drupal 11.

composer require drush/drush
vendor/bin/drush --version
vendor/bin/drush core:status

On an inherited site, check the existing Composer constraints before running composer require. Installing a new Drush major version during an unrelated maintenance task can turn a simple audit into an upgrade.

Start a takeover with facts

Before estimating an upgrade or removing a module, record the Drupal and Drush versions, PHP version, site URI, Drupal root, and configuration sync path. Then list enabled non-core modules. These checks help expose an unexpected runtime, an undocumented extension, or a command pointed at the wrong multisite.

vendor/bin/drush core:status --fields=drupal-version,drush-version,php-version,uri,root,config-sync
vendor/bin/drush pm:list --type=module --status=enabled --no-core
vendor/bin/drush pm:list --type=module --status=enabled --no-core --format=json

Use JSON when another tool needs the inventory; use the readable table for a review with a developer. Do not treat the list as an automatic removal plan. An enabled module may support a critical editorial task, depend on custom code, or be present for a migration that is still in progress. Review its purpose and ownership before changing it. When sharing status output, select the fields you need rather than exporting every available field, which can include database connection details.

Moment Drush check or action Team decision
Site takeover core:status and pm:list What is running, and what needs investigation?
Release preparation updatedb:status and config:status Are the expected database and configuration changes understood?
Environment check site:alias @self Does each command point to the intended site?
Deployment deploy Have code, backup, validation, and recovery steps been agreed?
Use command output to support an operational decision, rather than treating a successful command as the whole decision.

Make staging and live targets explicit

A shared alias file gives the team consistent names for its environments. Drush documents drush/sites/self.site.yml in the Composer project root. The root value is the Drupal web root, and each uri should match the address used to reach that site in a browser.

live:
  host: server.example.com
  user: deploy
  root: /var/www/example/web
  uri: https://www.example.com
stage:
  host: stage.example.com
  user: deploy
  root: /var/www/example/web
  uri: https://stage.example.com
vendor/bin/drush site:alias @self
vendor/bin/drush @stage core:status

Check the alias and the reported URI before running a command that changes data. This matters especially for multisite installations, where an incorrect URI can select a different site. Keep passwords and private keys out of the alias file; use the team’s SSH and secret-management arrangements for access. A shared alias also makes handover easier because the next operator can see how environments are addressed.

Make a release a sequence, not a single command

After the intended code has been deployed to staging, inspect pending updates and configuration differences. Resolve surprises there before scheduling production. For Drupal 10.3 and later, Drush’s deploy command runs database updates, configuration import, cache rebuild, and deploy hooks in order; on Drupal 11.2 and later, it also runs cache warming.

vendor/bin/drush @stage updatedb:status
vendor/bin/drush @stage config:status
vendor/bin/drush @stage deploy -y

Validate the journeys that matter to the site: for example, an editor publishing a page, a visitor submitting a form, or an integration receiving an event. Once the same code and configuration are ready for production, confirm the release window, a usable backup or recovery point, and who can make the go or stop decision. Then run the documented production step:

vendor/bin/drush @live deploy -y

deploy standardises Drupal’s update steps; it does not create a backup or reverse a database change. The recovery plan must say what to restore, who can restore it, and how the team will confirm the site works afterward. Keep a short record of the code revision, command outcome, and post-release checks so the next person does not have to reconstruct the release from terminal history.

Leave the next team an operating model

A useful handover fits on a page or two: supported Drupal, PHP, and Drush versions; environment aliases; deployment steps; backup ownership; recovery instructions; and the critical journeys to test. Give it a named owner and update it when the site changes. That modest discipline is often more valuable than another clever one-liner.

If your Drupal site depends on undocumented server knowledge or a release process only one person understands, talk to Greg about making its operations easier to inspect, run, and hand over.

Related on GrN.dk

Need help with this kind of work?

Talk to Greg about Drupal operations Get in touch with Greg.

Sources

Latest articles

Follow customer data through n8n, OpenAI and your CRM. Check who can access retained copies, what redaction hides and whether deletion works before scaling.

When checkout fails, your operations provider needs concrete evidence to work with. See how AI, dmesg and journalctl can gather the evidence into a useful incident ticket.

OpenAI’s hosted Evals platform is closing. Preserve your tests, validate replacement scoring and keep releases covered before the October and November 2026 deadlines.

Decide which AI-assisted pages to keep, improve, combine or remove. Check claims, page overlap and metadata, then put clear review controls into your CMS.

Use October to trial daily AI reorder recommendations before Black Friday. Get your Shopify data, lead times and budget in order before turning recommendations into purchases.

When an OpenAI request stalls, customers need an accurate status. Set sensible retry limits, preserve submissions, and make unresolved work visible.

I learned server operations by breaking my own servers. I want someone who stands next to me while I do it, then does it themselves the week after.

I am good at building and bad at calling. Here is who I want next to me, what is easiest to sell, and how we split it.

An AI assistant can prepare a refund, but a person should approve the exact payment and amount. Here is how to make that approval hold up through execution and retries.

AI can pull together onboarding tasks before a new hire’s first day. See how the manager approves specific access and how outstanding tasks are followed through.