Skip to content
CH SCShop classcommerce · intermediate · ~60 min · 6 steps

How to update a Drupal Commerce store safely

Apply Drupal Commerce and payment-module updates with order data protected and the gateway proven, on a store where downtime is measured in dollars.

August 10, 2026 · by Dane Petersen

A store update is a regular Drupal update with the stakes turned up: the database holds real orders and real payments, and every minute checkout is broken has a dollar figure attached. This lesson layers the store rules on top of the standard sequence from applying a Drupal security update safely, so read that one first. You’ll also want to know how to run a test order through your checkout, because you’re about to run three of them. You’ll need drush, a staging copy, and access to your payment gateway’s dashboard.

Read the release notes for order-schema changes

Commerce releases sometimes change how orders, payments, or profiles are stored — the 3.x line has reworked the order admin more than once. On the release page at drupal.org/project/commerce/releases, look for update hooks, “data model” or field changes, and anything touching your payment modules. Then see what’s in play on your site:

drush pm:list --status=enabled | grep -i commerce
composer outdated "drupal/commerce*"

Payment modules (commerce_stripe, commerce_paypal, and friends) ride along with Commerce core updates more often than you’d expect. Update them together, deliberately — not one by surprise.

Take the backup by the store rules

The store rule: back up at a quiet moment, and know exactly when. Any order placed after this dump exists only in the live database, so if you ever restore, those orders need rescuing first.

drush sql:dump --gzip --result-file=../backups/pre-commerce-update-$(date +%Y-%m-%d-%H%M).sql

Timestamp to the minute, take the host snapshot too, and jot down the current order number from the admin. That number is your high-water mark.

Update a copy and run the database updates

On staging or a local copy in DDEV, with a fresh copy of the live database:

composer update "drupal/commerce" "drupal/commerce_*" --with-dependencies
drush updatedb -y
drush cache:rebuild

Watch updatedb closely — those are your order tables being migrated. An update hook that fails here on a copy is a Tuesday; the same failure on live is a very bad Tuesday.

Run a test order on the copy in gateway test mode

On the copy, edit your gateway at /admin/commerce/config/payment-gateways and set its mode to Test with your sandbox credentials (your copy should already be doing this — a staging site pointed at a live gateway takes real money). Then run the full trip: add to cart, checkout, pay with the gateway’s test card, confirm the order completes and a payment records on it. Load an old order from before the update too — schema changes occasionally render history strangely while new orders look fine.

Ship it in a quiet hour

Check your analytics for the slow hour, then deploy the proven code and put the site into maintenance mode just for the database updates:

drush state:set system.maintenance_mode 1
drush deploy
drush state:set system.maintenance_mode 0

That’s typically under a minute of downtime, taken on purpose, instead of customers checking out mid-migration.

Verify live with a small real order and a refund

Test mode proves the plumbing; only a real charge proves the gateway. Place the cheapest order in your catalog with a real card, confirm the payment lands in your gateway dashboard, then refund it from the order’s Payments tab — which conveniently verifies refunds work too. If the order completes, the money moves both ways, and yesterday’s orders still display right, the update is done. Note the version and date somewhere durable, and go enjoy the quiet hour you picked.

That's the lesson. Back to the shop for more — or if this is the chore your organization never gets to,that's literally what we're for.